]> git.lizzy.rs Git - rust.git/blobdiff - crates/ide_completion/src/completions/fn_param.rs
add: Adding self keyword completion in complete_fn_param
[rust.git] / crates / ide_completion / src / completions / fn_param.rs
index 38e33a93e8d902a5e626321211bdd5622f98fa90..7805da24abd6681ec834f8b1510582ea622514a6 100644 (file)
@@ -12,9 +12,9 @@
 /// functions in a file have a `spam: &mut Spam` parameter, a completion with
 /// `spam: &mut Spam` insert text/label and `spam` lookup string will be
 /// suggested.
-pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) {
+pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
     if !ctx.is_param {
-        return;
+        return None;
     }
 
     let mut params = FxHashMap::default();
@@ -25,12 +25,15 @@ pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
             return;
         }
         func.param_list().into_iter().flat_map(|it| it.params()).for_each(|param| {
-            let text = param.syntax().text().to_string();
-            params.entry(text).or_insert(param);
-        })
+            if let Some(pat) = param.pat() {
+                let text = param.syntax().text().to_string();
+                let lookup = pat.syntax().text().to_string();
+                params.entry(text).or_insert(lookup);
+            }
+        });
     };
 
-    for node in ctx.token.parent().ancestors() {
+    for node in ctx.token.ancestors() {
         match_ast! {
             match node {
                 ast::SourceFile(it) => it.items().filter_map(|item| match item {
@@ -50,28 +53,37 @@ pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
         };
     }
 
-    params
-        .into_iter()
-        .filter_map(|(label, param)| {
-            let lookup = param.pat()?.syntax().text().to_string();
-            Some((label, lookup))
-        })
-        .for_each(|(label, lookup)| {
-            CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label)
-                .kind(CompletionItemKind::Binding)
-                .lookup_by(lookup)
-                .add_to(acc)
+    let self_completion_items = ["self", "&self", "mut self", "&mut self"];
+    if ctx.impl_def.is_some() && me?.param_list()?.params().next().is_none() {
+        self_completion_items.iter().for_each(|self_item| {
+            add_new_item_to_acc(ctx, acc, self_item.to_string(), self_item.to_string())
         });
+    }
+
+    params.into_iter().for_each(|(label, lookup)| add_new_item_to_acc(ctx, acc, label, lookup));
+
+    Some(())
+}
+
+fn add_new_item_to_acc(
+    ctx: &CompletionContext,
+    acc: &mut Completions,
+    label: String,
+    lookup: String,
+) {
+    let mut item = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label);
+    item.kind(CompletionItemKind::Binding).lookup_by(lookup);
+    item.add_to(acc)
 }
 
 #[cfg(test)]
 mod tests {
     use expect_test::{expect, Expect};
 
-    use crate::{test_utils::completion_list, CompletionKind};
+    use crate::{tests::filtered_completion_list, CompletionKind};
 
     fn check(ra_fixture: &str, expect: Expect) {
-        let actual = completion_list(ra_fixture, CompletionKind::Magic);
+        let actual = filtered_completion_list(ra_fixture, CompletionKind::Magic);
         expect.assert_eq(&actual);
     }
 
@@ -132,4 +144,41 @@ fn inner($0)
             "#]],
         )
     }
+
+    #[test]
+    fn completes_non_ident_pat_param() {
+        check(
+            r#"
+struct Bar { bar: u32 }
+
+fn foo(Bar { bar }: Bar) {}
+fn foo2($0) {}
+"#,
+            expect![[r#"
+                bn Bar { bar }: Bar
+            "#]],
+        )
+    }
+
+    #[test]
+    fn test_param_completion_self_param() {
+        check(
+            r#"
+                struct A {}
+
+                impl A {
+                    fn foo(file_id: FileId) {}
+                    fn new($0) {
+                    }
+                }
+            "#,
+            expect![[r#"
+                bn self
+                bn &self
+                bn mut self
+                bn &mut self
+                bn file_id: FileId
+            "#]],
+        )
+    }
 }