diff options
Diffstat (limited to 'crates/completion/src/completions')
-rw-r--r-- | crates/completion/src/completions/pattern.rs | 56 | ||||
-rw-r--r-- | crates/completion/src/completions/unqualified_path.rs | 56 |
2 files changed, 82 insertions, 30 deletions
diff --git a/crates/completion/src/completions/pattern.rs b/crates/completion/src/completions/pattern.rs index 595160ff5..9282c3827 100644 --- a/crates/completion/src/completions/pattern.rs +++ b/crates/completion/src/completions/pattern.rs | |||
@@ -11,6 +11,12 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { | |||
11 | return; | 11 | return; |
12 | } | 12 | } |
13 | 13 | ||
14 | if let Some(ty) = &ctx.expected_type { | ||
15 | super::complete_enum_variants(acc, ctx, ty, |acc, ctx, variant, path| { | ||
16 | acc.add_qualified_variant_pat(ctx, variant, path) | ||
17 | }); | ||
18 | } | ||
19 | |||
14 | // FIXME: ideally, we should look at the type we are matching against and | 20 | // FIXME: ideally, we should look at the type we are matching against and |
15 | // suggest variants + auto-imports | 21 | // suggest variants + auto-imports |
16 | ctx.scope.process_all_names(&mut |name, res| { | 22 | ctx.scope.process_all_names(&mut |name, res| { |
@@ -31,6 +37,14 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { | |||
31 | _ => false, | 37 | _ => false, |
32 | }, | 38 | }, |
33 | hir::ScopeDef::MacroDef(_) => true, | 39 | hir::ScopeDef::MacroDef(_) => true, |
40 | hir::ScopeDef::ImplSelfType(impl_) => match impl_.target_ty(ctx.db).as_adt() { | ||
41 | Some(hir::Adt::Struct(strukt)) => { | ||
42 | acc.add_struct_pat(ctx, strukt, Some(name.clone())); | ||
43 | true | ||
44 | } | ||
45 | Some(hir::Adt::Enum(_)) => !ctx.is_irrefutable_pat_binding, | ||
46 | _ => true, | ||
47 | }, | ||
34 | _ => false, | 48 | _ => false, |
35 | }; | 49 | }; |
36 | if add_resolution { | 50 | if add_resolution { |
@@ -258,4 +272,46 @@ fn main() { | |||
258 | "#, | 272 | "#, |
259 | ); | 273 | ); |
260 | } | 274 | } |
275 | |||
276 | #[test] | ||
277 | fn completes_self_pats() { | ||
278 | check_snippet( | ||
279 | r#" | ||
280 | struct Foo(i32); | ||
281 | impl Foo { | ||
282 | fn foo() { | ||
283 | match () { | ||
284 | $0 | ||
285 | } | ||
286 | } | ||
287 | } | ||
288 | "#, | ||
289 | expect![[r#" | ||
290 | bn Self Self($1)$0 | ||
291 | bn Foo Foo($1)$0 | ||
292 | "#]], | ||
293 | ) | ||
294 | } | ||
295 | |||
296 | #[test] | ||
297 | fn completes_qualified_variant() { | ||
298 | check_snippet( | ||
299 | r#" | ||
300 | enum Foo { | ||
301 | Bar { baz: i32 } | ||
302 | } | ||
303 | impl Foo { | ||
304 | fn foo() { | ||
305 | match {Foo::Bar { baz: 0 }} { | ||
306 | B$0 | ||
307 | } | ||
308 | } | ||
309 | } | ||
310 | "#, | ||
311 | expect![[r#" | ||
312 | bn Self::Bar Self::Bar { baz$1 }$0 | ||
313 | bn Foo::Bar Foo::Bar { baz$1 }$0 | ||
314 | "#]], | ||
315 | ) | ||
316 | } | ||
261 | } | 317 | } |
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs index e2482f959..e9d0ff665 100644 --- a/crates/completion/src/completions/unqualified_path.rs +++ b/crates/completion/src/completions/unqualified_path.rs | |||
@@ -1,8 +1,6 @@ | |||
1 | //! Completion of names from the current scope, e.g. locals and imported items. | 1 | //! Completion of names from the current scope, e.g. locals and imported items. |
2 | 2 | ||
3 | use std::iter; | 3 | use hir::ScopeDef; |
4 | |||
5 | use hir::{Adt, ModuleDef, ScopeDef, Type}; | ||
6 | use syntax::AstNode; | 4 | use syntax::AstNode; |
7 | use test_utils::mark; | 5 | use test_utils::mark; |
8 | 6 | ||
@@ -21,7 +19,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC | |||
21 | } | 19 | } |
22 | 20 | ||
23 | if let Some(ty) = &ctx.expected_type { | 21 | if let Some(ty) = &ctx.expected_type { |
24 | complete_enum_variants(acc, ctx, ty); | 22 | super::complete_enum_variants(acc, ctx, ty, |acc, ctx, variant, path| { |
23 | acc.add_qualified_enum_variant(ctx, variant, path) | ||
24 | }); | ||
25 | } | 25 | } |
26 | 26 | ||
27 | if ctx.is_pat_binding_or_const { | 27 | if ctx.is_pat_binding_or_const { |
@@ -45,32 +45,6 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC | |||
45 | }); | 45 | }); |
46 | } | 46 | } |
47 | 47 | ||
48 | fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) { | ||
49 | if let Some(Adt::Enum(enum_data)) = | ||
50 | iter::successors(Some(ty.clone()), |ty| ty.remove_ref()).last().and_then(|ty| ty.as_adt()) | ||
51 | { | ||
52 | let variants = enum_data.variants(ctx.db); | ||
53 | |||
54 | let module = if let Some(module) = ctx.scope.module() { | ||
55 | // Compute path from the completion site if available. | ||
56 | module | ||
57 | } else { | ||
58 | // Otherwise fall back to the enum's definition site. | ||
59 | enum_data.module(ctx.db) | ||
60 | }; | ||
61 | |||
62 | for variant in variants { | ||
63 | 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, | ||
65 | // so we should avoid adding these twice | ||
66 | if path.segments().len() > 1 { | ||
67 | acc.add_qualified_enum_variant(ctx, variant, path); | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | } | ||
73 | |||
74 | #[cfg(test)] | 48 | #[cfg(test)] |
75 | mod tests { | 49 | mod tests { |
76 | use expect_test::{expect, Expect}; | 50 | use expect_test::{expect, Expect}; |
@@ -729,6 +703,28 @@ fn f() -> m::E { V$0 } | |||
729 | } | 703 | } |
730 | 704 | ||
731 | #[test] | 705 | #[test] |
706 | fn completes_enum_variant_impl() { | ||
707 | check( | ||
708 | r#" | ||
709 | enum Foo { Bar, Baz, Quux } | ||
710 | impl Foo { | ||
711 | fn foo() { match Foo::Bar { Q$0 } } | ||
712 | } | ||
713 | "#, | ||
714 | expect![[r#" | ||
715 | ev Self::Bar () | ||
716 | ev Self::Baz () | ||
717 | ev Self::Quux () | ||
718 | ev Foo::Bar () | ||
719 | ev Foo::Baz () | ||
720 | ev Foo::Quux () | ||
721 | sp Self | ||
722 | en Foo | ||
723 | "#]], | ||
724 | ) | ||
725 | } | ||
726 | |||
727 | #[test] | ||
732 | fn dont_complete_attr() { | 728 | fn dont_complete_attr() { |
733 | check( | 729 | check( |
734 | r#" | 730 | r#" |