Skip to content

Commit 1bf111e

Browse files
authored
rust: fix emiting escaped symbols (#169)
1 parent 7fe4420 commit 1bf111e

File tree

1 file changed

+61
-21
lines changed

1 file changed

+61
-21
lines changed

bindings/rust/src/symbol.rs

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -94,22 +94,25 @@ pub fn format_symbol_with(symbol: Symbol, options: SymbolFormatOptions) -> Strin
9494
.iter()
9595
.filter_map(|desc| {
9696
Some(match desc.suffix.enum_value() {
97-
Ok(val) => match val {
98-
descriptor::Suffix::Package | descriptor::Suffix::Namespace => {
99-
format!("{}/", desc.name)
97+
Ok(val) => {
98+
let name = escape_name(&desc.name);
99+
match val {
100+
descriptor::Suffix::Package | descriptor::Suffix::Namespace => {
101+
format!("{}/", name)
102+
}
103+
descriptor::Suffix::Type => format!("{}#", name),
104+
descriptor::Suffix::Term => format!("{}.", name),
105+
descriptor::Suffix::Method => {
106+
format!("{}({}).", name, desc.disambiguator)
107+
}
108+
descriptor::Suffix::TypeParameter => format!("[{}]", name),
109+
descriptor::Suffix::Parameter => format!("({})", name),
110+
descriptor::Suffix::Macro => format!("{}!", name),
111+
descriptor::Suffix::Meta => format!("{}:", name),
112+
descriptor::Suffix::Local => format!("{}", name),
113+
descriptor::Suffix::UnspecifiedSuffix => return None,
100114
}
101-
descriptor::Suffix::Type => format!("{}#", desc.name),
102-
descriptor::Suffix::Term => format!("{}.", desc.name),
103-
descriptor::Suffix::Method => {
104-
format!("{}({}).", desc.name, desc.disambiguator)
105-
}
106-
descriptor::Suffix::TypeParameter => format!("[{}]", desc.name),
107-
descriptor::Suffix::Parameter => format!("({})", desc.name),
108-
descriptor::Suffix::Macro => format!("{}!", desc.name),
109-
descriptor::Suffix::Meta => format!("{}:", desc.name),
110-
descriptor::Suffix::Local => format!("{}", desc.name),
111-
descriptor::Suffix::UnspecifiedSuffix => return None,
112-
},
115+
}
113116
Err(_) => return None,
114117
})
115118
})
@@ -121,6 +124,17 @@ pub fn format_symbol_with(symbol: Symbol, options: SymbolFormatOptions) -> Strin
121124
parts.join(" ")
122125
}
123126

127+
fn escape_name(name: &str) -> String {
128+
if name
129+
.chars()
130+
.all(|ch| ch == '_' || ch == '+' || ch == '-' || ch == '$' || ch.is_ascii_alphanumeric())
131+
{
132+
name.to_string()
133+
} else {
134+
format!("`{}`", name)
135+
}
136+
}
137+
124138
pub fn format_symbol(symbol: Symbol) -> String {
125139
format_symbol_with(symbol, SymbolFormatOptions::default())
126140
}
@@ -153,14 +167,26 @@ pub fn parse_symbol(symbol: &str) -> Result<Symbol, SymbolError> {
153167
));
154168
}
155169

170+
let package = crate::types::Package {
171+
manager: dot(parser.accept_space_escaped_identifier("package.manager")?),
172+
name: dot(parser.accept_space_escaped_identifier("package.name")?),
173+
version: dot(parser.accept_space_escaped_identifier("package.version")?),
174+
special_fields: SpecialFields::default(),
175+
};
176+
177+
// If all the package fields are empty, we can just say that package is None
178+
let package = match (
179+
package.manager.as_str(),
180+
package.name.as_str(),
181+
package.version.as_str(),
182+
) {
183+
("", "", "") => protobuf::MessageField::none(),
184+
_ => protobuf::MessageField::some(package),
185+
};
186+
156187
Ok(Symbol {
157188
scheme,
158-
package: protobuf::MessageField::some(crate::types::Package {
159-
manager: dot(parser.accept_space_escaped_identifier("package.manager")?),
160-
name: dot(parser.accept_space_escaped_identifier("package.name")?),
161-
version: dot(parser.accept_space_escaped_identifier("package.version")?),
162-
special_fields: SpecialFields::default(),
163-
}),
189+
package,
164190
descriptors: parser.accept_descriptors()?,
165191
special_fields: SpecialFields::default(),
166192
})
@@ -563,4 +589,18 @@ mod test {
563589
format_symbol(parse_symbol(input_symbol).expect("rust symbol"))
564590
)
565591
}
592+
593+
#[test]
594+
fn test_properly_escapes_identifiers() {
595+
let symbol_struct = Symbol {
596+
scheme: "scip-ctags".to_string(),
597+
package: None.into(),
598+
descriptors: vec![new_descriptor("foo=".to_string(), descriptor::Suffix::Term)],
599+
..Default::default()
600+
};
601+
let symbol = format_symbol(symbol_struct.clone());
602+
603+
assert_eq!(symbol, "scip-ctags . . . `foo=`.");
604+
assert_eq!(parse_symbol(&symbol).expect("to parse"), symbol_struct);
605+
}
566606
}

0 commit comments

Comments
 (0)