ide_completion/completions/
extern_abi.rs

1//! Completes function abi strings.
2use syntax::{
3    AstNode, AstToken, SmolStr,
4    ast::{self, IsString},
5};
6
7use crate::{
8    CompletionItem, CompletionItemKind, completions::Completions, context::CompletionContext,
9};
10
11// Most of these are feature gated, we should filter/add feature gate completions once we have them.
12const 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}