From 5454559c0a45d208db963df105f22f5e17f0340a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 9 Feb 2021 21:32:05 +0100 Subject: Show qualified variant pattern completions --- crates/completion/src/completions/pattern.rs | 28 +++++++++++++ .../completion/src/completions/unqualified_path.rs | 46 ++-------------------- 2 files changed, 32 insertions(+), 42 deletions(-) (limited to 'crates/completion/src/completions') diff --git a/crates/completion/src/completions/pattern.rs b/crates/completion/src/completions/pattern.rs index 43a5160cb..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) { return; } + if let Some(ty) = &ctx.expected_type { + super::complete_enum_variants(acc, ctx, ty, |acc, ctx, variant, path| { + acc.add_qualified_variant_pat(ctx, variant, path) + }); + } + // FIXME: ideally, we should look at the type we are matching against and // suggest variants + auto-imports ctx.scope.process_all_names(&mut |name, res| { @@ -286,4 +292,26 @@ impl Foo { "#]], ) } + + #[test] + fn completes_qualified_variant() { + check_snippet( + r#" +enum Foo { + Bar { baz: i32 } +} +impl Foo { + fn foo() { + match {Foo::Bar { baz: 0 }} { + B$0 + } + } +} + "#, + expect![[r#" + bn Self::Bar Self::Bar { baz$1 }$0 + bn Foo::Bar Foo::Bar { baz$1 }$0 + "#]], + ) + } } diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs index 5112ecc2d..e9d0ff665 100644 --- a/crates/completion/src/completions/unqualified_path.rs +++ b/crates/completion/src/completions/unqualified_path.rs @@ -1,8 +1,6 @@ //! Completion of names from the current scope, e.g. locals and imported items. -use std::iter; - -use hir::{known, Adt, ModuleDef, ScopeDef, Type}; +use hir::ScopeDef; use syntax::AstNode; use test_utils::mark; @@ -21,7 +19,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC } if let Some(ty) = &ctx.expected_type { - complete_enum_variants(acc, ctx, ty); + super::complete_enum_variants(acc, ctx, ty, |acc, ctx, variant, path| { + acc.add_qualified_enum_variant(ctx, variant, path) + }); } if ctx.is_pat_binding_or_const { @@ -45,44 +45,6 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC }); } -fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) { - if let Some(Adt::Enum(enum_data)) = - iter::successors(Some(ty.clone()), |ty| ty.remove_ref()).last().and_then(|ty| ty.as_adt()) - { - let variants = enum_data.variants(ctx.db); - - let module = if let Some(module) = ctx.scope.module() { - // Compute path from the completion site if available. - module - } else { - // Otherwise fall back to the enum's definition site. - 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, - // so we should avoid adding these twice - if path.segments().len() > 1 { - acc.add_qualified_enum_variant(ctx, variant, path); - } - } - } - } -} - #[cfg(test)] mod tests { use expect_test::{expect, Expect}; -- cgit v1.2.3