ide_completion/completions/
extern_abi.rs1use syntax::{
3 AstNode, AstToken, SmolStr,
4 ast::{self, IsString},
5};
6
7use crate::{
8 CompletionItem, CompletionItemKind, completions::Completions, context::CompletionContext,
9};
10
11const SUPPORTED_CALLING_CONVENTIONS: &[&str] = &[
13 "Rust",
14 "C",
15 "C-unwind",
16 "cdecl",
17 "stdcall",
18 "stdcall-unwind",
19 "fastcall",
20 "vectorcall",
21 "thiscall",
22 "thiscall-unwind",
23 "aapcs",
24 "win64",
25 "sysv64",
26 "ptx-kernel",
27 "msp430-interrupt",
28 "x86-interrupt",
29 "efiapi",
30 "avr-interrupt",
31 "avr-non-blocking-interrupt",
32 "riscv-interrupt-m",
33 "riscv-interrupt-s",
34 "C-cmse-nonsecure-call",
35 "C-cmse-nonsecure-entry",
36 "wasm",
37 "system",
38 "system-unwind",
39 "rust-intrinsic",
40 "rust-call",
41 "unadjusted",
42];
43
44pub(crate) fn complete_extern_abi(
45 acc: &mut Completions,
46 ctx: &CompletionContext<'_>,
47 expanded: &ast::String,
48) -> Option<()> {
49 if !expanded.syntax().parent().is_some_and(|it| ast::Abi::can_cast(it.kind())) {
50 return None;
51 }
52 let abi_str = expanded;
53 let source_range = abi_str.text_range_between_quotes()?;
54 for &abi in SUPPORTED_CALLING_CONVENTIONS {
55 CompletionItem::new(
56 CompletionItemKind::Keyword,
57 source_range,
58 SmolStr::new_static(abi),
59 ctx.edition,
60 )
61 .add_to(acc, ctx.db);
62 }
63 Some(())
64}
65
66#[cfg(test)]
67mod tests {
68 use expect_test::expect;
69
70 use crate::tests::{check_edit, check_no_kw};
71
72 #[test]
73 fn only_completes_in_string_literals() {
74 check_no_kw(
75 r#"
76$0 fn foo {}
77"#,
78 expect![[]],
79 );
80 }
81
82 #[test]
83 fn requires_extern_prefix() {
84 check_no_kw(
85 r#"
86"$0" fn foo {}
87"#,
88 expect![[]],
89 );
90 }
91
92 #[test]
93 fn works() {
94 check_no_kw(
95 r#"
96extern "$0" fn foo {}
97"#,
98 expect![[]],
99 );
100 check_edit(
101 "Rust",
102 r#"
103extern "$0" fn foo {}
104"#,
105 r#"
106extern "Rust" fn foo {}
107"#,
108 );
109 }
110}