ide_completion/completions/
extern_abi.rsuse syntax::{
ast::{self, IsString},
AstNode, AstToken, SmolStr,
};
use crate::{
completions::Completions, context::CompletionContext, CompletionItem, CompletionItemKind,
};
const SUPPORTED_CALLING_CONVENTIONS: &[&str] = &[
"Rust",
"C",
"C-unwind",
"cdecl",
"stdcall",
"stdcall-unwind",
"fastcall",
"vectorcall",
"thiscall",
"thiscall-unwind",
"aapcs",
"win64",
"sysv64",
"ptx-kernel",
"msp430-interrupt",
"x86-interrupt",
"efiapi",
"avr-interrupt",
"avr-non-blocking-interrupt",
"riscv-interrupt-m",
"riscv-interrupt-s",
"C-cmse-nonsecure-call",
"C-cmse-nonsecure-entry",
"wasm",
"system",
"system-unwind",
"rust-intrinsic",
"rust-call",
"unadjusted",
];
pub(crate) fn complete_extern_abi(
acc: &mut Completions,
ctx: &CompletionContext<'_>,
expanded: &ast::String,
) -> Option<()> {
if !expanded.syntax().parent().map_or(false, |it| ast::Abi::can_cast(it.kind())) {
return None;
}
let abi_str = expanded;
let source_range = abi_str.text_range_between_quotes()?;
for &abi in SUPPORTED_CALLING_CONVENTIONS {
CompletionItem::new(
CompletionItemKind::Keyword,
source_range,
SmolStr::new_static(abi),
ctx.edition,
)
.add_to(acc, ctx.db);
}
Some(())
}
#[cfg(test)]
mod tests {
use expect_test::{expect, Expect};
use crate::tests::{check_edit, completion_list_no_kw};
fn check(ra_fixture: &str, expect: Expect) {
let actual = completion_list_no_kw(ra_fixture);
expect.assert_eq(&actual);
}
#[test]
fn only_completes_in_string_literals() {
check(
r#"
$0 fn foo {}
"#,
expect![[]],
);
}
#[test]
fn requires_extern_prefix() {
check(
r#"
"$0" fn foo {}
"#,
expect![[]],
);
}
#[test]
fn works() {
check(
r#"
extern "$0" fn foo {}
"#,
expect![[]],
);
check_edit(
"Rust",
r#"
extern "$0" fn foo {}
"#,
r#"
extern "Rust" fn foo {}
"#,
);
}
}