@@ -5,8 +5,7 @@ use crate::{
55 RangeInfo , TryToNav , UpmappingResult ,
66} ;
77use hir:: {
8- AsAssocItem , AssocItem , DescendPreference , HirFileId , InFile , MacroFileIdExt , ModuleDef ,
9- Semantics ,
8+ AsAssocItem , AssocItem , DescendPreference , InFile , MacroFileIdExt , ModuleDef , Semantics ,
109} ;
1110use ide_db:: {
1211 base_db:: { AnchoredPath , FileLoader } ,
@@ -15,11 +14,12 @@ use ide_db::{
1514 FileId , RootDatabase ,
1615} ;
1716use itertools:: Itertools ;
17+ use span:: FileRange ;
1818use syntax:: {
19- ast:: { self , HasLoopBody } ,
19+ ast:: { self , HasLoopBody , Label } ,
2020 match_ast, AstNode , AstToken ,
21- SyntaxKind :: { self , * } ,
22- SyntaxNode , SyntaxToken , TextRange , T ,
21+ SyntaxKind :: * ,
22+ SyntaxToken , TextRange , T ,
2323} ;
2424
2525// Feature: Go to Definition
@@ -224,30 +224,28 @@ fn try_find_fn_or_closure(
224224) -> Option < Vec < NavigationTarget > > {
225225 fn find_exit_point (
226226 sema : & Semantics < ' _ , RootDatabase > ,
227- file_id : HirFileId ,
228- ancestors : impl Iterator < Item = SyntaxNode > ,
229- cursor_token_kind : SyntaxKind ,
227+ token : SyntaxToken ,
230228 ) -> Option < UpmappingResult < NavigationTarget > > {
231229 let db = sema. db ;
232230
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) ;
234233 match_ast ! {
235234 match anc {
236235 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) ?;
240238 // For async token, we navigate to itself, which triggers
241239 // 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 ] ) {
243241 fn_. async_token( ) ?
244242 } else {
245243 fn_. fn_token( ) ?
246244 } ;
247- let focus_range = InFile :: new( file_id, focus_token. text_range( ) )
248- . original_node_file_range_opt( db)
249- . map( |( frange, _) | frange. range) ;
250245
246+ let focus_range = InFile :: new( file_id, focus_token. text_range( ) )
247+ . original_node_file_range_opt( db)
248+ . map( |( frange, _) | frange. range) ;
251249 return Some ( nav. map( |it| {
252250 if focus_range. is_some_and( |range| it. full_range. contains_range( range) ) {
253251 NavigationTarget { focus_range, ..it }
@@ -258,21 +256,26 @@ fn try_find_fn_or_closure(
258256 } ,
259257 ast:: ClosureExpr ( c) => {
260258 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) ;
262261 return Some ( nav) ;
263262 } ,
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+ }
276279 } ,
277280 _ => { }
278281 }
@@ -281,28 +284,9 @@ fn try_find_fn_or_closure(
281284 None
282285 }
283286
284- let token_kind = token. kind ( ) ;
285287 sema. descend_into_macros ( DescendPreference :: None , token. clone ( ) )
286288 . 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) )
306290 . flatten ( )
307291 . collect_vec ( )
308292 . into ( )
@@ -314,19 +298,13 @@ fn try_find_loop(
314298) -> Option < Vec < NavigationTarget > > {
315299 fn find_break_point (
316300 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 ,
320303 ) -> Option < UpmappingResult < NavigationTarget > > {
321304 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 ( ) ?) ;
328306
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) {
330308 match anc {
331309 ast:: Expr :: LoopExpr ( loop_) if label_matches ( loop_. label ( ) ) => {
332310 let expr = ast:: Expr :: LoopExpr ( loop_. clone ( ) ) ;
@@ -369,28 +347,16 @@ fn try_find_loop(
369347 _ => None ,
370348 }
371349 } ;
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+ } ;
372356
373357 sema. descend_into_macros ( DescendPreference :: None , token. clone ( ) )
374358 . 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) )
394360 . flatten ( )
395361 . collect_vec ( )
396362 . into ( )
0 commit comments