about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/ide_completion/src/completions.rs1
-rw-r--r--crates/ide_completion/src/completions/dot.rs8
-rw-r--r--crates/ide_completion/src/completions/extern_abi.rs104
-rw-r--r--crates/ide_completion/src/lib.rs31
-rw-r--r--crates/ide_completion/src/tests/expression.rs2
-rw-r--r--crates/ide_completion/src/tests/record.rs8
6 files changed, 130 insertions, 24 deletions
diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs
index 9c65efdb102..c11a1efce4f 100644
--- a/crates/ide_completion/src/completions.rs
+++ b/crates/ide_completion/src/completions.rs
@@ -2,6 +2,7 @@
 
 pub(crate) mod attribute;
 pub(crate) mod dot;
+pub(crate) mod extern_abi;
 pub(crate) mod flyimport;
 pub(crate) mod fn_param;
 pub(crate) mod format_string;
diff --git a/crates/ide_completion/src/completions/dot.rs b/crates/ide_completion/src/completions/dot.rs
index 4a34b0f7e56..3bb3f883cdb 100644
--- a/crates/ide_completion/src/completions/dot.rs
+++ b/crates/ide_completion/src/completions/dot.rs
@@ -684,12 +684,12 @@ struct Foo { field: i32 }
 
 impl Foo { fn foo(&self) { $0 } }"#,
             expect![[r#"
+                fd self.field i32
+                me self.foo() fn(&self)
                 lc self       &Foo
                 sp Self
                 st Foo
                 bt u32
-                fd self.field i32
-                me self.foo() fn(&self)
             "#]],
         );
         check(
@@ -698,12 +698,12 @@ struct Foo(i32);
 
 impl Foo { fn foo(&mut self) { $0 } }"#,
             expect![[r#"
+                fd self.0     i32
+                me self.foo() fn(&mut self)
                 lc self       &mut Foo
                 sp Self
                 st Foo
                 bt u32
-                fd self.0     i32
-                me self.foo() fn(&mut self)
             "#]],
         );
     }
diff --git a/crates/ide_completion/src/completions/extern_abi.rs b/crates/ide_completion/src/completions/extern_abi.rs
new file mode 100644
index 00000000000..87fccec008e
--- /dev/null
+++ b/crates/ide_completion/src/completions/extern_abi.rs
@@ -0,0 +1,104 @@
+//! Completes function abi strings.
+use syntax::{
+    ast::{self, IsString},
+    AstNode, AstToken,
+};
+
+use crate::{
+    completions::Completions, context::CompletionContext, CompletionItem, CompletionItemKind,
+};
+
+// Most of these are feature gated, we should filter/add feature gate completions once we have them.
+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",
+    "amdgpu-kernel",
+    "efiapi",
+    "avr-interrupt",
+    "avr-non-blocking-interrupt",
+    "C-cmse-nonsecure-call",
+    "wasm",
+    "system",
+    "system-unwind",
+    "rust-intrinsic",
+    "rust-call",
+    "platform-intrinsic",
+    "unadjusted",
+];
+
+pub(crate) fn complete_extern_abi(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
+    if ctx.token.parent().and_then(ast::Abi::cast).is_none() {
+        return None;
+    }
+    let abi_str = ast::String::cast(ctx.token.clone())?;
+    let source_range = abi_str.text_range_between_quotes()?;
+    for &abi in SUPPORTED_CALLING_CONVENTIONS {
+        CompletionItem::new(CompletionItemKind::Keyword, source_range, abi).add_to(acc);
+    }
+    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 {}
+"#,
+        );
+    }
+}
diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs
index f0cd125973a..9f6f6592de5 100644
--- a/crates/ide_completion/src/lib.rs
+++ b/crates/ide_completion/src/lib.rs
@@ -151,27 +151,28 @@ pub fn completions(
     }
 
     let mut acc = Completions::default();
-    completions::attribute::complete_known_attribute_input(&mut acc, &ctx);
     completions::attribute::complete_attribute(&mut acc, &ctx);
-    completions::use_::complete_use_tree(&mut acc, &ctx);
-    completions::vis::complete_vis(&mut acc, &ctx);
+    completions::attribute::complete_known_attribute_input(&mut acc, &ctx);
+    completions::dot::complete_dot(&mut acc, &ctx);
+    completions::extern_abi::complete_extern_abi(&mut acc, &ctx);
+    completions::flyimport::import_on_the_fly(&mut acc, &ctx);
     completions::fn_param::complete_fn_param(&mut acc, &ctx);
+    completions::format_string::format_string(&mut acc, &ctx);
     completions::keyword::complete_expr_keyword(&mut acc, &ctx);
-    completions::snippet::complete_expr_snippet(&mut acc, &ctx);
-    completions::snippet::complete_item_snippet(&mut acc, &ctx);
-    completions::qualified_path::complete_qualified_path(&mut acc, &ctx);
-    completions::unqualified_path::complete_unqualified_path(&mut acc, &ctx);
-    completions::dot::complete_dot(&mut acc, &ctx);
-    completions::record::complete_record(&mut acc, &ctx);
-    completions::record::complete_record_literal(&mut acc, &ctx);
+    completions::lifetime::complete_label(&mut acc, &ctx);
+    completions::lifetime::complete_lifetime(&mut acc, &ctx);
+    completions::mod_::complete_mod(&mut acc, &ctx);
     completions::pattern::complete_pattern(&mut acc, &ctx);
     completions::postfix::complete_postfix(&mut acc, &ctx);
+    completions::qualified_path::complete_qualified_path(&mut acc, &ctx);
+    completions::record::complete_record_literal(&mut acc, &ctx);
+    completions::record::complete_record(&mut acc, &ctx);
+    completions::snippet::complete_expr_snippet(&mut acc, &ctx);
+    completions::snippet::complete_item_snippet(&mut acc, &ctx);
     completions::trait_impl::complete_trait_impl(&mut acc, &ctx);
-    completions::mod_::complete_mod(&mut acc, &ctx);
-    completions::flyimport::import_on_the_fly(&mut acc, &ctx);
-    completions::lifetime::complete_lifetime(&mut acc, &ctx);
-    completions::lifetime::complete_label(&mut acc, &ctx);
-    completions::format_string::format_string(&mut acc, &ctx);
+    completions::unqualified_path::complete_unqualified_path(&mut acc, &ctx);
+    completions::use_::complete_use_tree(&mut acc, &ctx);
+    completions::vis::complete_vis(&mut acc, &ctx);
 
     Some(acc)
 }
diff --git a/crates/ide_completion/src/tests/expression.rs b/crates/ide_completion/src/tests/expression.rs
index 56a2cd6e9dc..5e1fae68fd2 100644
--- a/crates/ide_completion/src/tests/expression.rs
+++ b/crates/ide_completion/src/tests/expression.rs
@@ -126,6 +126,7 @@ impl Unit {
 "#,
         // `self` is in here twice, once as the module, once as the local
         expect![[r##"
+            me self.foo()   fn(self)
             kw unsafe
             kw fn
             kw const
@@ -172,7 +173,6 @@ impl Unit {
             un Union
             ev TupleV(…)    (u32)
             ct CONST
-            me self.foo()   fn(self)
         "##]],
     );
     check(
diff --git a/crates/ide_completion/src/tests/record.rs b/crates/ide_completion/src/tests/record.rs
index e09e99aad5e..3bb332b4372 100644
--- a/crates/ide_completion/src/tests/record.rs
+++ b/crates/ide_completion/src/tests/record.rs
@@ -166,6 +166,10 @@ fn main() {
             kw true
             kw false
             kw return
+            sn Foo {…}              Foo { foo1: ${1:()}, foo2: ${2:()} }$0
+            fd ..Default::default()
+            fd foo1                 u32
+            fd foo2                 u32
             kw self
             kw super
             kw crate
@@ -177,10 +181,6 @@ fn main() {
             bt u32
             tt Sized
             tt Default
-            fd ..Default::default()
-            fd foo1                 u32
-            fd foo2                 u32
-            sn Foo {…}              Foo { foo1: ${1:()}, foo2: ${2:()} }$0
         "#]],
     );
     check(