This commit is contained in:
Lukas Wirth 2021-06-23 17:05:00 +02:00
parent 12266d5e56
commit cc791538d6

View file

@ -19,7 +19,7 @@ pub struct DocumentHighlight {
pub access: Option<ReferenceAccess>, pub access: Option<ReferenceAccess>,
} }
// Feature: Highlight related // Feature: Highlight Related
// //
// Highlights exit points, yield points or the definition and all references of the item at the cursor location in the current file. // Highlights exit points, yield points or the definition and all references of the item at the cursor location in the current file.
pub(crate) fn highlight_related( pub(crate) fn highlight_related(
@ -78,7 +78,7 @@ fn highlight_exit_points(token: SyntaxToken) -> Option<Vec<DocumentHighlight>> {
fn hl(body: Option<ast::Expr>) -> Option<Vec<DocumentHighlight>> { fn hl(body: Option<ast::Expr>) -> Option<Vec<DocumentHighlight>> {
let mut highlights = Vec::new(); let mut highlights = Vec::new();
let body = body?; let body = body?;
walk(body.syntax(), |node| { walk(&body, |node| {
match_ast! { match_ast! {
match node { match node {
ast::ReturnExpr(expr) => if let Some(token) = expr.return_token() { ast::ReturnExpr(expr) => if let Some(token) = expr.return_token() {
@ -93,11 +93,11 @@ fn highlight_exit_points(token: SyntaxToken) -> Option<Vec<DocumentHighlight>> {
range: token.text_range(), range: token.text_range(),
}); });
}, },
ast::EffectExpr(effect) => if effect.async_token().is_some() { // All the following are different contexts so skip them
return true; ast::EffectExpr(effect) => return effect.async_token().is_some() || effect.try_token().is_some(),
},
ast::ClosureExpr(__) => return true, ast::ClosureExpr(__) => return true,
ast::Item(__) => return true, ast::Item(__) => return true,
// Don't look into const args
ast::Path(__) => return true, ast::Path(__) => return true,
_ => (), _ => (),
} }
@ -118,8 +118,8 @@ fn highlight_exit_points(token: SyntaxToken) -> Option<Vec<DocumentHighlight>> {
match anc { match anc {
ast::Fn(fn_) => hl(fn_.body().map(ast::Expr::BlockExpr)), ast::Fn(fn_) => hl(fn_.body().map(ast::Expr::BlockExpr)),
ast::ClosureExpr(closure) => hl(closure.body()), ast::ClosureExpr(closure) => hl(closure.body()),
ast::EffectExpr(effect) => if effect.async_token().is_some() { ast::EffectExpr(effect) => if effect.async_token().is_some() || effect.try_token().is_some() {
None hl(effect.block_expr().map(ast::Expr::BlockExpr))
} else { } else {
continue; continue;
}, },
@ -133,12 +133,12 @@ fn highlight_exit_points(token: SyntaxToken) -> Option<Vec<DocumentHighlight>> {
fn highlight_yield_points(token: SyntaxToken) -> Option<Vec<DocumentHighlight>> { fn highlight_yield_points(token: SyntaxToken) -> Option<Vec<DocumentHighlight>> {
fn hl( fn hl(
async_token: Option<SyntaxToken>, async_token: Option<SyntaxToken>,
body: Option<ast::BlockExpr>, body: Option<ast::Expr>,
) -> Option<Vec<DocumentHighlight>> { ) -> Option<Vec<DocumentHighlight>> {
let mut highlights = Vec::new(); let mut highlights = Vec::new();
highlights.push(DocumentHighlight { access: None, range: async_token?.text_range() }); highlights.push(DocumentHighlight { access: None, range: async_token?.text_range() });
if let Some(body) = body { if let Some(body) = body {
walk(body.syntax(), |node| { walk(&body, |node| {
match_ast! { match_ast! {
match node { match node {
ast::AwaitExpr(expr) => if let Some(token) = expr.await_token() { ast::AwaitExpr(expr) => if let Some(token) = expr.await_token() {
@ -147,11 +147,11 @@ fn highlight_yield_points(token: SyntaxToken) -> Option<Vec<DocumentHighlight>>
range: token.text_range(), range: token.text_range(),
}); });
}, },
ast::EffectExpr(effect) => if effect.async_token().is_some() { // All the following are different contexts so skip them
return true; ast::EffectExpr(effect) => return effect.async_token().is_some() || effect.try_token().is_some(),
},
ast::ClosureExpr(__) => return true, ast::ClosureExpr(__) => return true,
ast::Item(__) => return true, ast::Item(__) => return true,
// Don't look into const args
ast::Path(__) => return true, ast::Path(__) => return true,
_ => (), _ => (),
} }
@ -164,9 +164,9 @@ fn highlight_yield_points(token: SyntaxToken) -> Option<Vec<DocumentHighlight>>
for anc in token.ancestors() { for anc in token.ancestors() {
return match_ast! { return match_ast! {
match anc { match anc {
ast::Fn(fn_) => hl(fn_.async_token(), fn_.body()), ast::Fn(fn_) => hl(fn_.async_token(), fn_.body().map(ast::Expr::BlockExpr)),
ast::EffectExpr(effect) => hl(effect.async_token(), effect.block_expr()), ast::EffectExpr(effect) => hl(effect.async_token(), effect.block_expr().map(ast::Expr::BlockExpr)),
ast::ClosureExpr(__) => None, ast::ClosureExpr(closure) => hl(closure.async_token(), closure.body()),
_ => continue, _ => continue,
} }
}; };
@ -174,8 +174,9 @@ fn highlight_yield_points(token: SyntaxToken) -> Option<Vec<DocumentHighlight>>
None None
} }
fn walk(syntax: &SyntaxNode, mut cb: impl FnMut(SyntaxNode) -> bool) { /// Preorder walk the expression node skipping a node's subtrees if the callback returns `true` for the node.
let mut preorder = syntax.preorder(); fn walk(expr: &ast::Expr, mut cb: impl FnMut(SyntaxNode) -> bool) {
let mut preorder = expr.syntax().preorder();
while let Some(event) = preorder.next() { while let Some(event) = preorder.next() {
let node = match event { let node = match event {
WalkEvent::Enter(node) => node, WalkEvent::Enter(node) => node,