Skip to content

Commit 62e112a

Browse files
committed
feat: highlighting of related return values while the cursor is on any match, if, or match arm arrow (=>)
1 parent 3e5c46f commit 62e112a

File tree

6 files changed

+775
-9
lines changed

6 files changed

+775
-9
lines changed

src/tools/rust-analyzer/crates/ide/src/goto_definition.rs

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ fn handle_control_flow_keywords(
298298
T![for] if token.parent().and_then(ast::ForExpr::cast).is_some() => {
299299
nav_for_break_points(sema, token)
300300
}
301+
T![match] | T![=>] | T![if] => nav_for_branches(sema, token),
301302
_ => None,
302303
}
303304
}
@@ -407,6 +408,64 @@ fn nav_for_exit_points(
407408
Some(navs)
408409
}
409410

411+
fn nav_for_branches(
412+
sema: &Semantics<'_, RootDatabase>,
413+
token: &SyntaxToken,
414+
) -> Option<Vec<NavigationTarget>> {
415+
let db = sema.db;
416+
417+
let navs = match token.kind() {
418+
T![match] => sema
419+
.descend_into_macros(token.clone())
420+
.into_iter()
421+
.filter_map(|token| {
422+
let match_expr =
423+
sema.token_ancestors_with_macros(token).find_map(ast::MatchExpr::cast)?;
424+
let file_id = sema.hir_file_for(match_expr.syntax());
425+
let focus_range = match_expr.match_token()?.text_range();
426+
let match_expr_in_file = InFile::new(file_id, match_expr.into());
427+
Some(expr_to_nav(db, match_expr_in_file, Some(focus_range)))
428+
})
429+
.flatten()
430+
.collect_vec(),
431+
432+
T![=>] => sema
433+
.descend_into_macros(token.clone())
434+
.into_iter()
435+
.filter_map(|token| {
436+
let match_arm =
437+
sema.token_ancestors_with_macros(token).find_map(ast::MatchArm::cast)?;
438+
let match_expr = sema
439+
.ancestors_with_macros(match_arm.syntax().clone())
440+
.find_map(ast::MatchExpr::cast)?;
441+
let file_id = sema.hir_file_for(match_expr.syntax());
442+
let focus_range = match_arm.fat_arrow_token()?.text_range();
443+
let match_expr_in_file = InFile::new(file_id, match_expr.into());
444+
Some(expr_to_nav(db, match_expr_in_file, Some(focus_range)))
445+
})
446+
.flatten()
447+
.collect_vec(),
448+
449+
T![if] => sema
450+
.descend_into_macros(token.clone())
451+
.into_iter()
452+
.filter_map(|token| {
453+
let if_expr =
454+
sema.token_ancestors_with_macros(token).find_map(ast::IfExpr::cast)?;
455+
let file_id = sema.hir_file_for(if_expr.syntax());
456+
let focus_range = if_expr.if_token()?.text_range();
457+
let if_expr_in_file = InFile::new(file_id, if_expr.into());
458+
Some(expr_to_nav(db, if_expr_in_file, Some(focus_range)))
459+
})
460+
.flatten()
461+
.collect_vec(),
462+
463+
_ => return Some(Vec::new()),
464+
};
465+
466+
Some(navs)
467+
}
468+
410469
pub(crate) fn find_loops(
411470
sema: &Semantics<'_, RootDatabase>,
412471
token: &SyntaxToken,
@@ -3614,4 +3673,155 @@ fn foo() {
36143673
"#,
36153674
);
36163675
}
3676+
3677+
#[test]
3678+
fn goto_def_for_match_keyword() {
3679+
check(
3680+
r#"
3681+
fn main() {
3682+
match$0 0 {
3683+
// ^^^^^
3684+
0 => {},
3685+
_ => {},
3686+
}
3687+
}
3688+
"#,
3689+
);
3690+
}
3691+
3692+
#[test]
3693+
fn goto_def_for_match_arm_fat_arrow() {
3694+
check(
3695+
r#"
3696+
fn main() {
3697+
match 0 {
3698+
0 =>$0 {},
3699+
// ^^
3700+
_ => {},
3701+
}
3702+
}
3703+
"#,
3704+
);
3705+
}
3706+
3707+
#[test]
3708+
fn goto_def_for_if_keyword() {
3709+
check(
3710+
r#"
3711+
fn main() {
3712+
if$0 true {
3713+
// ^^
3714+
()
3715+
}
3716+
}
3717+
"#,
3718+
);
3719+
}
3720+
3721+
#[test]
3722+
fn goto_def_for_match_nested_in_if() {
3723+
check(
3724+
r#"
3725+
fn main() {
3726+
if true {
3727+
match$0 0 {
3728+
// ^^^^^
3729+
0 => {},
3730+
_ => {},
3731+
}
3732+
}
3733+
}
3734+
"#,
3735+
);
3736+
}
3737+
3738+
#[test]
3739+
fn goto_def_for_multiple_match_expressions() {
3740+
check(
3741+
r#"
3742+
fn main() {
3743+
match 0 {
3744+
0 => {},
3745+
_ => {},
3746+
};
3747+
3748+
match$0 1 {
3749+
// ^^^^^
3750+
1 => {},
3751+
_ => {},
3752+
}
3753+
}
3754+
"#,
3755+
);
3756+
}
3757+
3758+
#[test]
3759+
fn goto_def_for_nested_match_expressions() {
3760+
check(
3761+
r#"
3762+
fn main() {
3763+
match 0 {
3764+
0 => match$0 1 {
3765+
// ^^^^^
3766+
1 => {},
3767+
_ => {},
3768+
},
3769+
_ => {},
3770+
}
3771+
}
3772+
"#,
3773+
);
3774+
}
3775+
3776+
#[test]
3777+
fn goto_def_for_if_else_chains() {
3778+
check(
3779+
r#"
3780+
fn main() {
3781+
if true {
3782+
()
3783+
} else if$0 false {
3784+
// ^^
3785+
()
3786+
} else {
3787+
()
3788+
}
3789+
}
3790+
"#,
3791+
);
3792+
}
3793+
3794+
#[test]
3795+
fn goto_def_for_match_with_guards() {
3796+
check(
3797+
r#"
3798+
fn main() {
3799+
match 42 {
3800+
x if x > 0 =>$0 {},
3801+
// ^^
3802+
_ => {},
3803+
}
3804+
}
3805+
"#,
3806+
);
3807+
}
3808+
3809+
#[test]
3810+
fn goto_def_for_match_with_macro_arm() {
3811+
check(
3812+
r#"
3813+
macro_rules! arm {
3814+
() => { 0 => {} };
3815+
}
3816+
3817+
fn main() {
3818+
match$0 0 {
3819+
// ^^^^^
3820+
arm!(),
3821+
_ => {},
3822+
}
3823+
}
3824+
"#,
3825+
);
3826+
}
36173827
}

0 commit comments

Comments
 (0)