@@ -291,14 +291,14 @@ fn handle_control_flow_keywords(
291
291
token : & SyntaxToken ,
292
292
) -> Option < Vec < NavigationTarget > > {
293
293
match token. kind ( ) {
294
- // For `fn` / `loop` / `while` / `for` / `async`, return the keyword it self,
294
+ // For `fn` / `loop` / `while` / `for` / `async` / `match` , return the keyword it self,
295
295
// so that VSCode will find the references when using `ctrl + click`
296
296
T ! [ fn ] | T ! [ async ] | T ! [ try] | T ! [ return ] => nav_for_exit_points ( sema, token) ,
297
297
T ! [ loop ] | T ! [ while ] | T ! [ break ] | T ! [ continue ] => nav_for_break_points ( sema, token) ,
298
298
T ! [ for ] if token. parent ( ) . and_then ( ast:: ForExpr :: cast) . is_some ( ) => {
299
299
nav_for_break_points ( sema, token)
300
300
}
301
- T ! [ match ] | T ! [ =>] | T ! [ if ] => nav_for_branches ( sema, token) ,
301
+ T ! [ match ] | T ! [ =>] | T ! [ if ] => nav_for_branch_exit_points ( sema, token) ,
302
302
_ => None ,
303
303
}
304
304
}
@@ -408,37 +408,77 @@ fn nav_for_exit_points(
408
408
Some ( navs)
409
409
}
410
410
411
- fn nav_for_branches (
411
+ pub ( crate ) fn find_branch_root (
412
+ sema : & Semantics < ' _ , RootDatabase > ,
413
+ token : & SyntaxToken ,
414
+ ) -> Vec < SyntaxNode > {
415
+ fn find_root (
416
+ sema : & Semantics < ' _ , RootDatabase > ,
417
+ token : & SyntaxToken ,
418
+ pred : impl Fn ( SyntaxNode ) -> Option < SyntaxNode > ,
419
+ ) -> Vec < SyntaxNode > {
420
+ let mut result = Vec :: new ( ) ;
421
+ for token in sema. descend_into_macros ( token. clone ( ) ) {
422
+ for node in sema. token_ancestors_with_macros ( token) {
423
+ if ast:: MacroCall :: can_cast ( node. kind ( ) ) {
424
+ break ;
425
+ }
426
+
427
+ if let Some ( node) = pred ( node) {
428
+ result. push ( node) ;
429
+ break ;
430
+ }
431
+ }
432
+ }
433
+ result
434
+ }
435
+
436
+ match token. kind ( ) {
437
+ T ! [ match ] => {
438
+ find_root ( sema, token, |node| Some ( ast:: MatchExpr :: cast ( node) ?. syntax ( ) . clone ( ) ) )
439
+ }
440
+ T ! [ =>] => find_root ( sema, token, |node| Some ( ast:: MatchArm :: cast ( node) ?. syntax ( ) . clone ( ) ) ) ,
441
+ T ! [ if ] => find_root ( sema, token, |node| {
442
+ let if_expr = ast:: IfExpr :: cast ( node) ?;
443
+
444
+ iter:: successors ( Some ( if_expr. clone ( ) ) , |if_expr| {
445
+ let parent_if = if_expr. syntax ( ) . parent ( ) . and_then ( ast:: IfExpr :: cast) ?;
446
+ if let ast:: ElseBranch :: IfExpr ( nested_if) = parent_if. else_branch ( ) ? {
447
+ ( nested_if. syntax ( ) == if_expr. syntax ( ) ) . then_some ( parent_if)
448
+ } else {
449
+ None
450
+ }
451
+ } )
452
+ . last ( )
453
+ . map ( |if_expr| if_expr. syntax ( ) . clone ( ) )
454
+ } ) ,
455
+ _ => vec ! [ ] ,
456
+ }
457
+ }
458
+
459
+ fn nav_for_branch_exit_points (
412
460
sema : & Semantics < ' _ , RootDatabase > ,
413
461
token : & SyntaxToken ,
414
462
) -> Option < Vec < NavigationTarget > > {
415
463
let db = sema. db ;
416
464
417
465
let navs = match token. kind ( ) {
418
- T ! [ match ] => sema
419
- . descend_into_macros ( token. clone ( ) )
466
+ T ! [ match ] => find_branch_root ( sema, token)
420
467
. into_iter ( )
421
- . filter_map ( |token| {
422
- let match_expr = sema
423
- . token_ancestors_with_macros ( token)
424
- . take_while ( |node| !ast:: MacroCall :: can_cast ( node. kind ( ) ) )
425
- . find_map ( ast:: MatchExpr :: cast) ?;
426
- let file_id = sema. hir_file_for ( match_expr. syntax ( ) ) ;
468
+ . filter_map ( |node| {
469
+ let file_id = sema. hir_file_for ( & node) ;
470
+ let match_expr = ast:: MatchExpr :: cast ( node) ?;
427
471
let focus_range = match_expr. match_token ( ) ?. text_range ( ) ;
428
472
let match_expr_in_file = InFile :: new ( file_id, match_expr. into ( ) ) ;
429
473
Some ( expr_to_nav ( db, match_expr_in_file, Some ( focus_range) ) )
430
474
} )
431
475
. flatten ( )
432
476
. collect_vec ( ) ,
433
477
434
- T ! [ =>] => sema
435
- . descend_into_macros ( token. clone ( ) )
478
+ T ! [ =>] => find_branch_root ( sema, token)
436
479
. into_iter ( )
437
- . filter_map ( |token| {
438
- let match_arm = sema
439
- . token_ancestors_with_macros ( token)
440
- . take_while ( |node| !ast:: MacroCall :: can_cast ( node. kind ( ) ) )
441
- . find_map ( ast:: MatchArm :: cast) ?;
480
+ . filter_map ( |node| {
481
+ let match_arm = ast:: MatchArm :: cast ( node) ?;
442
482
let match_expr = sema
443
483
. ancestors_with_macros ( match_arm. syntax ( ) . clone ( ) )
444
484
. find_map ( ast:: MatchExpr :: cast) ?;
@@ -450,15 +490,11 @@ fn nav_for_branches(
450
490
. flatten ( )
451
491
. collect_vec ( ) ,
452
492
453
- T ! [ if ] => sema
454
- . descend_into_macros ( token. clone ( ) )
493
+ T ! [ if ] => find_branch_root ( sema, token)
455
494
. into_iter ( )
456
- . filter_map ( |token| {
457
- let if_expr = sema
458
- . token_ancestors_with_macros ( token)
459
- . take_while ( |node| !ast:: MacroCall :: can_cast ( node. kind ( ) ) )
460
- . find_map ( ast:: IfExpr :: cast) ?;
461
- let file_id = sema. hir_file_for ( if_expr. syntax ( ) ) ;
495
+ . filter_map ( |node| {
496
+ let file_id = sema. hir_file_for ( & node) ;
497
+ let if_expr = ast:: IfExpr :: cast ( node) ?;
462
498
let focus_range = if_expr. if_token ( ) ?. text_range ( ) ;
463
499
let if_expr_in_file = InFile :: new ( file_id, if_expr. into ( ) ) ;
464
500
Some ( expr_to_nav ( db, if_expr_in_file, Some ( focus_range) ) )
@@ -3785,9 +3821,9 @@ fn main() {
3785
3821
r#"
3786
3822
fn main() {
3787
3823
if true {
3824
+ // ^^
3788
3825
()
3789
3826
} else if$0 false {
3790
- // ^^
3791
3827
()
3792
3828
} else {
3793
3829
()
0 commit comments