Skip to content

Commit bff9f4c

Browse files
committed
refactor: simplify functions related to branch_exit_points in highlight_related
1 parent 7ab46b4 commit bff9f4c

File tree

3 files changed

+74
-72
lines changed

3 files changed

+74
-72
lines changed

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

Lines changed: 63 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -291,14 +291,14 @@ fn handle_control_flow_keywords(
291291
token: &SyntaxToken,
292292
) -> Option<Vec<NavigationTarget>> {
293293
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,
295295
// so that VSCode will find the references when using `ctrl + click`
296296
T![fn] | T![async] | T![try] | T![return] => nav_for_exit_points(sema, token),
297297
T![loop] | T![while] | T![break] | T![continue] => nav_for_break_points(sema, token),
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),
301+
T![match] | T![=>] | T![if] => nav_for_branch_exit_points(sema, token),
302302
_ => None,
303303
}
304304
}
@@ -408,37 +408,77 @@ fn nav_for_exit_points(
408408
Some(navs)
409409
}
410410

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(
412460
sema: &Semantics<'_, RootDatabase>,
413461
token: &SyntaxToken,
414462
) -> Option<Vec<NavigationTarget>> {
415463
let db = sema.db;
416464

417465
let navs = match token.kind() {
418-
T![match] => sema
419-
.descend_into_macros(token.clone())
466+
T![match] => find_branch_root(sema, token)
420467
.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)?;
427471
let focus_range = match_expr.match_token()?.text_range();
428472
let match_expr_in_file = InFile::new(file_id, match_expr.into());
429473
Some(expr_to_nav(db, match_expr_in_file, Some(focus_range)))
430474
})
431475
.flatten()
432476
.collect_vec(),
433477

434-
T![=>] => sema
435-
.descend_into_macros(token.clone())
478+
T![=>] => find_branch_root(sema, token)
436479
.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)?;
442482
let match_expr = sema
443483
.ancestors_with_macros(match_arm.syntax().clone())
444484
.find_map(ast::MatchExpr::cast)?;
@@ -450,15 +490,11 @@ fn nav_for_branches(
450490
.flatten()
451491
.collect_vec(),
452492

453-
T![if] => sema
454-
.descend_into_macros(token.clone())
493+
T![if] => find_branch_root(sema, token)
455494
.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)?;
462498
let focus_range = if_expr.if_token()?.text_range();
463499
let if_expr_in_file = InFile::new(file_id, if_expr.into());
464500
Some(expr_to_nav(db, if_expr_in_file, Some(focus_range)))
@@ -3785,9 +3821,9 @@ fn main() {
37853821
r#"
37863822
fn main() {
37873823
if true {
3824+
// ^^
37883825
()
37893826
} else if$0 false {
3790-
// ^^
37913827
()
37923828
} else {
37933829
()

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

Lines changed: 5 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -331,40 +331,24 @@ pub(crate) fn highlight_branch_exit_points(
331331
});
332332
};
333333

334+
let nodes = goto_definition::find_branch_root(sema, &token).into_iter();
334335
match token.kind() {
335336
T![match] => {
336-
for token in sema.descend_into_macros(token.clone()) {
337-
let Some(match_expr) = sema
338-
.token_ancestors_with_macros(token)
339-
.take_while(|node| !ast::MacroCall::can_cast(node.kind()))
340-
.find_map(ast::MatchExpr::cast)
341-
else {
342-
continue;
343-
};
344-
337+
for match_expr in nodes.filter_map(ast::MatchExpr::cast) {
345338
let file_id = sema.hir_file_for(match_expr.syntax());
346339
let range = match_expr.match_token().map(|token| token.text_range());
347340
push_to_highlights(file_id, range, &mut highlights);
348341

349342
let Some(arm_list) = match_expr.match_arm_list() else {
350343
continue;
351344
};
352-
353345
for arm in arm_list.arms() {
354346
push_tail_expr(arm.expr(), &mut highlights);
355347
}
356348
}
357349
}
358350
T![=>] => {
359-
for token in sema.descend_into_macros(token.clone()) {
360-
let Some(arm) = sema
361-
.token_ancestors_with_macros(token)
362-
.take_while(|node| !ast::MacroCall::can_cast(node.kind()))
363-
.find_map(ast::MatchArm::cast)
364-
else {
365-
continue;
366-
};
367-
351+
for arm in nodes.filter_map(ast::MatchArm::cast) {
368352
let file_id = sema.hir_file_for(arm.syntax());
369353
let range = arm.fat_arrow_token().map(|token| token.text_range());
370354
push_to_highlights(file_id, range, &mut highlights);
@@ -373,27 +357,7 @@ pub(crate) fn highlight_branch_exit_points(
373357
}
374358
}
375359
T![if] => {
376-
for token in sema.descend_into_macros(token.clone()) {
377-
let Some(if_expr) = sema
378-
.token_ancestors_with_macros(token)
379-
.take_while(|node| !ast::MacroCall::can_cast(node.kind()))
380-
.find_map(ast::IfExpr::cast)
381-
else {
382-
continue;
383-
};
384-
385-
// Find the root of the if expression
386-
let mut if_to_process = iter::successors(Some(if_expr.clone()), |if_expr| {
387-
let parent_if = if_expr.syntax().parent().and_then(ast::IfExpr::cast)?;
388-
if let ast::ElseBranch::IfExpr(nested_if) = parent_if.else_branch()? {
389-
(nested_if.syntax() == if_expr.syntax()).then_some(parent_if)
390-
} else {
391-
None
392-
}
393-
})
394-
.last()
395-
.or(Some(if_expr));
396-
360+
for mut if_to_process in nodes.map(ast::IfExpr::cast) {
397361
while let Some(cur_if) = if_to_process.take() {
398362
let file_id = sema.hir_file_for(cur_if.syntax());
399363

@@ -415,7 +379,7 @@ pub(crate) fn highlight_branch_exit_points(
415379
}
416380
}
417381
}
418-
_ => unreachable!(),
382+
_ => {}
419383
}
420384

421385
highlights

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use hir::{PathResolution, Semantics};
2121
use ide_db::{
2222
FileId, RootDatabase,
2323
defs::{Definition, NameClass, NameRefClass},
24+
helpers::pick_best_token,
2425
search::{ReferenceCategory, SearchScope, UsageSearchResult},
2526
};
2627
use itertools::Itertools;
@@ -397,10 +398,11 @@ fn handle_control_flow_keywords(
397398
.attach_first_edition(file_id)
398399
.map(|it| it.edition(sema.db))
399400
.unwrap_or(Edition::CURRENT);
400-
let token = file
401-
.syntax()
402-
.token_at_offset(offset)
403-
.find(|t| t.kind().is_keyword(edition) || t.kind() == T![=>])?;
401+
let token = pick_best_token(file.syntax().token_at_offset(offset), |kind| match kind {
402+
_ if kind.is_keyword(edition) => 4,
403+
T![=>] => 3,
404+
_ => 1,
405+
})?;
404406

405407
let references = match token.kind() {
406408
T![fn] | T![return] | T![try] => highlight_related::highlight_exit_points(sema, token),

0 commit comments

Comments
 (0)