aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2020-12-22 18:00:38 +0000
committerLukas Wirth <[email protected]>2020-12-22 18:00:38 +0000
commit83121efcd577124a992dc8bd304690b36bda2931 (patch)
tree7c936ea2d9ceb39192046ac5cc504a52e6dbcf79
parent2cd2947bf8cb7abfb06ceb00804447def899d37d (diff)
Reduce some more code duplication
-rw-r--r--crates/completion/src/completions/pattern.rs38
-rw-r--r--crates/completion/src/render.rs6
-rw-r--r--crates/completion/src/render/builder_ext.rs1
-rw-r--r--crates/completion/src/render/enum_variant.rs45
-rw-r--r--crates/completion/src/render/pattern.rs80
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 @@
1//! Completes constats and paths in patterns. 1//! Completes constats and paths in patterns.
2 2
3use hir::StructKind;
4
5use crate::{CompletionContext, Completions}; 3use crate::{CompletionContext, Completions};
6 4
7/// Completes constants and paths in patterns. 5/// Completes constants and paths in patterns.
@@ -22,11 +20,7 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
22 acc.add_struct_pat(ctx, strukt.clone(), Some(name.clone())); 20 acc.add_struct_pat(ctx, strukt.clone(), Some(name.clone()));
23 true 21 true
24 } 22 }
25 hir::ModuleDef::Variant(variant) 23 hir::ModuleDef::Variant(variant) if !ctx.is_irrefutable_pat_binding => {
26 if !ctx.is_irrefutable_pat_binding
27 // render_resolution already does some pattern completion tricks for tuple variants
28 && variant.kind(ctx.db) == StructKind::Record =>
29 {
30 acc.add_variant_pat(ctx, variant.clone(), Some(name.clone())); 24 acc.add_variant_pat(ctx, variant.clone(), Some(name.clone()));
31 true 25 true
32 } 26 }
@@ -49,7 +43,10 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
49mod tests { 43mod tests {
50 use expect_test::{expect, Expect}; 44 use expect_test::{expect, Expect};
51 45
52 use crate::{test_utils::completion_list, CompletionKind}; 46 use crate::{
47 test_utils::{check_edit, completion_list},
48 CompletionKind,
49 };
53 50
54 fn check(ra_fixture: &str, expect: Expect) { 51 fn check(ra_fixture: &str, expect: Expect) {
55 let actual = completion_list(ra_fixture, CompletionKind::Reference); 52 let actual = completion_list(ra_fixture, CompletionKind::Reference);
@@ -81,7 +78,7 @@ fn foo() {
81 en E 78 en E
82 ct Z 79 ct Z
83 st Bar 80 st Bar
84 ev X () 81 ev X
85 md m 82 md m
86 "#]], 83 "#]],
87 ); 84 );
@@ -238,4 +235,27 @@ fn outer() {
238 "#]], 235 "#]],
239 ) 236 )
240 } 237 }
238
239 #[test]
240 fn only_shows_ident_completion() {
241 check_edit(
242 "Foo",
243 r#"
244struct Foo(i32);
245fn main() {
246 match Foo(92) {
247 <|>(92) => (),
248 }
249}
250"#,
251 r#"
252struct Foo(i32);
253fn main() {
254 match Foo(92) {
255 Foo(92) => (),
256 }
257}
258"#,
259 );
260 }
241} 261}
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> {
160 let item = render_fn(self.ctx, import_to_add, Some(local_name), *func); 160 let item = render_fn(self.ctx, import_to_add, Some(local_name), *func);
161 return Some(item); 161 return Some(item);
162 } 162 }
163 ScopeDef::ModuleDef(Variant(_))
164 if self.ctx.completion.is_pat_binding_or_const
165 | self.ctx.completion.is_irrefutable_pat_binding =>
166 {
167 CompletionItemKind::EnumVariant
168 }
163 ScopeDef::ModuleDef(Variant(var)) => { 169 ScopeDef::ModuleDef(Variant(var)) => {
164 let item = render_variant(self.ctx, import_to_add, Some(local_name), *var, None); 170 let item = render_variant(self.ctx, import_to_add, Some(local_name), *var, None);
165 return Some(item); 171 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 {
34 return false; 34 return false;
35 } 35 }
36 if ctx.is_pattern_call { 36 if ctx.is_pattern_call {
37 mark::hit!(dont_duplicate_pattern_parens);
38 return false; 37 return false;
39 } 38 }
40 if ctx.is_call { 39 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
@@ -126,50 +126,5 @@ fn main() -> Option<i32> {
126} 126}
127"#, 127"#,
128 ); 128 );
129 check_edit(
130 "Some",
131 r#"
132enum Option<T> { Some(T), None }
133use Option::*;
134fn main(value: Option<i32>) {
135 match value {
136 Som<|>
137 }
138}
139"#,
140 r#"
141enum Option<T> { Some(T), None }
142use Option::*;
143fn main(value: Option<i32>) {
144 match value {
145 Some($0)
146 }
147}
148"#,
149 );
150 }
151
152 #[test]
153 fn dont_duplicate_pattern_parens() {
154 mark::check!(dont_duplicate_pattern_parens);
155 check_edit(
156 "Var",
157 r#"
158enum E { Var(i32) }
159fn main() {
160 match E::Var(92) {
161 E::<|>(92) => (),
162 }
163}
164"#,
165 r#"
166enum E { Var(i32) }
167fn main() {
168 match E::Var(92) {
169 E::Var(92) => (),
170 }
171}
172"#,
173 );
174 } 129 }
175} 130}
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::{
8 CompletionItemKind, 8 CompletionItemKind,
9}; 9};
10 10
11fn visible_fields(
12 ctx: &RenderContext<'_>,
13 fields: &[hir::Field],
14 item: impl HasAttrs,
15) -> Option<(Vec<hir::Field>, bool)> {
16 let module = ctx.completion.scope.module()?;
17 let n_fields = fields.len();
18 let fields = fields
19 .into_iter()
20 .filter(|field| field.is_visible_from(ctx.db(), module))
21 .copied()
22 .collect::<Vec<_>>();
23
24 let fields_omitted =
25 n_fields - fields.len() > 0 || item.attrs(ctx.db()).by_key("non_exhaustive").exists();
26 Some((fields, fields_omitted))
27}
28
11pub(crate) fn render_struct_pat( 29pub(crate) fn render_struct_pat(
12 ctx: RenderContext<'_>, 30 ctx: RenderContext<'_>,
13 strukt: hir::Struct, 31 strukt: hir::Struct,
@@ -15,35 +33,18 @@ pub(crate) fn render_struct_pat(
15) -> Option<CompletionItem> { 33) -> Option<CompletionItem> {
16 let _p = profile::span("render_struct_pat"); 34 let _p = profile::span("render_struct_pat");
17 35
18 let module = ctx.completion.scope.module()?;
19 let fields = strukt.fields(ctx.db()); 36 let fields = strukt.fields(ctx.db());
20 let n_fields = fields.len(); 37 let (visible_fields, fields_omitted) = visible_fields(&ctx, &fields, strukt)?;
21 let fields = fields
22 .into_iter()
23 .filter(|field| field.is_visible_from(ctx.db(), module))
24 .collect::<Vec<_>>();
25 38
26 if fields.is_empty() { 39 if visible_fields.is_empty() {
27 // Matching a struct without matching its fields is pointless, unlike matching a Variant without its fields 40 // Matching a struct without matching its fields is pointless, unlike matching a Variant without its fields
28 return None; 41 return None;
29 } 42 }
30 let fields_omitted =
31 n_fields - fields.len() > 0 || strukt.attrs(ctx.db()).by_key("non_exhaustive").exists();
32 43
33 let name = local_name.unwrap_or_else(|| strukt.name(ctx.db())).to_string(); 44 let name = local_name.unwrap_or_else(|| strukt.name(ctx.db())).to_string();
34 let pat = render_pat(&ctx, &name, strukt.kind(ctx.db()), &fields, fields_omitted)?; 45 let pat = render_pat(&ctx, &name, strukt.kind(ctx.db()), &visible_fields, fields_omitted)?;
35 46
36 let mut completion = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), name) 47 Some(build_completion(ctx, name, pat, strukt))
37 .kind(CompletionItemKind::Binding)
38 .set_documentation(ctx.docs(strukt))
39 .set_deprecated(ctx.is_deprecated(strukt))
40 .detail(&pat);
41 if let Some(snippet_cap) = ctx.snippet_cap() {
42 completion = completion.insert_snippet(snippet_cap, pat);
43 } else {
44 completion = completion.insert_text(pat);
45 }
46 Some(completion.build())
47} 48}
48 49
49pub(crate) fn render_variant_pat( 50pub(crate) fn render_variant_pat(
@@ -53,31 +54,32 @@ pub(crate) fn render_variant_pat(
53) -> Option<CompletionItem> { 54) -> Option<CompletionItem> {
54 let _p = profile::span("render_variant_pat"); 55 let _p = profile::span("render_variant_pat");
55 56
56 let module = ctx.completion.scope.module()?;
57 let fields = variant.fields(ctx.db()); 57 let fields = variant.fields(ctx.db());
58 let n_fields = fields.len(); 58 let (visible_fields, fields_omitted) = visible_fields(&ctx, &fields, variant)?;
59 let fields = fields
60 .into_iter()
61 .filter(|field| field.is_visible_from(ctx.db(), module))
62 .collect::<Vec<_>>();
63
64 let fields_omitted =
65 n_fields - fields.len() > 0 || variant.attrs(ctx.db()).by_key("non_exhaustive").exists();
66 59
67 let name = local_name.unwrap_or_else(|| variant.name(ctx.db())).to_string(); 60 let name = local_name.unwrap_or_else(|| variant.name(ctx.db())).to_string();
68 let pat = render_pat(&ctx, &name, variant.kind(ctx.db()), &fields, fields_omitted)?; 61 let pat = render_pat(&ctx, &name, variant.kind(ctx.db()), &visible_fields, fields_omitted)?;
69 62
70 let mut completion = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), name) 63 Some(build_completion(ctx, name, pat, variant))
64}
65
66fn build_completion(
67 ctx: RenderContext<'_>,
68 name: String,
69 pat: String,
70 item: impl HasAttrs + Copy,
71) -> CompletionItem {
72 let completion = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), name)
71 .kind(CompletionItemKind::Binding) 73 .kind(CompletionItemKind::Binding)
72 .set_documentation(ctx.docs(variant)) 74 .set_documentation(ctx.docs(item))
73 .set_deprecated(ctx.is_deprecated(variant)) 75 .set_deprecated(ctx.is_deprecated(item))
74 .detail(&pat); 76 .detail(&pat);
75 if let Some(snippet_cap) = ctx.snippet_cap() { 77 let completion = if let Some(snippet_cap) = ctx.snippet_cap() {
76 completion = completion.insert_snippet(snippet_cap, pat); 78 completion.insert_snippet(snippet_cap, pat)
77 } else { 79 } else {
78 completion = completion.insert_text(pat); 80 completion.insert_text(pat)
79 } 81 };
80 Some(completion.build()) 82 completion.build()
81} 83}
82 84
83fn render_pat( 85fn render_pat(