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