ra_ap_completion/completions/
pattern.rs

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}