@@ -8,8 +8,8 @@ use std::{
8
8
use crate :: line_index:: { LineEndings , LineIndex , OffsetEncoding } ;
9
9
use hir:: Name ;
10
10
use ide:: {
11
- LineCol , MonikerDescriptorKind , MonikerResult , StaticIndex , StaticIndexedFile , TextRange ,
12
- TokenId ,
11
+ LineCol , MonikerDescriptorKind , StaticIndex , StaticIndexedFile , TextRange , TokenId ,
12
+ TokenStaticData ,
13
13
} ;
14
14
use ide_db:: LineIndexDatabase ;
15
15
use project_model:: { CargoConfig , ProjectManifest , ProjectWorkspace } ;
@@ -75,7 +75,7 @@ impl flags::Scip {
75
75
let mut symbols_emitted: HashSet < TokenId > = HashSet :: default ( ) ;
76
76
let mut tokens_to_symbol: HashMap < TokenId , String > = HashMap :: new ( ) ;
77
77
78
- for file in si. files {
78
+ for StaticIndexedFile { file_id , tokens , .. } in si. files {
79
79
let mut local_count = 0 ;
80
80
let mut new_local_symbol = || {
81
81
let new_symbol = scip:: types:: Symbol :: new_local ( local_count) ;
@@ -84,7 +84,6 @@ impl flags::Scip {
84
84
new_symbol
85
85
} ;
86
86
87
- let StaticIndexedFile { file_id, tokens, .. } = file;
88
87
let relative_path = match get_relative_filepath ( & vfs, & rootpath, file_id) {
89
88
Some ( relative_path) => relative_path,
90
89
None => continue ,
@@ -107,28 +106,20 @@ impl flags::Scip {
107
106
108
107
let mut occurrence = scip_types:: Occurrence :: default ( ) ;
109
108
occurrence. range = text_range_to_scip_range ( & line_index, range) ;
110
- occurrence. symbol = match tokens_to_symbol. get ( & id) {
111
- Some ( symbol) => symbol. clone ( ) ,
112
- None => {
113
- let symbol = match & token. moniker {
114
- Some ( moniker) => moniker_to_symbol ( & moniker) ,
115
- None => new_local_symbol ( ) ,
116
- } ;
117
-
118
- let symbol = scip:: symbol:: format_symbol ( symbol) ;
119
- tokens_to_symbol. insert ( id, symbol. clone ( ) ) ;
120
- symbol
121
- }
122
- } ;
109
+ occurrence. symbol = tokens_to_symbol
110
+ . entry ( id)
111
+ . or_insert_with ( || {
112
+ let symbol = token_to_symbol ( & token) . unwrap_or_else ( & mut new_local_symbol) ;
113
+ scip:: symbol:: format_symbol ( symbol)
114
+ } )
115
+ . clone ( ) ;
123
116
124
117
if let Some ( def) = token. definition {
125
118
if def. range == range {
126
119
occurrence. symbol_roles |= scip_types:: SymbolRole :: Definition as i32 ;
127
120
}
128
121
129
- if !symbols_emitted. contains ( & id) {
130
- symbols_emitted. insert ( id) ;
131
-
122
+ if symbols_emitted. insert ( id) {
132
123
let mut symbol_info = scip_types:: SymbolInformation :: default ( ) ;
133
124
symbol_info. symbol = occurrence. symbol . clone ( ) ;
134
125
if let Some ( hover) = & token. hover {
@@ -207,9 +198,11 @@ fn new_descriptor(name: Name, suffix: scip_types::descriptor::Suffix) -> scip_ty
207
198
///
208
199
/// Only returns a Symbol when it's a non-local symbol.
209
200
/// So if the visibility isn't outside of a document, then it will return None
210
- fn moniker_to_symbol ( moniker : & MonikerResult ) -> scip_types:: Symbol {
201
+ fn token_to_symbol ( token : & TokenStaticData ) -> Option < scip_types:: Symbol > {
211
202
use scip_types:: descriptor:: Suffix :: * ;
212
203
204
+ let moniker = token. moniker . as_ref ( ) ?;
205
+
213
206
let package_name = moniker. package_information . name . clone ( ) ;
214
207
let version = moniker. package_information . version . clone ( ) ;
215
208
let descriptors = moniker
@@ -233,7 +226,7 @@ fn moniker_to_symbol(moniker: &MonikerResult) -> scip_types::Symbol {
233
226
} )
234
227
. collect ( ) ;
235
228
236
- scip_types:: Symbol {
229
+ Some ( scip_types:: Symbol {
237
230
scheme : "rust-analyzer" . into ( ) ,
238
231
package : Some ( scip_types:: Package {
239
232
manager : "cargo" . to_string ( ) ,
@@ -244,19 +237,15 @@ fn moniker_to_symbol(moniker: &MonikerResult) -> scip_types::Symbol {
244
237
. into ( ) ,
245
238
descriptors,
246
239
..Default :: default ( )
247
- }
240
+ } )
248
241
}
249
242
250
243
#[ cfg( test) ]
251
244
mod test {
252
245
use super :: * ;
253
- use hir:: Semantics ;
254
- use ide:: { AnalysisHost , FilePosition } ;
255
- use ide_db:: defs:: IdentClass ;
256
- use ide_db:: { base_db:: fixture:: ChangeFixture , helpers:: pick_best_token} ;
246
+ use ide:: { AnalysisHost , FilePosition , StaticIndex , TextSize } ;
247
+ use ide_db:: base_db:: fixture:: ChangeFixture ;
257
248
use scip:: symbol:: format_symbol;
258
- use syntax:: SyntaxKind :: * ;
259
- use syntax:: { AstNode , T } ;
260
249
261
250
fn position ( ra_fixture : & str ) -> ( AnalysisHost , FilePosition ) {
262
251
let mut host = AnalysisHost :: default ( ) ;
@@ -273,53 +262,33 @@ mod test {
273
262
fn check_symbol ( ra_fixture : & str , expected : & str ) {
274
263
let ( host, position) = position ( ra_fixture) ;
275
264
265
+ let analysis = host. analysis ( ) ;
266
+ let si = StaticIndex :: compute ( & analysis) ;
267
+
276
268
let FilePosition { file_id, offset } = position;
277
269
278
- let db = host. raw_database ( ) ;
279
- let sema = & Semantics :: new ( db) ;
280
- let file = sema. parse ( file_id) . syntax ( ) . clone ( ) ;
281
- let original_token = pick_best_token ( file. token_at_offset ( offset) , |kind| match kind {
282
- IDENT
283
- | INT_NUMBER
284
- | LIFETIME_IDENT
285
- | T ! [ self ]
286
- | T ! [ super ]
287
- | T ! [ crate ]
288
- | T ! [ Self ]
289
- | COMMENT => 2 ,
290
- kind if kind. is_trivia ( ) => 0 ,
291
- _ => 1 ,
292
- } )
293
- . expect ( "OK OK" ) ;
294
-
295
- let navs = sema
296
- . descend_into_macros ( original_token. clone ( ) )
297
- . into_iter ( )
298
- . filter_map ( |token| {
299
- IdentClass :: classify_token ( sema, & token) . map ( IdentClass :: definitions) . map ( |it| {
300
- it. into_iter ( ) . flat_map ( |def| {
301
- let module = def. module ( db) . unwrap ( ) ;
302
- let current_crate = module. krate ( ) ;
303
-
304
- match MonikerResult :: from_def ( sema. db , def, current_crate) {
305
- Some ( moniker_result) => Some ( moniker_to_symbol ( & moniker_result) ) ,
306
- None => None ,
307
- }
308
- } )
309
- } )
310
- } )
311
- . flatten ( )
312
- . collect :: < Vec < _ > > ( ) ;
270
+ let mut found_symbol = None ;
271
+ for file in & si. files {
272
+ if file. file_id != file_id {
273
+ continue ;
274
+ }
275
+ for & ( range, id) in & file. tokens {
276
+ if range. contains ( offset - TextSize :: from ( 1 ) ) {
277
+ let token = si. tokens . get ( id) . unwrap ( ) ;
278
+ found_symbol = token_to_symbol ( token) ;
279
+ break ;
280
+ }
281
+ }
282
+ }
313
283
314
284
if expected == "" {
315
- assert_eq ! ( 0 , navs . len ( ) , "must have no symbols {:?}" , navs ) ;
285
+ assert ! ( found_symbol . is_none ( ) , "must have no symbols {:?}" , found_symbol ) ;
316
286
return ;
317
287
}
318
288
319
- assert_eq ! ( 1 , navs. len( ) , "must have one symbol {:?}" , navs) ;
320
-
321
- let res = navs. get ( 0 ) . unwrap ( ) ;
322
- let formatted = format_symbol ( res. clone ( ) ) ;
289
+ assert ! ( found_symbol. is_some( ) , "must have one symbol {:?}" , found_symbol) ;
290
+ let res = found_symbol. unwrap ( ) ;
291
+ let formatted = format_symbol ( res) ;
323
292
assert_eq ! ( formatted, expected) ;
324
293
}
325
294
0 commit comments