about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/completion/src/completions/pattern.rs28
-rw-r--r--crates/completion/src/completions/unqualified_path.rs36
-rw-r--r--crates/completion/src/context.rs16
3 files changed, 74 insertions, 6 deletions
diff --git a/crates/completion/src/completions/pattern.rs b/crates/completion/src/completions/pattern.rs
index 595160ff57a..43a5160cba3 100644
--- a/crates/completion/src/completions/pattern.rs
+++ b/crates/completion/src/completions/pattern.rs
@@ -31,6 +31,14 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
                 _ => false,
             },
             hir::ScopeDef::MacroDef(_) => true,
+            hir::ScopeDef::ImplSelfType(impl_) => match impl_.target_ty(ctx.db).as_adt() {
+                Some(hir::Adt::Struct(strukt)) => {
+                    acc.add_struct_pat(ctx, strukt, Some(name.clone()));
+                    true
+                }
+                Some(hir::Adt::Enum(_)) => !ctx.is_irrefutable_pat_binding,
+                _ => true,
+            },
             _ => false,
         };
         if add_resolution {
@@ -258,4 +266,24 @@ fn main() {
 "#,
         );
     }
+
+    #[test]
+    fn completes_self_pats() {
+        check_snippet(
+            r#"
+struct Foo(i32);
+impl Foo {
+    fn foo() {
+        match () {
+            $0
+        }
+    }
+}
+    "#,
+            expect![[r#"
+                bn Self Self($1)$0
+                bn Foo  Foo($1)$0
+            "#]],
+        )
+    }
 }
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs
index e2482f9592d..5112ecc2d9c 100644
--- a/crates/completion/src/completions/unqualified_path.rs
+++ b/crates/completion/src/completions/unqualified_path.rs
@@ -2,7 +2,7 @@
 
 use std::iter;
 
-use hir::{Adt, ModuleDef, ScopeDef, Type};
+use hir::{known, Adt, ModuleDef, ScopeDef, Type};
 use syntax::AstNode;
 use test_utils::mark;
 
@@ -59,6 +59,18 @@ fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &T
             enum_data.module(ctx.db)
         };
 
+        if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) {
+            if impl_.target_ty(ctx.db) == *ty {
+                for &variant in &variants {
+                    let self_path = hir::ModPath::from_segments(
+                        hir::PathKind::Plain,
+                        iter::once(known::SELF_TYPE).chain(iter::once(variant.name(ctx.db))),
+                    );
+                    acc.add_qualified_enum_variant(ctx, variant, self_path.clone());
+                }
+            }
+        }
+
         for variant in variants {
             if let Some(path) = module.find_use_path(ctx.db, ModuleDef::from(variant)) {
                 // Variants with trivial paths are already added by the existing completion logic,
@@ -729,6 +741,28 @@ fn f() -> m::E { V$0 }
     }
 
     #[test]
+    fn completes_enum_variant_impl() {
+        check(
+            r#"
+enum Foo { Bar, Baz, Quux }
+impl Foo {
+    fn foo() { match Foo::Bar { Q$0 } }
+}
+"#,
+            expect![[r#"
+                ev Self::Bar  ()
+                ev Self::Baz  ()
+                ev Self::Quux ()
+                ev Foo::Bar   ()
+                ev Foo::Baz   ()
+                ev Foo::Quux  ()
+                sp Self
+                en Foo
+            "#]],
+        )
+    }
+
+    #[test]
     fn dont_complete_attr() {
         check(
             r#"
diff --git a/crates/completion/src/context.rs b/crates/completion/src/context.rs
index b1e8eba8564..3db3578555f 100644
--- a/crates/completion/src/context.rs
+++ b/crates/completion/src/context.rs
@@ -276,6 +276,14 @@ impl<'a> CompletionContext<'a> {
             });
     }
 
+    fn fill_impl_def(&mut self) {
+        self.impl_def = self
+            .sema
+            .ancestors_with_macros(self.token.parent())
+            .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
+            .find_map(ast::Impl::cast);
+    }
+
     fn fill(
         &mut self,
         original_file: &SyntaxNode,
@@ -345,6 +353,8 @@ impl<'a> CompletionContext<'a> {
                         self.is_irrefutable_pat_binding = true;
                     }
                 }
+
+                self.fill_impl_def();
             }
             if is_node::<ast::Param>(name.syntax()) {
                 self.is_param = true;
@@ -372,11 +382,7 @@ impl<'a> CompletionContext<'a> {
                 self.sema.find_node_at_offset_with_macros(&original_file, offset);
         }
 
-        self.impl_def = self
-            .sema
-            .ancestors_with_macros(self.token.parent())
-            .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
-            .find_map(ast::Impl::cast);
+        self.fill_impl_def();
 
         let top_node = name_ref
             .syntax()