mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-15 22:54:00 +00:00
Auto merge of #17513 - roife:fix-issue-17500, r=Veykril
fix: completions after async kw fix #17500 ### Changes 1. fix completions after async kw 2. fix completions for `async` kw in trait
This commit is contained in:
commit
b6422dcaf1
5 changed files with 48 additions and 8 deletions
|
@ -82,17 +82,30 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option
|
|||
let no_vis_qualifiers = ctx.qualifier_ctx.vis_node.is_none();
|
||||
let in_block = kind.is_none();
|
||||
|
||||
let missing_qualifiers = [
|
||||
ctx.qualifier_ctx.unsafe_tok.is_none().then_some(("unsafe", "unsafe $0")),
|
||||
ctx.qualifier_ctx.async_tok.is_none().then_some(("async", "async $0")),
|
||||
];
|
||||
|
||||
if !in_trait_impl {
|
||||
if ctx.qualifier_ctx.unsafe_tok.is_some() {
|
||||
// handle qualifier tokens
|
||||
if missing_qualifiers.iter().any(Option::is_none) {
|
||||
// only complete missing qualifiers
|
||||
missing_qualifiers.iter().filter_map(|x| *x).for_each(|(kw, snippet)| {
|
||||
add_keyword(kw, snippet);
|
||||
});
|
||||
|
||||
if in_item_list || in_assoc_non_trait_impl {
|
||||
add_keyword("fn", "fn $1($2) {\n $0\n}");
|
||||
}
|
||||
if in_item_list {
|
||||
|
||||
if ctx.qualifier_ctx.unsafe_tok.is_some() && in_item_list {
|
||||
add_keyword("trait", "trait $1 {\n $0\n}");
|
||||
if no_vis_qualifiers {
|
||||
add_keyword("impl", "impl $1 {\n $0\n}");
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -100,7 +113,6 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option
|
|||
add_keyword("enum", "enum $1 {\n $0\n}");
|
||||
add_keyword("mod", "mod $0");
|
||||
add_keyword("static", "static $0");
|
||||
add_keyword("async", "async $0");
|
||||
add_keyword("struct", "struct $0");
|
||||
add_keyword("trait", "trait $1 {\n $0\n}");
|
||||
add_keyword("union", "union $1 {\n $0\n}");
|
||||
|
@ -129,6 +141,7 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option
|
|||
add_keyword("fn", "fn $1($2) {\n $0\n}");
|
||||
add_keyword("unsafe", "unsafe $0");
|
||||
add_keyword("const", "const $0");
|
||||
add_keyword("async", "async $0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ mod tests {
|
|||
check(
|
||||
r"fn my_fn() { unsafe $0 }",
|
||||
expect![[r#"
|
||||
kw async
|
||||
kw fn
|
||||
kw impl
|
||||
kw trait
|
||||
|
|
|
@ -46,13 +46,15 @@ pub(crate) enum Visible {
|
|||
/// Existing qualifiers for the thing we are currently completing.
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct QualifierCtx {
|
||||
// TODO: Add try_tok and default_tok
|
||||
pub(crate) async_tok: Option<SyntaxToken>,
|
||||
pub(crate) unsafe_tok: Option<SyntaxToken>,
|
||||
pub(crate) vis_node: Option<ast::Visibility>,
|
||||
}
|
||||
|
||||
impl QualifierCtx {
|
||||
pub(crate) fn none(&self) -> bool {
|
||||
self.unsafe_tok.is_none() && self.vis_node.is_none()
|
||||
self.async_tok.is_none() && self.unsafe_tok.is_none() && self.vis_node.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1287,10 +1287,15 @@ fn classify_name_ref(
|
|||
syntax::algo::non_trivia_sibling(top.clone().into(), syntax::Direction::Prev)
|
||||
{
|
||||
if error_node.kind() == SyntaxKind::ERROR {
|
||||
qualifier_ctx.unsafe_tok = error_node
|
||||
.children_with_tokens()
|
||||
.filter_map(NodeOrToken::into_token)
|
||||
.find(|it| it.kind() == T![unsafe]);
|
||||
for token in
|
||||
error_node.children_with_tokens().filter_map(NodeOrToken::into_token)
|
||||
{
|
||||
match token.kind() {
|
||||
SyntaxKind::UNSAFE_KW => qualifier_ctx.unsafe_tok = Some(token),
|
||||
SyntaxKind::ASYNC_KW => qualifier_ctx.async_tok = Some(token),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
qualifier_ctx.vis_node = error_node.children().find_map(ast::Visibility::cast);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,6 +123,7 @@ fn after_unsafe_token() {
|
|||
check(
|
||||
r#"unsafe $0"#,
|
||||
expect![[r#"
|
||||
kw async
|
||||
kw fn
|
||||
kw impl
|
||||
kw trait
|
||||
|
@ -130,6 +131,17 @@ fn after_unsafe_token() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_async_token() {
|
||||
check(
|
||||
r#"async $0"#,
|
||||
expect![[r#"
|
||||
kw fn
|
||||
kw unsafe
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_visibility() {
|
||||
check(
|
||||
|
@ -157,6 +169,7 @@ fn after_visibility_unsafe() {
|
|||
check(
|
||||
r#"pub unsafe $0"#,
|
||||
expect![[r#"
|
||||
kw async
|
||||
kw fn
|
||||
kw trait
|
||||
"#]],
|
||||
|
@ -170,6 +183,7 @@ fn in_impl_assoc_item_list() {
|
|||
expect![[r#"
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
kw async
|
||||
kw const
|
||||
kw crate::
|
||||
kw fn
|
||||
|
@ -189,6 +203,7 @@ fn in_impl_assoc_item_list_after_attr() {
|
|||
expect![[r#"
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
kw async
|
||||
kw const
|
||||
kw crate::
|
||||
kw fn
|
||||
|
@ -208,6 +223,7 @@ fn in_trait_assoc_item_list() {
|
|||
expect![[r#"
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
kw async
|
||||
kw const
|
||||
kw crate::
|
||||
kw fn
|
||||
|
@ -225,6 +241,7 @@ fn in_trait_assoc_fn_missing_body() {
|
|||
expect![[r#"
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
kw async
|
||||
kw const
|
||||
kw crate::
|
||||
kw fn
|
||||
|
@ -242,6 +259,7 @@ fn in_trait_assoc_const_missing_body() {
|
|||
expect![[r#"
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
kw async
|
||||
kw const
|
||||
kw crate::
|
||||
kw fn
|
||||
|
@ -259,6 +277,7 @@ fn in_trait_assoc_type_aliases_missing_ty() {
|
|||
expect![[r#"
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
kw async
|
||||
kw const
|
||||
kw crate::
|
||||
kw fn
|
||||
|
|
Loading…
Reference in a new issue