From ee06c07f50fe590c5185807daa19de1d5540e66b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 25 Nov 2020 23:25:10 +0100 Subject: Complete struct in irrefutable let --- crates/completion/src/completions/pattern.rs | 57 +++++++++++++++++++++------- crates/completion/src/context.rs | 3 ++ 2 files changed, 46 insertions(+), 14 deletions(-) (limited to 'crates/completion/src') diff --git a/crates/completion/src/completions/pattern.rs b/crates/completion/src/completions/pattern.rs index 7ab7f09fe..4f63ff0ef 100644 --- a/crates/completion/src/completions/pattern.rs +++ b/crates/completion/src/completions/pattern.rs @@ -4,7 +4,7 @@ use crate::{CompletionContext, Completions}; /// Completes constats and paths in patterns. pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { - if !ctx.is_pat_binding_or_const { + if !(ctx.is_pat_binding_or_const || ctx.is_irrefutable_let_pat_binding) { return; } if ctx.record_pat_syntax.is_some() { @@ -14,20 +14,27 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { // 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| { - match &res { - hir::ScopeDef::ModuleDef(def) => match def { - hir::ModuleDef::Adt(hir::Adt::Enum(..)) - | hir::ModuleDef::Adt(hir::Adt::Struct(..)) - | hir::ModuleDef::EnumVariant(..) - | hir::ModuleDef::Const(..) - | hir::ModuleDef::Module(..) => (), - _ => return, - }, - hir::ScopeDef::MacroDef(_) => (), - _ => return, + let add_resolution = match &res { + hir::ScopeDef::ModuleDef(def) => { + if ctx.is_irrefutable_let_pat_binding { + matches!(def, hir::ModuleDef::Adt(hir::Adt::Struct(_))) + } else { + matches!( + def, + hir::ModuleDef::Adt(hir::Adt::Enum(..)) + | hir::ModuleDef::Adt(hir::Adt::Struct(..)) + | hir::ModuleDef::EnumVariant(..) + | hir::ModuleDef::Const(..) + | hir::ModuleDef::Module(..) + ) + } + } + hir::ScopeDef::MacroDef(_) => true, + _ => false, }; - - acc.add_resolution(ctx, name.to_string(), &res) + if add_resolution { + acc.add_resolution(ctx, name.to_string(), &res); + } }); } @@ -85,4 +92,26 @@ fn foo() { "#]], ); } + + #[test] + fn completes_in_irrefutable_let() { + check( + r#" +enum E { X } +use self::E::X; +const Z: E = E::X; +mod m {} + +static FOO: E = E::X; +struct Bar { f: u32 } + +fn foo() { + let <|> +} +"#, + expect![[r#" + st Bar + "#]], + ); + } } diff --git a/crates/completion/src/context.rs b/crates/completion/src/context.rs index bf70ee478..5cd11cf77 100644 --- a/crates/completion/src/context.rs +++ b/crates/completion/src/context.rs @@ -51,6 +51,7 @@ pub(crate) struct CompletionContext<'a> { /// If a name-binding or reference to a const in a pattern. /// Irrefutable patterns (like let) are excluded. pub(super) is_pat_binding_or_const: bool, + pub(super) is_irrefutable_let_pat_binding: bool, /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path. pub(super) is_trivial_path: bool, /// If not a trivial path, the prefix (qualifier). @@ -146,6 +147,7 @@ impl<'a> CompletionContext<'a> { active_parameter: ActiveParameter::at(db, position), is_param: false, is_pat_binding_or_const: false, + is_irrefutable_let_pat_binding: false, is_trivial_path: false, path_qual: None, after_if: false, @@ -330,6 +332,7 @@ impl<'a> CompletionContext<'a> { if pat.syntax().text_range().contains_range(bind_pat.syntax().text_range()) { self.is_pat_binding_or_const = false; + self.is_irrefutable_let_pat_binding = true; } } } -- cgit v1.2.3