]> git.lizzy.rs Git - rust.git/blob - crates/ide_completion/src/completions/record.rs
Merge #7707
[rust.git] / crates / ide_completion / src / completions / record.rs
1 //! Complete fields in record literals and patterns.
2 use ide_db::{helpers::FamousDefs, SymbolKind};
3 use syntax::ast::Expr;
4
5 use crate::{item::CompletionKind, CompletionContext, CompletionItem, Completions};
6
7 pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
8     let missing_fields = match (ctx.record_pat_syntax.as_ref(), ctx.record_lit_syntax.as_ref()) {
9         (None, None) => return None,
10         (Some(_), Some(_)) => unreachable!("A record cannot be both a literal and a pattern"),
11         (Some(record_pat), _) => ctx.sema.record_pattern_missing_fields(record_pat),
12         (_, Some(record_lit)) => {
13             let ty = ctx.sema.type_of_expr(&Expr::RecordExpr(record_lit.clone()));
14             let default_trait = FamousDefs(&ctx.sema, ctx.krate).core_default_Default();
15             let impl_default_trait = default_trait
16                 .and_then(|default_trait| ty.map(|ty| ty.impls_trait(ctx.db, default_trait, &[])))
17                 .unwrap_or(false);
18
19             let missing_fields = ctx.sema.record_literal_missing_fields(record_lit);
20             if impl_default_trait && !missing_fields.is_empty() {
21                 let completion_text = "..Default::default()";
22                 let completion_text = completion_text
23                     .strip_prefix(ctx.token.to_string().as_str())
24                     .unwrap_or(completion_text);
25                 acc.add(
26                     CompletionItem::new(
27                         CompletionKind::Snippet,
28                         ctx.source_range(),
29                         "..Default::default()",
30                     )
31                     .insert_text(completion_text)
32                     .kind(SymbolKind::Field)
33                     .build(),
34                 );
35             }
36
37             missing_fields
38         }
39     };
40
41     for (field, ty) in missing_fields {
42         acc.add_field(ctx, field, &ty);
43     }
44
45     Some(())
46 }
47
48 #[cfg(test)]
49 mod tests {
50     use expect_test::{expect, Expect};
51     use ide_db::helpers::FamousDefs;
52
53     use crate::{
54         test_utils::{self, completion_list},
55         CompletionKind,
56     };
57
58     fn check(ra_fixture: &str, expect: Expect) {
59         let actual = completion_list(ra_fixture, CompletionKind::Reference);
60         expect.assert_eq(&actual);
61     }
62
63     fn check_snippet(ra_fixture: &str, expect: Expect) {
64         let actual = completion_list(
65             &format!("//- /main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE),
66             CompletionKind::Snippet,
67         );
68         expect.assert_eq(&actual);
69     }
70
71     fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
72         test_utils::check_edit(
73             what,
74             &format!(
75                 "//- /main.rs crate:main deps:core{}\n{}",
76                 ra_fixture_before,
77                 FamousDefs::FIXTURE,
78             ),
79             &(ra_fixture_after.to_owned() + "\n"),
80         );
81     }
82
83     #[test]
84     fn test_record_literal_field_default() {
85         let test_code = r#"
86 struct S { foo: u32, bar: usize }
87
88 impl core::default::Default for S {
89     fn default() -> Self {
90         S {
91             foo: 0,
92             bar: 0,
93         }
94     }
95 }
96
97 fn process(f: S) {
98     let other = S {
99         foo: 5,
100         .$0
101     };
102 }
103 "#;
104         check(
105             test_code,
106             expect![[r#"
107                 fd bar usize
108             "#]],
109         );
110
111         check_snippet(
112             test_code,
113             expect![[r#"
114                 sn pd
115                 sn ppd
116                 fd ..Default::default()
117             "#]],
118         );
119     }
120
121     #[test]
122     fn test_record_literal_field_default_completion() {
123         check_edit(
124             "..Default::default()",
125             r#"
126 struct S { foo: u32, bar: usize }
127
128 impl core::default::Default for S {
129     fn default() -> Self {
130         S {
131             foo: 0,
132             bar: 0,
133         }
134     }
135 }
136
137 fn process(f: S) {
138     let other = S {
139         foo: 5,
140         .$0
141     };
142 }
143 "#,
144             r#"
145 struct S { foo: u32, bar: usize }
146
147 impl core::default::Default for S {
148     fn default() -> Self {
149         S {
150             foo: 0,
151             bar: 0,
152         }
153     }
154 }
155
156 fn process(f: S) {
157     let other = S {
158         foo: 5,
159         ..Default::default()
160     };
161 }
162 "#,
163         );
164     }
165
166     #[test]
167     fn test_record_literal_field_without_default() {
168         let test_code = r#"
169 struct S { foo: u32, bar: usize }
170
171 fn process(f: S) {
172     let other = S {
173         foo: 5,
174         .$0
175     };
176 }
177 "#;
178         check(
179             test_code,
180             expect![[r#"
181                 fd bar usize
182             "#]],
183         );
184
185         check_snippet(
186             test_code,
187             expect![[r#"
188                 sn pd
189                 sn ppd
190             "#]],
191         );
192     }
193
194     #[test]
195     fn test_record_pattern_field() {
196         check(
197             r#"
198 struct S { foo: u32 }
199
200 fn process(f: S) {
201     match f {
202         S { f$0: 92 } => (),
203     }
204 }
205 "#,
206             expect![[r#"
207                 fd foo u32
208             "#]],
209         );
210     }
211
212     #[test]
213     fn test_record_pattern_enum_variant() {
214         check(
215             r#"
216 enum E { S { foo: u32, bar: () } }
217
218 fn process(e: E) {
219     match e {
220         E::S { $0 } => (),
221     }
222 }
223 "#,
224             expect![[r#"
225                 fd foo u32
226                 fd bar ()
227             "#]],
228         );
229     }
230
231     #[test]
232     fn test_record_pattern_field_in_simple_macro() {
233         check(
234             r"
235 macro_rules! m { ($e:expr) => { $e } }
236 struct S { foo: u32 }
237
238 fn process(f: S) {
239     m!(match f {
240         S { f$0: 92 } => (),
241     })
242 }
243 ",
244             expect![[r#"
245                 fd foo u32
246             "#]],
247         );
248     }
249
250     #[test]
251     fn only_missing_fields_are_completed_in_destruct_pats() {
252         check(
253             r#"
254 struct S {
255     foo1: u32, foo2: u32,
256     bar: u32, baz: u32,
257 }
258
259 fn main() {
260     let s = S {
261         foo1: 1, foo2: 2,
262         bar: 3, baz: 4,
263     };
264     if let S { foo1, foo2: a, $0 } = s {}
265 }
266 "#,
267             expect![[r#"
268                 fd bar u32
269                 fd baz u32
270             "#]],
271         );
272     }
273
274     #[test]
275     fn test_record_literal_field() {
276         check(
277             r#"
278 struct A { the_field: u32 }
279 fn foo() {
280    A { the$0 }
281 }
282 "#,
283             expect![[r#"
284                 fd the_field u32
285             "#]],
286         );
287     }
288
289     #[test]
290     fn test_record_literal_enum_variant() {
291         check(
292             r#"
293 enum E { A { a: u32 } }
294 fn foo() {
295     let _ = E::A { $0 }
296 }
297 "#,
298             expect![[r#"
299                 fd a u32
300             "#]],
301         );
302     }
303
304     #[test]
305     fn test_record_literal_two_structs() {
306         check(
307             r#"
308 struct A { a: u32 }
309 struct B { b: u32 }
310
311 fn foo() {
312    let _: A = B { $0 }
313 }
314 "#,
315             expect![[r#"
316                 fd b u32
317             "#]],
318         );
319     }
320
321     #[test]
322     fn test_record_literal_generic_struct() {
323         check(
324             r#"
325 struct A<T> { a: T }
326
327 fn foo() {
328    let _: A<u32> = A { $0 }
329 }
330 "#,
331             expect![[r#"
332                 fd a u32
333             "#]],
334         );
335     }
336
337     #[test]
338     fn test_record_literal_field_in_simple_macro() {
339         check(
340             r#"
341 macro_rules! m { ($e:expr) => { $e } }
342 struct A { the_field: u32 }
343 fn foo() {
344    m!(A { the$0 })
345 }
346 "#,
347             expect![[r#"
348                 fd the_field u32
349             "#]],
350         );
351     }
352
353     #[test]
354     fn only_missing_fields_are_completed() {
355         check(
356             r#"
357 struct S {
358     foo1: u32, foo2: u32,
359     bar: u32, baz: u32,
360 }
361
362 fn main() {
363     let foo1 = 1;
364     let s = S { foo1, foo2: 5, $0 }
365 }
366 "#,
367             expect![[r#"
368                 fd bar u32
369                 fd baz u32
370             "#]],
371         );
372     }
373
374     #[test]
375     fn completes_functional_update() {
376         check(
377             r#"
378 struct S { foo1: u32, foo2: u32 }
379
380 fn main() {
381     let foo1 = 1;
382     let s = S { foo1, $0 .. loop {} }
383 }
384 "#,
385             expect![[r#"
386                 fd foo2 u32
387             "#]],
388         );
389     }
390 }