aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src/completions/pattern.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2021-02-17 14:53:31 +0000
committerAleksey Kladov <[email protected]>2021-02-17 14:53:31 +0000
commit3db64a400c78bbd2708e67ddc07df1001fff3f29 (patch)
tree5386aab9c452981be09bc3e4362643a34e6e3617 /crates/ide_completion/src/completions/pattern.rs
parent6334ce866ab095215381c4b72692b20a84d26e96 (diff)
rename completion -> ide_completion
We don't have completion-related PRs in flight, so lets do it
Diffstat (limited to 'crates/ide_completion/src/completions/pattern.rs')
-rw-r--r--crates/ide_completion/src/completions/pattern.rs317
1 files changed, 317 insertions, 0 deletions
diff --git a/crates/ide_completion/src/completions/pattern.rs b/crates/ide_completion/src/completions/pattern.rs
new file mode 100644
index 000000000..9282c3827
--- /dev/null
+++ b/crates/ide_completion/src/completions/pattern.rs
@@ -0,0 +1,317 @@
1//! Completes constats and paths in patterns.
2
3use crate::{CompletionContext, Completions};
4
5/// Completes constants and paths in patterns.
6pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
7 if !(ctx.is_pat_binding_or_const || ctx.is_irrefutable_pat_binding) {
8 return;
9 }
10 if ctx.record_pat_syntax.is_some() {
11 return;
12 }
13
14 if let Some(ty) = &ctx.expected_type {
15 super::complete_enum_variants(acc, ctx, ty, |acc, ctx, variant, path| {
16 acc.add_qualified_variant_pat(ctx, variant, path)
17 });
18 }
19
20 // FIXME: ideally, we should look at the type we are matching against and
21 // suggest variants + auto-imports
22 ctx.scope.process_all_names(&mut |name, res| {
23 let add_resolution = match &res {
24 hir::ScopeDef::ModuleDef(def) => match def {
25 hir::ModuleDef::Adt(hir::Adt::Struct(strukt)) => {
26 acc.add_struct_pat(ctx, strukt.clone(), Some(name.clone()));
27 true
28 }
29 hir::ModuleDef::Variant(variant) if !ctx.is_irrefutable_pat_binding => {
30 acc.add_variant_pat(ctx, variant.clone(), Some(name.clone()));
31 true
32 }
33 hir::ModuleDef::Adt(hir::Adt::Enum(..))
34 | hir::ModuleDef::Variant(..)
35 | hir::ModuleDef::Const(..)
36 | hir::ModuleDef::Module(..) => !ctx.is_irrefutable_pat_binding,
37 _ => false,
38 },
39 hir::ScopeDef::MacroDef(_) => true,
40 hir::ScopeDef::ImplSelfType(impl_) => match impl_.target_ty(ctx.db).as_adt() {
41 Some(hir::Adt::Struct(strukt)) => {
42 acc.add_struct_pat(ctx, strukt, Some(name.clone()));
43 true
44 }
45 Some(hir::Adt::Enum(_)) => !ctx.is_irrefutable_pat_binding,
46 _ => true,
47 },
48 _ => false,
49 };
50 if add_resolution {
51 acc.add_resolution(ctx, name.to_string(), &res);
52 }
53 });
54}
55
56#[cfg(test)]
57mod tests {
58 use expect_test::{expect, Expect};
59
60 use crate::{
61 test_utils::{check_edit, completion_list},
62 CompletionKind,
63 };
64
65 fn check(ra_fixture: &str, expect: Expect) {
66 let actual = completion_list(ra_fixture, CompletionKind::Reference);
67 expect.assert_eq(&actual)
68 }
69
70 fn check_snippet(ra_fixture: &str, expect: Expect) {
71 let actual = completion_list(ra_fixture, CompletionKind::Snippet);
72 expect.assert_eq(&actual)
73 }
74
75 #[test]
76 fn completes_enum_variants_and_modules() {
77 check(
78 r#"
79enum E { X }
80use self::E::X;
81const Z: E = E::X;
82mod m {}
83
84static FOO: E = E::X;
85struct Bar { f: u32 }
86
87fn foo() {
88 match E::X { $0 }
89}
90"#,
91 expect![[r#"
92 en E
93 ct Z
94 st Bar
95 ev X
96 md m
97 "#]],
98 );
99 }
100
101 #[test]
102 fn completes_in_simple_macro_call() {
103 check(
104 r#"
105macro_rules! m { ($e:expr) => { $e } }
106enum E { X }
107
108fn foo() {
109 m!(match E::X { $0 })
110}
111"#,
112 expect![[r#"
113 en E
114 ma m!(…) macro_rules! m
115 "#]],
116 );
117 }
118
119 #[test]
120 fn completes_in_irrefutable_let() {
121 check(
122 r#"
123enum E { X }
124use self::E::X;
125const Z: E = E::X;
126mod m {}
127
128static FOO: E = E::X;
129struct Bar { f: u32 }
130
131fn foo() {
132 let $0
133}
134"#,
135 expect![[r#"
136 st Bar
137 "#]],
138 );
139 }
140
141 #[test]
142 fn completes_in_param() {
143 check(
144 r#"
145enum E { X }
146
147static FOO: E = E::X;
148struct Bar { f: u32 }
149
150fn foo($0) {
151}
152"#,
153 expect![[r#"
154 st Bar
155 "#]],
156 );
157 }
158
159 #[test]
160 fn completes_pat_in_let() {
161 check_snippet(
162 r#"
163struct Bar { f: u32 }
164
165fn foo() {
166 let $0
167}
168"#,
169 expect![[r#"
170 bn Bar Bar { f$1 }$0
171 "#]],
172 );
173 }
174
175 #[test]
176 fn completes_param_pattern() {
177 check_snippet(
178 r#"
179struct Foo { bar: String, baz: String }
180struct Bar(String, String);
181struct Baz;
182fn outer($0) {}
183"#,
184 expect![[r#"
185 bn Foo Foo { bar$1, baz$2 }: Foo$0
186 bn Bar Bar($1, $2): Bar$0
187 "#]],
188 )
189 }
190
191 #[test]
192 fn completes_let_pattern() {
193 check_snippet(
194 r#"
195struct Foo { bar: String, baz: String }
196struct Bar(String, String);
197struct Baz;
198fn outer() {
199 let $0
200}
201"#,
202 expect![[r#"
203 bn Foo Foo { bar$1, baz$2 }$0
204 bn Bar Bar($1, $2)$0
205 "#]],
206 )
207 }
208
209 #[test]
210 fn completes_refutable_pattern() {
211 check_snippet(
212 r#"
213struct Foo { bar: i32, baz: i32 }
214struct Bar(String, String);
215struct Baz;
216fn outer() {
217 match () {
218 $0
219 }
220}
221"#,
222 expect![[r#"
223 bn Foo Foo { bar$1, baz$2 }$0
224 bn Bar Bar($1, $2)$0
225 "#]],
226 )
227 }
228
229 #[test]
230 fn omits_private_fields_pat() {
231 check_snippet(
232 r#"
233mod foo {
234 pub struct Foo { pub bar: i32, baz: i32 }
235 pub struct Bar(pub String, String);
236 pub struct Invisible(String, String);
237}
238use foo::*;
239
240fn outer() {
241 match () {
242 $0
243 }
244}
245"#,
246 expect![[r#"
247 bn Foo Foo { bar$1, .. }$0
248 bn Bar Bar($1, ..)$0
249 "#]],
250 )
251 }
252
253 #[test]
254 fn only_shows_ident_completion() {
255 check_edit(
256 "Foo",
257 r#"
258struct Foo(i32);
259fn main() {
260 match Foo(92) {
261 $0(92) => (),
262 }
263}
264"#,
265 r#"
266struct Foo(i32);
267fn main() {
268 match Foo(92) {
269 Foo(92) => (),
270 }
271}
272"#,
273 );
274 }
275
276 #[test]
277 fn completes_self_pats() {
278 check_snippet(
279 r#"
280struct Foo(i32);
281impl Foo {
282 fn foo() {
283 match () {
284 $0
285 }
286 }
287}
288 "#,
289 expect![[r#"
290 bn Self Self($1)$0
291 bn Foo Foo($1)$0
292 "#]],
293 )
294 }
295
296 #[test]
297 fn completes_qualified_variant() {
298 check_snippet(
299 r#"
300enum Foo {
301 Bar { baz: i32 }
302}
303impl Foo {
304 fn foo() {
305 match {Foo::Bar { baz: 0 }} {
306 B$0
307 }
308 }
309}
310 "#,
311 expect![[r#"
312 bn Self::Bar Self::Bar { baz$1 }$0
313 bn Foo::Bar Foo::Bar { baz$1 }$0
314 "#]],
315 )
316 }
317}