Implement yield point highlighting

This commit is contained in:
Lukas Wirth 2021-06-23 16:16:32 +02:00
parent 14b66bb458
commit 9a53f1033e
2 changed files with 125 additions and 11 deletions

View File

@ -7,9 +7,9 @@
RootDatabase,
};
use syntax::{
AstNode,
ast, match_ast, AstNode,
SyntaxKind::{ASYNC_KW, AWAIT_KW, QUESTION, RETURN_KW, THIN_ARROW},
SyntaxNode, TextRange,
SyntaxNode, SyntaxToken, TextRange, WalkEvent,
};
use crate::{display::TryToNav, references, NavigationTarget};
@ -36,17 +36,59 @@ pub(crate) fn highlight_related(
})?;
match token.kind() {
QUESTION | RETURN_KW | THIN_ARROW => highlight_exit_points(),
AWAIT_KW | ASYNC_KW => highlight_yield_points(),
QUESTION | RETURN_KW | THIN_ARROW => highlight_exit_points(token),
AWAIT_KW | ASYNC_KW => highlight_yield_points(token),
_ => highlight_references(sema, &syntax, position),
}
}
fn highlight_exit_points() -> Option<Vec<DocumentHighlight>> {
fn highlight_exit_points(_token: SyntaxToken) -> Option<Vec<DocumentHighlight>> {
None
}
fn highlight_yield_points() -> Option<Vec<DocumentHighlight>> {
fn highlight_yield_points(token: SyntaxToken) -> Option<Vec<DocumentHighlight>> {
fn hl(
async_token: Option<SyntaxToken>,
body: Option<ast::BlockExpr>,
) -> Option<Vec<DocumentHighlight>> {
let mut highlights = Vec::new();
highlights.push(DocumentHighlight { access: None, range: async_token?.text_range() });
if let Some(body) = body {
let mut preorder = body.syntax().preorder();
while let Some(event) = preorder.next() {
let node = match event {
WalkEvent::Enter(node) => node,
WalkEvent::Leave(_) => continue,
};
match_ast! {
match node {
ast::AwaitExpr(expr) => if let Some(token) = expr.await_token() {
highlights.push(DocumentHighlight {
access: None,
range: token.text_range(),
});
},
ast::EffectExpr(__) => preorder.skip_subtree(),
ast::ClosureExpr(__) => preorder.skip_subtree(),
ast::Item(__) => preorder.skip_subtree(),
ast::Path(__) => preorder.skip_subtree(),
_ => (),
}
}
}
}
Some(highlights)
}
for anc in token.ancestors() {
return match_ast! {
match anc {
ast::Fn(fn_) => hl(fn_.async_token(), fn_.body()),
ast::EffectExpr(effect) => hl(effect.async_token(), effect.block_expr()),
ast::ClosureExpr(__) => None,
_ => continue,
}
};
}
None
}
@ -135,7 +177,6 @@ fn test_hl_module() {
fn test_hl_self_in_crate_root() {
check(
r#"
//- /lib.rs
use self$0;
"#,
);
@ -157,13 +198,86 @@ fn test_hl_self_in_module() {
fn test_hl_local() {
check(
r#"
//- /lib.rs
fn foo() {
let mut bar = 3;
// ^^^ write
bar$0;
// ^^^ read
}
"#,
);
}
#[test]
fn test_hl_yield_points() {
check(
r#"
pub async fn foo() {
// ^^^^^
let x = foo()
.await$0
// ^^^^^
.await;
// ^^^^^
|| { 0.await };
(async { 0.await }).await
// ^^^^^
}
"#,
);
}
#[test]
fn test_hl_yield_points2() {
check(
r#"
pub async$0 fn foo() {
// ^^^^^
let x = foo()
.await
// ^^^^^
.await;
// ^^^^^
|| { 0.await };
(async { 0.await }).await
// ^^^^^
}
"#,
);
}
#[test]
fn test_hl_yield_nested_fn() {
check(
r#"
async fn foo() {
async fn foo2() {
// ^^^^^
async fn foo3() {
0.await
}
0.await$0
// ^^^^^
}
0.await
}
"#,
);
}
#[test]
fn test_hl_yield_nested_async_blocks() {
check(
r#"
async fn foo() {
(async {
// ^^^^^
(async {
0.await
}).await$0 }
// ^^^^^
).await;
}
"#,
);
}

View File

@ -25,7 +25,7 @@ macro_rules! eprintln {
mod annotations;
mod call_hierarchy;
mod doc_links;
mod highlight_references;
mod highlight_related;
mod expand_macro;
mod extend_selection;
mod file_structure;
@ -76,7 +76,7 @@ macro_rules! eprintln {
expand_macro::ExpandedMacro,
file_structure::{StructureNode, StructureNodeKind},
folding_ranges::{Fold, FoldKind},
highlight_references::DocumentHighlight,
highlight_related::DocumentHighlight,
hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult},
inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
markup::Markup,
@ -490,7 +490,7 @@ pub fn highlight_related(
&self,
position: FilePosition,
) -> Cancellable<Option<Vec<DocumentHighlight>>> {
self.with_db(|db| highlight_references::highlight_related(&Semantics::new(db), position))
self.with_db(|db| highlight_related::highlight_related(&Semantics::new(db), position))
}
/// Computes syntax highlighting for the given file range.