diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/completion/src/completions/pattern.rs | 28 | ||||
-rw-r--r-- | crates/completion/src/completions/unqualified_path.rs | 36 | ||||
-rw-r--r-- | crates/completion/src/context.rs | 16 |
3 files changed, 74 insertions, 6 deletions
diff --git a/crates/completion/src/completions/pattern.rs b/crates/completion/src/completions/pattern.rs index 595160ff5..43a5160cb 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) { | |||
31 | _ => false, | 31 | _ => false, |
32 | }, | 32 | }, |
33 | hir::ScopeDef::MacroDef(_) => true, | 33 | hir::ScopeDef::MacroDef(_) => true, |
34 | hir::ScopeDef::ImplSelfType(impl_) => match impl_.target_ty(ctx.db).as_adt() { | ||
35 | Some(hir::Adt::Struct(strukt)) => { | ||
36 | acc.add_struct_pat(ctx, strukt, Some(name.clone())); | ||
37 | true | ||
38 | } | ||
39 | Some(hir::Adt::Enum(_)) => !ctx.is_irrefutable_pat_binding, | ||
40 | _ => true, | ||
41 | }, | ||
34 | _ => false, | 42 | _ => false, |
35 | }; | 43 | }; |
36 | if add_resolution { | 44 | if add_resolution { |
@@ -258,4 +266,24 @@ fn main() { | |||
258 | "#, | 266 | "#, |
259 | ); | 267 | ); |
260 | } | 268 | } |
269 | |||
270 | #[test] | ||
271 | fn completes_self_pats() { | ||
272 | check_snippet( | ||
273 | r#" | ||
274 | struct Foo(i32); | ||
275 | impl Foo { | ||
276 | fn foo() { | ||
277 | match () { | ||
278 | $0 | ||
279 | } | ||
280 | } | ||
281 | } | ||
282 | "#, | ||
283 | expect![[r#" | ||
284 | bn Self Self($1)$0 | ||
285 | bn Foo Foo($1)$0 | ||
286 | "#]], | ||
287 | ) | ||
288 | } | ||
261 | } | 289 | } |
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs index e2482f959..5112ecc2d 100644 --- a/crates/completion/src/completions/unqualified_path.rs +++ b/crates/completion/src/completions/unqualified_path.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | use std::iter; | 3 | use std::iter; |
4 | 4 | ||
5 | use hir::{Adt, ModuleDef, ScopeDef, Type}; | 5 | use hir::{known, Adt, ModuleDef, ScopeDef, Type}; |
6 | use syntax::AstNode; | 6 | use syntax::AstNode; |
7 | use test_utils::mark; | 7 | use test_utils::mark; |
8 | 8 | ||
@@ -59,6 +59,18 @@ fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &T | |||
59 | enum_data.module(ctx.db) | 59 | enum_data.module(ctx.db) |
60 | }; | 60 | }; |
61 | 61 | ||
62 | if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) { | ||
63 | if impl_.target_ty(ctx.db) == *ty { | ||
64 | for &variant in &variants { | ||
65 | let self_path = hir::ModPath::from_segments( | ||
66 | hir::PathKind::Plain, | ||
67 | iter::once(known::SELF_TYPE).chain(iter::once(variant.name(ctx.db))), | ||
68 | ); | ||
69 | acc.add_qualified_enum_variant(ctx, variant, self_path.clone()); | ||
70 | } | ||
71 | } | ||
72 | } | ||
73 | |||
62 | for variant in variants { | 74 | for variant in variants { |
63 | if let Some(path) = module.find_use_path(ctx.db, ModuleDef::from(variant)) { | 75 | if let Some(path) = module.find_use_path(ctx.db, ModuleDef::from(variant)) { |
64 | // Variants with trivial paths are already added by the existing completion logic, | 76 | // Variants with trivial paths are already added by the existing completion logic, |
@@ -729,6 +741,28 @@ fn f() -> m::E { V$0 } | |||
729 | } | 741 | } |
730 | 742 | ||
731 | #[test] | 743 | #[test] |
744 | fn completes_enum_variant_impl() { | ||
745 | check( | ||
746 | r#" | ||
747 | enum Foo { Bar, Baz, Quux } | ||
748 | impl Foo { | ||
749 | fn foo() { match Foo::Bar { Q$0 } } | ||
750 | } | ||
751 | "#, | ||
752 | expect![[r#" | ||
753 | ev Self::Bar () | ||
754 | ev Self::Baz () | ||
755 | ev Self::Quux () | ||
756 | ev Foo::Bar () | ||
757 | ev Foo::Baz () | ||
758 | ev Foo::Quux () | ||
759 | sp Self | ||
760 | en Foo | ||
761 | "#]], | ||
762 | ) | ||
763 | } | ||
764 | |||
765 | #[test] | ||
732 | fn dont_complete_attr() { | 766 | fn dont_complete_attr() { |
733 | check( | 767 | check( |
734 | r#" | 768 | r#" |
diff --git a/crates/completion/src/context.rs b/crates/completion/src/context.rs index b1e8eba85..3db357855 100644 --- a/crates/completion/src/context.rs +++ b/crates/completion/src/context.rs | |||
@@ -276,6 +276,14 @@ impl<'a> CompletionContext<'a> { | |||
276 | }); | 276 | }); |
277 | } | 277 | } |
278 | 278 | ||
279 | fn fill_impl_def(&mut self) { | ||
280 | self.impl_def = self | ||
281 | .sema | ||
282 | .ancestors_with_macros(self.token.parent()) | ||
283 | .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE) | ||
284 | .find_map(ast::Impl::cast); | ||
285 | } | ||
286 | |||
279 | fn fill( | 287 | fn fill( |
280 | &mut self, | 288 | &mut self, |
281 | original_file: &SyntaxNode, | 289 | original_file: &SyntaxNode, |
@@ -345,6 +353,8 @@ impl<'a> CompletionContext<'a> { | |||
345 | self.is_irrefutable_pat_binding = true; | 353 | self.is_irrefutable_pat_binding = true; |
346 | } | 354 | } |
347 | } | 355 | } |
356 | |||
357 | self.fill_impl_def(); | ||
348 | } | 358 | } |
349 | if is_node::<ast::Param>(name.syntax()) { | 359 | if is_node::<ast::Param>(name.syntax()) { |
350 | self.is_param = true; | 360 | self.is_param = true; |
@@ -372,11 +382,7 @@ impl<'a> CompletionContext<'a> { | |||
372 | self.sema.find_node_at_offset_with_macros(&original_file, offset); | 382 | self.sema.find_node_at_offset_with_macros(&original_file, offset); |
373 | } | 383 | } |
374 | 384 | ||
375 | self.impl_def = self | 385 | self.fill_impl_def(); |
376 | .sema | ||
377 | .ancestors_with_macros(self.token.parent()) | ||
378 | .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE) | ||
379 | .find_map(ast::Impl::cast); | ||
380 | 386 | ||
381 | let top_node = name_ref | 387 | let top_node = name_ref |
382 | .syntax() | 388 | .syntax() |