Skip to content

Commit 16a9a55

Browse files
committed
Fix complete after extern, add crate completion
Example --- ```rust extern "C" $0 ``` **Before this PR** Can't be completion **After this PR** ```text 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 ``` --- ```rust extern $0 ``` **Before this PR** Can't be completion **After this PR** ```rust extern crate $0; ```
1 parent 5c82106 commit 16a9a55

File tree

4 files changed

+110
-2
lines changed

4 files changed

+110
-2
lines changed

src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option
8787
let in_block = kind.is_none();
8888

8989
let no_vis_qualifiers = ctx.qualifier_ctx.vis_node.is_none();
90+
let no_abi_qualifiers = ctx.qualifier_ctx.abi_node.is_none();
91+
let has_extern_kw =
92+
ctx.qualifier_ctx.abi_node.as_ref().is_some_and(|it| it.string_token().is_none());
9093
let has_unsafe_kw = ctx.qualifier_ctx.unsafe_tok.is_some();
9194
let has_async_kw = ctx.qualifier_ctx.async_tok.is_some();
9295
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
118121
}
119122
}
120123

121-
if !has_async_kw && no_vis_qualifiers && in_item_list {
124+
if !has_async_kw && no_vis_qualifiers && no_abi_qualifiers && in_item_list {
122125
add_keyword("extern", "extern $0");
123126
}
124127

@@ -159,11 +162,14 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option
159162
add_keyword("static", "static $1: $2;");
160163
} else {
161164
if !in_inherent_impl {
162-
if !in_trait {
165+
if !in_trait && no_abi_qualifiers {
163166
add_keyword("extern", "extern $0");
164167
}
165168
add_keyword("type", "type $0");
166169
}
170+
if has_extern_kw {
171+
add_keyword("crate", "crate $0;");
172+
}
167173

168174
add_keyword("fn", "fn $1($2) {\n $0\n}");
169175
add_keyword("unsafe", "unsafe $0");

src/tools/rust-analyzer/crates/ide-completion/src/context.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub(crate) struct QualifierCtx {
5353
pub(crate) unsafe_tok: Option<SyntaxToken>,
5454
pub(crate) safe_tok: Option<SyntaxToken>,
5555
pub(crate) vis_node: Option<ast::Visibility>,
56+
pub(crate) abi_node: Option<ast::Abi>,
5657
}
5758

5859
impl QualifierCtx {
@@ -61,6 +62,7 @@ impl QualifierCtx {
6162
&& self.unsafe_tok.is_none()
6263
&& self.safe_tok.is_none()
6364
&& self.vis_node.is_none()
65+
&& self.abi_node.is_none()
6466
}
6567
}
6668

src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1628,6 +1628,7 @@ fn classify_name_ref<'db>(
16281628
}
16291629
}
16301630
qualifier_ctx.vis_node = error_node.children().find_map(ast::Visibility::cast);
1631+
qualifier_ctx.abi_node = error_node.children().find_map(ast::Abi::cast);
16311632
}
16321633

16331634
if let PathKind::Item { .. } = path_ctx.kind

src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,105 @@ fn after_visibility_unsafe() {
176176
);
177177
}
178178

179+
#[test]
180+
fn after_abi() {
181+
check_with_base_items(
182+
r#"extern "C" $0"#,
183+
expect![[r#"
184+
kw async
185+
kw const
186+
kw enum
187+
kw fn
188+
kw impl
189+
kw impl for
190+
kw mod
191+
kw pub
192+
kw pub(crate)
193+
kw pub(super)
194+
kw static
195+
kw struct
196+
kw trait
197+
kw type
198+
kw union
199+
kw unsafe
200+
kw use
201+
"#]],
202+
);
203+
check_with_base_items(
204+
r#"extern "C" f$0"#,
205+
expect![[r#"
206+
kw async
207+
kw const
208+
kw enum
209+
kw fn
210+
kw impl
211+
kw impl for
212+
kw mod
213+
kw pub
214+
kw pub(crate)
215+
kw pub(super)
216+
kw static
217+
kw struct
218+
kw trait
219+
kw type
220+
kw union
221+
kw unsafe
222+
kw use
223+
"#]],
224+
);
225+
}
226+
227+
#[test]
228+
fn after_extern_token() {
229+
check_with_base_items(
230+
r#"extern $0"#,
231+
expect![[r#"
232+
kw async
233+
kw const
234+
kw crate
235+
kw enum
236+
kw fn
237+
kw impl
238+
kw impl for
239+
kw mod
240+
kw pub
241+
kw pub(crate)
242+
kw pub(super)
243+
kw static
244+
kw struct
245+
kw trait
246+
kw type
247+
kw union
248+
kw unsafe
249+
kw use
250+
"#]],
251+
);
252+
check_with_base_items(
253+
r#"extern cr$0"#,
254+
expect![[r#"
255+
kw async
256+
kw const
257+
kw crate
258+
kw enum
259+
kw fn
260+
kw impl
261+
kw impl for
262+
kw mod
263+
kw pub
264+
kw pub(crate)
265+
kw pub(super)
266+
kw static
267+
kw struct
268+
kw trait
269+
kw type
270+
kw union
271+
kw unsafe
272+
kw use
273+
"#]],
274+
);
275+
check_edit("crate", "extern $0", "extern crate $0;");
276+
}
277+
179278
#[test]
180279
fn in_impl_assoc_item_list() {
181280
check_with_base_items(

0 commit comments

Comments
 (0)