Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/ide-completion/src/completions/item_list.rs10
-rw-r--r--crates/ide-completion/src/context.rs2
-rw-r--r--crates/ide-completion/src/context/analysis.rs1
-rw-r--r--crates/ide-completion/src/tests/item_list.rs99
4 files changed, 110 insertions, 2 deletions
diff --git a/crates/ide-completion/src/completions/item_list.rs b/crates/ide-completion/src/completions/item_list.rs
index 6c001bd16b..39048e4400 100644
--- a/crates/ide-completion/src/completions/item_list.rs
+++ b/crates/ide-completion/src/completions/item_list.rs
@@ -87,6 +87,9 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option
let in_block = kind.is_none();
let no_vis_qualifiers = ctx.qualifier_ctx.vis_node.is_none();
+ let no_abi_qualifiers = ctx.qualifier_ctx.abi_node.is_none();
+ let has_extern_kw =
+ ctx.qualifier_ctx.abi_node.as_ref().is_some_and(|it| it.string_token().is_none());
let has_unsafe_kw = ctx.qualifier_ctx.unsafe_tok.is_some();
let has_async_kw = ctx.qualifier_ctx.async_tok.is_some();
let has_safe_kw = ctx.qualifier_ctx.safe_tok.is_some();
@@ -118,7 +121,7 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option
}
}
- if !has_async_kw && no_vis_qualifiers && in_item_list {
+ if !has_async_kw && no_vis_qualifiers && no_abi_qualifiers && in_item_list {
add_keyword("extern", "extern $0");
}
@@ -159,11 +162,14 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option
add_keyword("static", "static $1: $2;");
} else {
if !in_inherent_impl {
- if !in_trait {
+ if !in_trait && no_abi_qualifiers {
add_keyword("extern", "extern $0");
}
add_keyword("type", "type $0");
}
+ if has_extern_kw {
+ add_keyword("crate", "crate $0;");
+ }
add_keyword("fn", "fn $1($2) {\n $0\n}");
add_keyword("unsafe", "unsafe $0");
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 31a9a74aa8..23318e1d19 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -53,6 +53,7 @@ pub(crate) struct QualifierCtx {
pub(crate) unsafe_tok: Option<SyntaxToken>,
pub(crate) safe_tok: Option<SyntaxToken>,
pub(crate) vis_node: Option<ast::Visibility>,
+ pub(crate) abi_node: Option<ast::Abi>,
}
impl QualifierCtx {
@@ -61,6 +62,7 @@ impl QualifierCtx {
&& self.unsafe_tok.is_none()
&& self.safe_tok.is_none()
&& self.vis_node.is_none()
+ && self.abi_node.is_none()
}
}
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index e84c065336..da9464f48a 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -1628,6 +1628,7 @@ fn classify_name_ref<'db>(
}
}
qualifier_ctx.vis_node = error_node.children().find_map(ast::Visibility::cast);
+ qualifier_ctx.abi_node = error_node.children().find_map(ast::Abi::cast);
}
if let PathKind::Item { .. } = path_ctx.kind
diff --git a/crates/ide-completion/src/tests/item_list.rs b/crates/ide-completion/src/tests/item_list.rs
index ac32649d4f..9afc8b49d6 100644
--- a/crates/ide-completion/src/tests/item_list.rs
+++ b/crates/ide-completion/src/tests/item_list.rs
@@ -177,6 +177,105 @@ fn after_visibility_unsafe() {
}
#[test]
+fn after_abi() {
+ check_with_base_items(
+ r#"extern "C" $0"#,
+ expect![[r#"
+ kw async
+ kw const
+ kw enum
+ kw fn
+ kw impl
+ kw impl for
+ kw mod
+ kw pub
+ kw pub(crate)
+ kw pub(super)
+ kw static
+ kw struct
+ kw trait
+ kw type
+ kw union
+ kw unsafe
+ kw use
+ "#]],
+ );
+ check_with_base_items(
+ r#"extern "C" f$0"#,
+ expect![[r#"
+ kw async
+ kw const
+ kw enum
+ kw fn
+ kw impl
+ kw impl for
+ kw mod
+ kw pub
+ kw pub(crate)
+ kw pub(super)
+ kw static
+ kw struct
+ kw trait
+ kw type
+ kw union
+ kw unsafe
+ kw use
+ "#]],
+ );
+}
+
+#[test]
+fn after_extern_token() {
+ check_with_base_items(
+ r#"extern $0"#,
+ expect![[r#"
+ kw async
+ kw const
+ kw crate
+ kw enum
+ kw fn
+ kw impl
+ kw impl for
+ kw mod
+ kw pub
+ kw pub(crate)
+ kw pub(super)
+ kw static
+ kw struct
+ kw trait
+ kw type
+ kw union
+ kw unsafe
+ kw use
+ "#]],
+ );
+ check_with_base_items(
+ r#"extern cr$0"#,
+ expect![[r#"
+ kw async
+ kw const
+ kw crate
+ kw enum
+ kw fn
+ kw impl
+ kw impl for
+ kw mod
+ kw pub
+ kw pub(crate)
+ kw pub(super)
+ kw static
+ kw struct
+ kw trait
+ kw type
+ kw union
+ kw unsafe
+ kw use
+ "#]],
+ );
+ check_edit("crate", "extern $0", "extern crate $0;");
+}
+
+#[test]
fn in_impl_assoc_item_list() {
check_with_base_items(
r#"impl Struct { $0 }"#,