refactor: enhance highlighting for control flow kws in macros

This commit is contained in:
roifewu 2025-06-26 13:40:24 +08:00
parent 79de21bd9d
commit 15e70c21d8
2 changed files with 45 additions and 33 deletions

View file

@ -412,45 +412,30 @@ pub(crate) fn find_branch_root(
sema: &Semantics<'_, RootDatabase>, sema: &Semantics<'_, RootDatabase>,
token: &SyntaxToken, token: &SyntaxToken,
) -> Vec<SyntaxNode> { ) -> Vec<SyntaxNode> {
fn find_root( let find_nodes = |node_filter: fn(SyntaxNode) -> Option<SyntaxNode>| {
sema: &Semantics<'_, RootDatabase>, sema.descend_into_macros(token.clone())
token: &SyntaxToken, .into_iter()
pred: impl Fn(SyntaxNode) -> Option<SyntaxNode>, .filter_map(|token| node_filter(token.parent()?))
) -> Vec<SyntaxNode> { .collect_vec()
let mut result = Vec::new(); };
for token in sema.descend_into_macros(token.clone()) {
for node in sema.token_ancestors_with_macros(token) {
if ast::MacroCall::can_cast(node.kind()) {
break;
}
if let Some(node) = pred(node) {
result.push(node);
break;
}
}
}
result
}
match token.kind() { match token.kind() {
T![match] => { T![match] => find_nodes(|node| Some(ast::MatchExpr::cast(node)?.syntax().clone())),
find_root(sema, token, |node| Some(ast::MatchExpr::cast(node)?.syntax().clone())) T![=>] => find_nodes(|node| Some(ast::MatchArm::cast(node)?.syntax().clone())),
} T![if] => find_nodes(|node| {
T![=>] => find_root(sema, token, |node| Some(ast::MatchArm::cast(node)?.syntax().clone())),
T![if] => find_root(sema, token, |node| {
let if_expr = ast::IfExpr::cast(node)?; let if_expr = ast::IfExpr::cast(node)?;
iter::successors(Some(if_expr.clone()), |if_expr| { let root_if = iter::successors(Some(if_expr.clone()), |if_expr| {
let parent_if = if_expr.syntax().parent().and_then(ast::IfExpr::cast)?; let parent_if = if_expr.syntax().parent().and_then(ast::IfExpr::cast)?;
if let ast::ElseBranch::IfExpr(nested_if) = parent_if.else_branch()? { let ast::ElseBranch::IfExpr(else_branch) = parent_if.else_branch()? else {
(nested_if.syntax() == if_expr.syntax()).then_some(parent_if) return None;
} else { };
None
} (else_branch.syntax() == if_expr.syntax()).then_some(parent_if)
}) })
.last() .last()?;
.map(|if_expr| if_expr.syntax().clone())
Some(root_if.syntax().clone())
}), }),
_ => vec![], _ => vec![],
} }

View file

@ -2356,6 +2356,33 @@ fn main() {
) )
} }
#[test]
fn match_in_macro_highlight_2() {
check(
r#"
macro_rules! match_ast {
(match $node:ident { $($tt:tt)* }) => { $crate::match_ast!(match ($node) { $($tt)* }) };
(match ($node:expr) {
$( $( $path:ident )::+ ($it:pat) => $res:expr, )*
_ => $catch_all:expr $(,)?
}) => {{
$( if let Some($it) = $($path::)+cast($node.clone()) { $res } else )*
{ $catch_all }
}};
}
fn main() {
match_ast! {
match$0 Some(1) {
Some(x) => x,
}
}
}
"#,
);
}
#[test] #[test]
fn nested_if_else() { fn nested_if_else() {
check( check(