Skip to content

Commit 335d67b

Browse files
committed
refactor: simplify functions related to branch_exit_points in highlight_related
1 parent 964db20 commit 335d67b

File tree

3 files changed

+74
-72
lines changed

3 files changed

+74
-72
lines changed

crates/ide/src/goto_definition.rs

Lines changed: 61 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -292,14 +292,14 @@ fn handle_control_flow_keywords(
292292
token: &SyntaxToken,
293293
) -> Option<Vec<NavigationTarget>> {
294294
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,
296296
// so that VSCode will find the references when using `ctrl + click`
297297
T![fn] | T![async] | T![try] | T![return] => nav_for_exit_points(sema, token),
298298
T![loop] | T![while] | T![break] | T![continue] => nav_for_break_points(sema, token),
299299
T![for] if token.parent().and_then(ast::ForExpr::cast).is_some() => {
300300
nav_for_break_points(sema, token)
301301
}
302-
T![match] | T![=>] | T![if] => nav_for_branches(sema, token),
302+
T![match] | T![=>] | T![if] => nav_for_branch_exit_points(sema, token),
303303
_ => None,
304304
}
305305
}
@@ -409,21 +409,65 @@ fn nav_for_exit_points(
409409
Some(navs)
410410
}
411411

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

418466
let navs = match token.kind() {
419-
T![match] => sema
420-
.descend_into_macros(token.clone())
467+
T![match] => find_branch_root(sema, token)
421468
.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)?;
427471
let file_id = sema.hir_file_for(match_expr.syntax());
428472
let focus_range = match_expr.match_token()?.text_range();
429473
let match_expr_in_file = InFile::new(file_id, match_expr.into());
@@ -432,14 +476,10 @@ fn nav_for_branches(
432476
.flatten()
433477
.collect_vec(),
434478

435-
T![=>] => sema
436-
.descend_into_macros(token.clone())
479+
T![=>] => find_branch_root(sema, token)
437480
.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)?;
443483
let match_expr = sema
444484
.ancestors_with_macros(match_arm.syntax().clone())
445485
.find_map(ast::MatchExpr::cast)?;
@@ -451,14 +491,10 @@ fn nav_for_branches(
451491
.flatten()
452492
.collect_vec(),
453493

454-
T![if] => sema
455-
.descend_into_macros(token.clone())
494+
T![if] => find_branch_root(sema, token)
456495
.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)?;
462498
let file_id = sema.hir_file_for(if_expr.syntax());
463499
let focus_range = if_expr.if_token()?.text_range();
464500
let if_expr_in_file = InFile::new(file_id, if_expr.into());
@@ -3648,9 +3684,9 @@ fn main() {
36483684
r#"
36493685
fn main() {
36503686
if true {
3687+
// ^^
36513688
()
36523689
} else if$0 false {
3653-
// ^^
36543690
()
36553691
} else {
36563692
()

crates/ide/src/highlight_related.rs

Lines changed: 6 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ fn highlight_references(
290290
if res.is_empty() { None } else { Some(res.into_iter().collect()) }
291291
}
292292

293-
pub(crate) fn highlight_branches(
293+
pub(crate) fn highlight_branch_exit_points(
294294
sema: &Semantics<'_, RootDatabase>,
295295
token: SyntaxToken,
296296
) -> FxHashMap<EditionedFileId, Vec<HighlightedRange>> {
@@ -315,40 +315,24 @@ pub(crate) fn highlight_branches(
315315
});
316316
};
317317

318+
let nodes = goto_definition::find_branch_root(sema, &token).into_iter();
318319
match token.kind() {
319320
T![match] => {
320-
for token in sema.descend_into_macros(token.clone()) {
321-
let Some(match_expr) = sema
322-
.token_ancestors_with_macros(token)
323-
.take_while(|node| !ast::MacroCall::can_cast(node.kind()))
324-
.find_map(ast::MatchExpr::cast)
325-
else {
326-
continue;
327-
};
328-
321+
for match_expr in nodes.filter_map(ast::MatchExpr::cast) {
329322
let file_id = sema.hir_file_for(match_expr.syntax());
330323
let range = match_expr.match_token().map(|token| token.text_range());
331324
push_to_highlights(file_id, range, &mut highlights);
332325

333326
let Some(arm_list) = match_expr.match_arm_list() else {
334327
continue;
335328
};
336-
337329
for arm in arm_list.arms() {
338330
push_tail_expr(arm.expr(), &mut highlights);
339331
}
340332
}
341333
}
342334
T![=>] => {
343-
for token in sema.descend_into_macros(token.clone()) {
344-
let Some(arm) = sema
345-
.token_ancestors_with_macros(token)
346-
.take_while(|node| !ast::MacroCall::can_cast(node.kind()))
347-
.find_map(ast::MatchArm::cast)
348-
else {
349-
continue;
350-
};
351-
335+
for arm in nodes.filter_map(ast::MatchArm::cast) {
352336
let file_id = sema.hir_file_for(arm.syntax());
353337
let range = arm.fat_arrow_token().map(|token| token.text_range());
354338
push_to_highlights(file_id, range, &mut highlights);
@@ -357,27 +341,7 @@ pub(crate) fn highlight_branches(
357341
}
358342
}
359343
T![if] => {
360-
for token in sema.descend_into_macros(token.clone()) {
361-
let Some(if_expr) = sema
362-
.token_ancestors_with_macros(token)
363-
.take_while(|node| !ast::MacroCall::can_cast(node.kind()))
364-
.find_map(ast::IfExpr::cast)
365-
else {
366-
continue;
367-
};
368-
369-
// Find the root of the if expression
370-
let mut if_to_process = iter::successors(Some(if_expr.clone()), |if_expr| {
371-
let parent_if = if_expr.syntax().parent().and_then(ast::IfExpr::cast)?;
372-
if let ast::ElseBranch::IfExpr(nested_if) = parent_if.else_branch()? {
373-
(nested_if.syntax() == if_expr.syntax()).then_some(parent_if)
374-
} else {
375-
None
376-
}
377-
})
378-
.last()
379-
.or(Some(if_expr));
380-
344+
for mut if_to_process in nodes.map(ast::IfExpr::cast) {
381345
while let Some(cur_if) = if_to_process.take() {
382346
let file_id = sema.hir_file_for(cur_if.syntax());
383347

@@ -2206,7 +2170,7 @@ fn main() {
22062170

22072171
#[test]
22082172
fn no_branches_when_disabled() {
2209-
let config = HighlightRelatedConfig { branches: false, ..ENABLED_CONFIG };
2173+
let config = HighlightRelatedConfig { branch_exit_points: false, ..ENABLED_CONFIG };
22102174
check_with_config(
22112175
r#"
22122176
fn main() {

crates/ide/src/references.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use hir::{PathResolution, Semantics};
1313
use ide_db::{
1414
FileId, RootDatabase,
1515
defs::{Definition, NameClass, NameRefClass},
16+
helpers::pick_best_token,
1617
search::{ReferenceCategory, SearchScope, UsageSearchResult},
1718
};
1819
use itertools::Itertools;
@@ -309,10 +310,11 @@ fn handle_control_flow_keywords(
309310
let file = sema.parse_guess_edition(file_id);
310311
let edition =
311312
sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT);
312-
let token = file
313-
.syntax()
314-
.token_at_offset(offset)
315-
.find(|t| t.kind().is_keyword(edition) || t.kind() == T![=>])?;
313+
let token = pick_best_token(file.syntax().token_at_offset(offset), |kind| match kind {
314+
_ if kind.is_keyword(edition) => 4,
315+
T![=>] => 3,
316+
_ => 1,
317+
})?;
316318

317319
let references = match token.kind() {
318320
T![fn] | T![return] | T![try] => highlight_related::highlight_exit_points(sema, token),
@@ -323,7 +325,7 @@ fn handle_control_flow_keywords(
323325
T![for] if token.parent().and_then(ast::ForExpr::cast).is_some() => {
324326
highlight_related::highlight_break_points(sema, token)
325327
}
326-
T![if] | T![=>] | T![match] => highlight_related::highlight_branches(sema, token),
328+
T![if] | T![=>] | T![match] => highlight_related::highlight_branch_exit_points(sema, token),
327329
_ => return None,
328330
}
329331
.into_iter()

0 commit comments

Comments
 (0)