@@ -5,8 +5,7 @@ use crate::{
5
5
RangeInfo , TryToNav , UpmappingResult ,
6
6
} ;
7
7
use hir:: {
8
- AsAssocItem , AssocItem , DescendPreference , HirFileId , InFile , MacroFileIdExt , ModuleDef ,
9
- Semantics ,
8
+ AsAssocItem , AssocItem , DescendPreference , InFile , MacroFileIdExt , ModuleDef , Semantics ,
10
9
} ;
11
10
use ide_db:: {
12
11
base_db:: { AnchoredPath , FileLoader } ,
@@ -15,11 +14,12 @@ use ide_db::{
15
14
FileId , RootDatabase ,
16
15
} ;
17
16
use itertools:: Itertools ;
17
+ use span:: FileRange ;
18
18
use syntax:: {
19
- ast:: { self , HasLoopBody } ,
19
+ ast:: { self , HasLoopBody , Label } ,
20
20
match_ast, AstNode , AstToken ,
21
- SyntaxKind :: { self , * } ,
22
- SyntaxNode , SyntaxToken , TextRange , T ,
21
+ SyntaxKind :: * ,
22
+ SyntaxToken , TextRange , T ,
23
23
} ;
24
24
25
25
// Feature: Go to Definition
@@ -224,30 +224,28 @@ fn try_find_fn_or_closure(
224
224
) -> Option < Vec < NavigationTarget > > {
225
225
fn find_exit_point (
226
226
sema : & Semantics < ' _ , RootDatabase > ,
227
- file_id : HirFileId ,
228
- ancestors : impl Iterator < Item = SyntaxNode > ,
229
- cursor_token_kind : SyntaxKind ,
227
+ token : SyntaxToken ,
230
228
) -> Option < UpmappingResult < NavigationTarget > > {
231
229
let db = sema. db ;
232
230
233
- for anc in ancestors {
231
+ for anc in sema. token_ancestors_with_macros ( token. clone ( ) ) {
232
+ let file_id = sema. hir_file_for ( & anc) ;
234
233
match_ast ! {
235
234
match anc {
236
235
ast:: Fn ( fn_) => {
237
- let hir_fn: hir:: Function = sema. to_def( & fn_) ?;
238
- let nav = hir_fn. try_to_nav( db) ?;
239
-
236
+ let fn_: ast:: Fn = fn_;
237
+ let nav = sema. to_def( & fn_) ?. try_to_nav( db) ?;
240
238
// For async token, we navigate to itself, which triggers
241
239
// VSCode to find the references
242
- let focus_token = if matches!( cursor_token_kind , T ![ async ] ) {
240
+ let focus_token = if matches!( token . kind ( ) , T ![ async ] ) {
243
241
fn_. async_token( ) ?
244
242
} else {
245
243
fn_. fn_token( ) ?
246
244
} ;
247
- let focus_range = InFile :: new( file_id, focus_token. text_range( ) )
248
- . original_node_file_range_opt( db)
249
- . map( |( frange, _) | frange. range) ;
250
245
246
+ let focus_range = InFile :: new( file_id, focus_token. text_range( ) )
247
+ . original_node_file_range_opt( db)
248
+ . map( |( frange, _) | frange. range) ;
251
249
return Some ( nav. map( |it| {
252
250
if focus_range. is_some_and( |range| it. full_range. contains_range( range) ) {
253
251
NavigationTarget { focus_range, ..it }
@@ -258,21 +256,26 @@ fn try_find_fn_or_closure(
258
256
} ,
259
257
ast:: ClosureExpr ( c) => {
260
258
let pipe_tok = c. param_list( ) . and_then( |it| it. pipe_token( ) ) ?. into( ) ;
261
- let nav = NavigationTarget :: from_expr( db, InFile :: new( file_id, c. into( ) ) , pipe_tok) ;
259
+ let c_infile = InFile :: new( file_id, c. into( ) ) ;
260
+ let nav = NavigationTarget :: from_expr( db, c_infile, pipe_tok) ;
262
261
return Some ( nav) ;
263
262
} ,
264
- ast:: BlockExpr ( blk) => match blk. modifier( ) {
265
- Some ( ast:: BlockModifier :: Async ( _) ) => {
266
- let async_tok = blk. async_token( ) ?. into( ) ;
267
- let nav = NavigationTarget :: from_expr( db, InFile :: new( file_id, blk. into( ) ) , async_tok) ;
268
- return Some ( nav) ;
269
- } ,
270
- Some ( ast:: BlockModifier :: Try ( _) ) if cursor_token_kind != T ![ return ] => {
271
- let try_tok = blk. try_token( ) ?. into( ) ;
272
- let nav = NavigationTarget :: from_expr( db, InFile :: new( file_id, blk. into( ) ) , try_tok) ;
273
- return Some ( nav) ;
274
- } ,
275
- _ => { }
263
+ ast:: BlockExpr ( blk) => {
264
+ match blk. modifier( ) {
265
+ Some ( ast:: BlockModifier :: Async ( _) ) => {
266
+ let async_tok = blk. async_token( ) ?. into( ) ;
267
+ let blk_infile = InFile :: new( file_id, blk. into( ) ) ;
268
+ let nav = NavigationTarget :: from_expr( db, blk_infile, async_tok) ;
269
+ return Some ( nav) ;
270
+ } ,
271
+ Some ( ast:: BlockModifier :: Try ( _) ) if token. kind( ) != T ![ return ] => {
272
+ let try_tok = blk. try_token( ) ?. into( ) ;
273
+ let blk_infile = InFile :: new( file_id, blk. into( ) ) ;
274
+ let nav = NavigationTarget :: from_expr( db, blk_infile, try_tok) ;
275
+ return Some ( nav) ;
276
+ } ,
277
+ _ => { }
278
+ }
276
279
} ,
277
280
_ => { }
278
281
}
@@ -281,28 +284,9 @@ fn try_find_fn_or_closure(
281
284
None
282
285
}
283
286
284
- let token_kind = token. kind ( ) ;
285
287
sema. descend_into_macros ( DescendPreference :: None , token. clone ( ) )
286
288
. into_iter ( )
287
- . filter_map ( |descended| {
288
- let file_id = sema. hir_file_for ( & descended. parent ( ) ?) ;
289
-
290
- // Try to find the function in the macro file
291
- find_exit_point ( sema, file_id, descended. parent_ancestors ( ) , token_kind) . or_else ( || {
292
- // If not found, try to find it in the root file
293
- if file_id. is_macro ( ) {
294
- token
295
- . parent_ancestors ( )
296
- . find ( |it| ast:: TokenTree :: can_cast ( it. kind ( ) ) )
297
- . and_then ( |parent| {
298
- let file_id = sema. hir_file_for ( & parent) ;
299
- find_exit_point ( sema, file_id, parent. ancestors ( ) , token_kind)
300
- } )
301
- } else {
302
- None
303
- }
304
- } )
305
- } )
289
+ . filter_map ( |descended| find_exit_point ( sema, descended) )
306
290
. flatten ( )
307
291
. collect_vec ( )
308
292
. into ( )
@@ -314,19 +298,13 @@ fn try_find_loop(
314
298
) -> Option < Vec < NavigationTarget > > {
315
299
fn find_break_point (
316
300
sema : & Semantics < ' _ , RootDatabase > ,
317
- file_id : HirFileId ,
318
- ancestors : impl Iterator < Item = SyntaxNode > ,
319
- lbl : & Option < ast:: Lifetime > ,
301
+ token : SyntaxToken ,
302
+ label_matches : impl Fn ( Option < Label > ) -> bool ,
320
303
) -> Option < UpmappingResult < NavigationTarget > > {
321
304
let db = sema. db ;
322
- let label_matches = |it : Option < ast:: Label > | match lbl {
323
- Some ( lbl) => {
324
- Some ( lbl. text ( ) ) == it. and_then ( |it| it. lifetime ( ) ) . as_ref ( ) . map ( |it| it. text ( ) )
325
- }
326
- None => true ,
327
- } ;
305
+ let file_id = sema. hir_file_for ( & token. parent ( ) ?) ;
328
306
329
- for anc in ancestors . filter_map ( ast:: Expr :: cast) {
307
+ for anc in sema . token_ancestors_with_macros ( token . clone ( ) ) . filter_map ( ast:: Expr :: cast) {
330
308
match anc {
331
309
ast:: Expr :: LoopExpr ( loop_) if label_matches ( loop_. label ( ) ) => {
332
310
let expr = ast:: Expr :: LoopExpr ( loop_. clone ( ) ) ;
@@ -369,28 +347,16 @@ fn try_find_loop(
369
347
_ => None ,
370
348
}
371
349
} ;
350
+ let label_matches =
351
+ |it : Option < ast:: Label > | match ( lbl. as_ref ( ) , it. and_then ( |it| it. lifetime ( ) ) ) {
352
+ ( Some ( lbl) , Some ( it) ) => lbl. text ( ) == it. text ( ) ,
353
+ ( None , _) => true ,
354
+ ( Some ( _) , None ) => false ,
355
+ } ;
372
356
373
357
sema. descend_into_macros ( DescendPreference :: None , token. clone ( ) )
374
358
. into_iter ( )
375
- . filter_map ( |descended| {
376
- let file_id = sema. hir_file_for ( & descended. parent ( ) ?) ;
377
-
378
- // Try to find the function in the macro file
379
- find_break_point ( sema, file_id, descended. parent_ancestors ( ) , & lbl) . or_else ( || {
380
- // If not found, try to find it in the root file
381
- if file_id. is_macro ( ) {
382
- token
383
- . parent_ancestors ( )
384
- . find ( |it| ast:: TokenTree :: can_cast ( it. kind ( ) ) )
385
- . and_then ( |parent| {
386
- let file_id = sema. hir_file_for ( & parent) ;
387
- find_break_point ( sema, file_id, parent. ancestors ( ) , & lbl)
388
- } )
389
- } else {
390
- None
391
- }
392
- } )
393
- } )
359
+ . filter_map ( |descended| find_break_point ( sema, descended, label_matches) )
394
360
. flatten ( )
395
361
. collect_vec ( )
396
362
. into ( )
0 commit comments