From 2f171ca78d306d105a9e36f8e509039d6a034c8e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 9 Feb 2021 19:04:39 +0100 Subject: Show completions for enum variant with self prefix if inside impl --- .../completion/src/completions/unqualified_path.rs | 36 +++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'crates/completion') diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs index e2482f959..fb67756bb 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, @@ -728,6 +740,28 @@ fn f() -> m::E { V$0 } ) } + #[test] + fn completes_enum_variant_impl() { + check( + r#" +enum Foo { Bar, Baz, Quux } +impl Foo { + fn foo() { let foo: Foo = 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( -- cgit v1.2.3 From e92180a1d8c964d386fc5ffb80bfb05abdb6c153 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 9 Feb 2021 19:47:21 +0100 Subject: Show Self pattern completions for Adts if inside impls --- crates/completion/src/completions/pattern.rs | 28 ++++++++++++++++++++++ .../completion/src/completions/unqualified_path.rs | 2 +- crates/completion/src/context.rs | 16 +++++++++---- 3 files changed, 40 insertions(+), 6 deletions(-) (limited to 'crates/completion') 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) { _ => 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 fb67756bb..5112ecc2d 100644 --- a/crates/completion/src/completions/unqualified_path.rs +++ b/crates/completion/src/completions/unqualified_path.rs @@ -746,7 +746,7 @@ fn f() -> m::E { V$0 } r#" enum Foo { Bar, Baz, Quux } impl Foo { - fn foo() { let foo: Foo = Q$0 } + fn foo() { match Foo::Bar { Q$0 } } } "#, expect![[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> { }); } + 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::(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() -- cgit v1.2.3