Skip to content

Commit e23e442

Browse files
committed
refactor: simplify functions related to branch_exit_points in highlight_related
1 parent a814764 commit e23e442

File tree

3 files changed

+74
-72
lines changed

3 files changed

+74
-72
lines changed

crates/ide/src/goto_definition.rs

+61-25
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

+6-42
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ fn highlight_references(
307307
if res.is_empty() { None } else { Some(res.into_iter().collect()) }
308308
}
309309

310-
pub(crate) fn highlight_branches(
310+
pub(crate) fn highlight_branch_exit_points(
311311
sema: &Semantics<'_, RootDatabase>,
312312
token: SyntaxToken,
313313
) -> FxHashMap<EditionedFileId, Vec<HighlightedRange>> {
@@ -332,40 +332,24 @@ pub(crate) fn highlight_branches(
332332
});
333333
};
334334

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

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

@@ -2235,7 +2199,7 @@ fn main() {
22352199

22362200
#[test]
22372201
fn no_branches_when_disabled() {
2238-
let config = HighlightRelatedConfig { branches: false, ..ENABLED_CONFIG };
2202+
let config = HighlightRelatedConfig { branch_exit_points: false, ..ENABLED_CONFIG };
22392203
check_with_config(
22402204
r#"
22412205
fn main() {

crates/ide/src/references.rs

+7-5
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)