@@ -94,22 +94,25 @@ pub fn format_symbol_with(symbol: Symbol, options: SymbolFormatOptions) -> Strin
94
94
. iter ( )
95
95
. filter_map ( |desc| {
96
96
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 ,
100
114
}
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
+ }
113
116
Err ( _) => return None ,
114
117
} )
115
118
} )
@@ -121,6 +124,17 @@ pub fn format_symbol_with(symbol: Symbol, options: SymbolFormatOptions) -> Strin
121
124
parts. join ( " " )
122
125
}
123
126
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
+
124
138
pub fn format_symbol ( symbol : Symbol ) -> String {
125
139
format_symbol_with ( symbol, SymbolFormatOptions :: default ( ) )
126
140
}
@@ -153,14 +167,26 @@ pub fn parse_symbol(symbol: &str) -> Result<Symbol, SymbolError> {
153
167
) ) ;
154
168
}
155
169
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
+
156
187
Ok ( Symbol {
157
188
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,
164
190
descriptors : parser. accept_descriptors ( ) ?,
165
191
special_fields : SpecialFields :: default ( ) ,
166
192
} )
@@ -563,4 +589,18 @@ mod test {
563
589
format_symbol( parse_symbol( input_symbol) . expect( "rust symbol" ) )
564
590
)
565
591
}
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
+ }
566
606
}
0 commit comments