Skip to content

Commit 3789184

Browse files
committed
refactor: simplify functions related to branch_exit_points in highlight_related
1 parent ca1a308 commit 3789184

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
@@ -288,14 +288,14 @@ fn handle_control_flow_keywords(
288288
token: &SyntaxToken,
289289
) -> Option<Vec<NavigationTarget>> {
290290
match token.kind() {
291-
// For `fn` / `loop` / `while` / `for` / `async`, return the keyword it self,
291+
// For `fn` / `loop` / `while` / `for` / `async` / `match`, return the keyword it self,
292292
// so that VSCode will find the references when using `ctrl + click`
293293
T![fn] | T![async] | T![try] | T![return] => nav_for_exit_points(sema, token),
294294
T![loop] | T![while] | T![break] | T![continue] => nav_for_break_points(sema, token),
295295
T![for] if token.parent().and_then(ast::ForExpr::cast).is_some() => {
296296
nav_for_break_points(sema, token)
297297
}
298-
T![match] | T![=>] | T![if] => nav_for_branches(sema, token),
298+
T![match] | T![=>] | T![if] => nav_for_branch_exit_points(sema, token),
299299
_ => None,
300300
}
301301
}
@@ -405,21 +405,65 @@ fn nav_for_exit_points(
405405
Some(navs)
406406
}
407407

408-
fn nav_for_branches(
408+
pub(crate) fn find_branch_root(
409+
sema: &Semantics<'_, RootDatabase>,
410+
token: &SyntaxToken,
411+
) -> Vec<SyntaxNode> {
412+
fn find_root(
413+
sema: &Semantics<'_, RootDatabase>,
414+
token: &SyntaxToken,
415+
pred: impl Fn(SyntaxNode) -> Option<SyntaxNode>,
416+
) -> Vec<SyntaxNode> {
417+
let mut result = Vec::new();
418+
for token in sema.descend_into_macros(token.clone()) {
419+
for node in sema.token_ancestors_with_macros(token) {
420+
if ast::MacroCall::can_cast(node.kind()) {
421+
break;
422+
}
423+
424+
if let Some(node) = pred(node) {
425+
result.push(node);
426+
break;
427+
}
428+
}
429+
}
430+
result
431+
}
432+
433+
match token.kind() {
434+
T![match] => {
435+
find_root(sema, token, |node| Some(ast::MatchExpr::cast(node)?.syntax().clone()))
436+
}
437+
T![=>] => find_root(sema, token, |node| Some(ast::MatchArm::cast(node)?.syntax().clone())),
438+
T![if] => find_root(sema, token, |node| {
439+
let if_expr = ast::IfExpr::cast(node)?;
440+
441+
iter::successors(Some(if_expr.clone()), |if_expr| {
442+
let parent_if = if_expr.syntax().parent().and_then(ast::IfExpr::cast)?;
443+
if let ast::ElseBranch::IfExpr(nested_if) = parent_if.else_branch()? {
444+
(nested_if.syntax() == if_expr.syntax()).then_some(parent_if)
445+
} else {
446+
None
447+
}
448+
})
449+
.last()
450+
.map(|if_expr| if_expr.syntax().clone())
451+
}),
452+
_ => vec![],
453+
}
454+
}
455+
456+
fn nav_for_branch_exit_points(
409457
sema: &Semantics<'_, RootDatabase>,
410458
token: &SyntaxToken,
411459
) -> Option<Vec<NavigationTarget>> {
412460
let db = sema.db;
413461

414462
let navs = match token.kind() {
415-
T![match] => sema
416-
.descend_into_macros(token.clone())
463+
T![match] => find_branch_root(sema, token)
417464
.into_iter()
418-
.filter_map(|token| {
419-
let match_expr = sema
420-
.token_ancestors_with_macros(token)
421-
.take_while(|node| !ast::MacroCall::can_cast(node.kind()))
422-
.find_map(ast::MatchExpr::cast)?;
465+
.filter_map(|node| {
466+
let match_expr = ast::MatchExpr::cast(node)?;
423467
let file_id = sema.hir_file_for(match_expr.syntax());
424468
let focus_range = match_expr.match_token()?.text_range();
425469
let match_expr_in_file = InFile::new(file_id, match_expr.into());
@@ -428,14 +472,10 @@ fn nav_for_branches(
428472
.flatten()
429473
.collect_vec(),
430474

431-
T![=>] => sema
432-
.descend_into_macros(token.clone())
475+
T![=>] => find_branch_root(sema, token)
433476
.into_iter()
434-
.filter_map(|token| {
435-
let match_arm = sema
436-
.token_ancestors_with_macros(token)
437-
.take_while(|node| !ast::MacroCall::can_cast(node.kind()))
438-
.find_map(ast::MatchArm::cast)?;
477+
.filter_map(|node| {
478+
let match_arm = ast::MatchArm::cast(node)?;
439479
let match_expr = sema
440480
.ancestors_with_macros(match_arm.syntax().clone())
441481
.find_map(ast::MatchExpr::cast)?;
@@ -447,14 +487,10 @@ fn nav_for_branches(
447487
.flatten()
448488
.collect_vec(),
449489

450-
T![if] => sema
451-
.descend_into_macros(token.clone())
490+
T![if] => find_branch_root(sema, token)
452491
.into_iter()
453-
.filter_map(|token| {
454-
let if_expr = sema
455-
.token_ancestors_with_macros(token)
456-
.take_while(|node| !ast::MacroCall::can_cast(node.kind()))
457-
.find_map(ast::IfExpr::cast)?;
492+
.filter_map(|node| {
493+
let if_expr = ast::IfExpr::cast(node)?;
458494
let file_id = sema.hir_file_for(if_expr.syntax());
459495
let focus_range = if_expr.if_token()?.text_range();
460496
let if_expr_in_file = InFile::new(file_id, if_expr.into());
@@ -3497,9 +3533,9 @@ fn main() {
34973533
r#"
34983534
fn main() {
34993535
if true {
3536+
// ^^
35003537
()
35013538
} else if$0 false {
3502-
// ^^
35033539
()
35043540
} else {
35053541
()

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)