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