From 83121efcd577124a992dc8bd304690b36bda2931 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 22 Dec 2020 19:00:38 +0100 Subject: Reduce some more code duplication --- crates/completion/src/completions/pattern.rs | 38 +++++++++---- crates/completion/src/render.rs | 6 +++ crates/completion/src/render/builder_ext.rs | 1 - crates/completion/src/render/enum_variant.rs | 45 ---------------- crates/completion/src/render/pattern.rs | 80 ++++++++++++++-------------- 5 files changed, 76 insertions(+), 94 deletions(-) diff --git a/crates/completion/src/completions/pattern.rs b/crates/completion/src/completions/pattern.rs index ba9921a44..eee31098d 100644 --- a/crates/completion/src/completions/pattern.rs +++ b/crates/completion/src/completions/pattern.rs @@ -1,7 +1,5 @@ //! Completes constats and paths in patterns. -use hir::StructKind; - use crate::{CompletionContext, Completions}; /// Completes constants and paths in patterns. @@ -22,11 +20,7 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { acc.add_struct_pat(ctx, strukt.clone(), Some(name.clone())); true } - hir::ModuleDef::Variant(variant) - if !ctx.is_irrefutable_pat_binding - // render_resolution already does some pattern completion tricks for tuple variants - && variant.kind(ctx.db) == StructKind::Record => - { + hir::ModuleDef::Variant(variant) if !ctx.is_irrefutable_pat_binding => { acc.add_variant_pat(ctx, variant.clone(), Some(name.clone())); true } @@ -49,7 +43,10 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { mod tests { use expect_test::{expect, Expect}; - use crate::{test_utils::completion_list, CompletionKind}; + use crate::{ + test_utils::{check_edit, completion_list}, + CompletionKind, + }; fn check(ra_fixture: &str, expect: Expect) { let actual = completion_list(ra_fixture, CompletionKind::Reference); @@ -81,7 +78,7 @@ fn foo() { en E ct Z st Bar - ev X () + ev X md m "#]], ); @@ -238,4 +235,27 @@ fn outer() { "#]], ) } + + #[test] + fn only_shows_ident_completion() { + check_edit( + "Foo", + r#" +struct Foo(i32); +fn main() { + match Foo(92) { + <|>(92) => (), + } +} +"#, + r#" +struct Foo(i32); +fn main() { + match Foo(92) { + Foo(92) => (), + } +} +"#, + ); + } } diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs index 945158d10..1ba7201a1 100644 --- a/crates/completion/src/render.rs +++ b/crates/completion/src/render.rs @@ -160,6 +160,12 @@ impl<'a> Render<'a> { let item = render_fn(self.ctx, import_to_add, Some(local_name), *func); return Some(item); } + ScopeDef::ModuleDef(Variant(_)) + if self.ctx.completion.is_pat_binding_or_const + | self.ctx.completion.is_irrefutable_pat_binding => + { + CompletionItemKind::EnumVariant + } ScopeDef::ModuleDef(Variant(var)) => { let item = render_variant(self.ctx, import_to_add, Some(local_name), *var, None); return Some(item); diff --git a/crates/completion/src/render/builder_ext.rs b/crates/completion/src/render/builder_ext.rs index ce8718bd5..d053a988b 100644 --- a/crates/completion/src/render/builder_ext.rs +++ b/crates/completion/src/render/builder_ext.rs @@ -34,7 +34,6 @@ impl Builder { return false; } if ctx.is_pattern_call { - mark::hit!(dont_duplicate_pattern_parens); return false; } if ctx.is_call { diff --git a/crates/completion/src/render/enum_variant.rs b/crates/completion/src/render/enum_variant.rs index 7176fd9b3..732e139ec 100644 --- a/crates/completion/src/render/enum_variant.rs +++ b/crates/completion/src/render/enum_variant.rs @@ -124,51 +124,6 @@ use Option::*; fn main() -> Option { Some($0) } -"#, - ); - check_edit( - "Some", - r#" -enum Option { Some(T), None } -use Option::*; -fn main(value: Option) { - match value { - Som<|> - } -} -"#, - r#" -enum Option { Some(T), None } -use Option::*; -fn main(value: Option) { - match value { - Some($0) - } -} -"#, - ); - } - - #[test] - fn dont_duplicate_pattern_parens() { - mark::check!(dont_duplicate_pattern_parens); - check_edit( - "Var", - r#" -enum E { Var(i32) } -fn main() { - match E::Var(92) { - E::<|>(92) => (), - } -} -"#, - r#" -enum E { Var(i32) } -fn main() { - match E::Var(92) { - E::Var(92) => (), - } -} "#, ); } diff --git a/crates/completion/src/render/pattern.rs b/crates/completion/src/render/pattern.rs index 073d50a11..a3b6a3cac 100644 --- a/crates/completion/src/render/pattern.rs +++ b/crates/completion/src/render/pattern.rs @@ -8,6 +8,24 @@ use crate::{ CompletionItemKind, }; +fn visible_fields( + ctx: &RenderContext<'_>, + fields: &[hir::Field], + item: impl HasAttrs, +) -> Option<(Vec, bool)> { + let module = ctx.completion.scope.module()?; + let n_fields = fields.len(); + let fields = fields + .into_iter() + .filter(|field| field.is_visible_from(ctx.db(), module)) + .copied() + .collect::>(); + + let fields_omitted = + n_fields - fields.len() > 0 || item.attrs(ctx.db()).by_key("non_exhaustive").exists(); + Some((fields, fields_omitted)) +} + pub(crate) fn render_struct_pat( ctx: RenderContext<'_>, strukt: hir::Struct, @@ -15,35 +33,18 @@ pub(crate) fn render_struct_pat( ) -> Option { let _p = profile::span("render_struct_pat"); - let module = ctx.completion.scope.module()?; let fields = strukt.fields(ctx.db()); - let n_fields = fields.len(); - let fields = fields - .into_iter() - .filter(|field| field.is_visible_from(ctx.db(), module)) - .collect::>(); + let (visible_fields, fields_omitted) = visible_fields(&ctx, &fields, strukt)?; - if fields.is_empty() { + if visible_fields.is_empty() { // Matching a struct without matching its fields is pointless, unlike matching a Variant without its fields return None; } - let fields_omitted = - n_fields - fields.len() > 0 || strukt.attrs(ctx.db()).by_key("non_exhaustive").exists(); let name = local_name.unwrap_or_else(|| strukt.name(ctx.db())).to_string(); - let pat = render_pat(&ctx, &name, strukt.kind(ctx.db()), &fields, fields_omitted)?; + let pat = render_pat(&ctx, &name, strukt.kind(ctx.db()), &visible_fields, fields_omitted)?; - let mut completion = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), name) - .kind(CompletionItemKind::Binding) - .set_documentation(ctx.docs(strukt)) - .set_deprecated(ctx.is_deprecated(strukt)) - .detail(&pat); - if let Some(snippet_cap) = ctx.snippet_cap() { - completion = completion.insert_snippet(snippet_cap, pat); - } else { - completion = completion.insert_text(pat); - } - Some(completion.build()) + Some(build_completion(ctx, name, pat, strukt)) } pub(crate) fn render_variant_pat( @@ -53,31 +54,32 @@ pub(crate) fn render_variant_pat( ) -> Option { let _p = profile::span("render_variant_pat"); - let module = ctx.completion.scope.module()?; let fields = variant.fields(ctx.db()); - let n_fields = fields.len(); - let fields = fields - .into_iter() - .filter(|field| field.is_visible_from(ctx.db(), module)) - .collect::>(); - - let fields_omitted = - n_fields - fields.len() > 0 || variant.attrs(ctx.db()).by_key("non_exhaustive").exists(); + let (visible_fields, fields_omitted) = visible_fields(&ctx, &fields, variant)?; let name = local_name.unwrap_or_else(|| variant.name(ctx.db())).to_string(); - let pat = render_pat(&ctx, &name, variant.kind(ctx.db()), &fields, fields_omitted)?; + let pat = render_pat(&ctx, &name, variant.kind(ctx.db()), &visible_fields, fields_omitted)?; - let mut completion = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), name) + Some(build_completion(ctx, name, pat, variant)) +} + +fn build_completion( + ctx: RenderContext<'_>, + name: String, + pat: String, + item: impl HasAttrs + Copy, +) -> CompletionItem { + let completion = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), name) .kind(CompletionItemKind::Binding) - .set_documentation(ctx.docs(variant)) - .set_deprecated(ctx.is_deprecated(variant)) + .set_documentation(ctx.docs(item)) + .set_deprecated(ctx.is_deprecated(item)) .detail(&pat); - if let Some(snippet_cap) = ctx.snippet_cap() { - completion = completion.insert_snippet(snippet_cap, pat); + let completion = if let Some(snippet_cap) = ctx.snippet_cap() { + completion.insert_snippet(snippet_cap, pat) } else { - completion = completion.insert_text(pat); - } - Some(completion.build()) + completion.insert_text(pat) + }; + completion.build() } fn render_pat( -- cgit v1.2.3