1 //! Complete fields in record literals and patterns.
2 use ide_db::SymbolKind;
3 use syntax::ast::{self, Expr};
4
5 use crate::{
6 context::{DotAccess, DotAccessKind, PatternContext},
7 CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance,
8 CompletionRelevancePostfixMatch, Completions,
9 };
10
complete_record_pattern_fields( acc: &mut Completions, ctx: &CompletionContext<'_>, pattern_ctx: &PatternContext, )11 pub(crate) fn complete_record_pattern_fields(
12 acc: &mut Completions,
13 ctx: &CompletionContext<'_>,
14 pattern_ctx: &PatternContext,
15 ) {
16 if let PatternContext { record_pat: Some(record_pat), .. } = pattern_ctx {
17 let ty = ctx.sema.type_of_pat(&ast::Pat::RecordPat(record_pat.clone()));
18 let missing_fields = match ty.as_ref().and_then(|t| t.original.as_adt()) {
19 Some(hir::Adt::Union(un)) => {
20 // ctx.sema.record_pat_missing_fields will always return
21 // an empty Vec on a union literal. This is normally
22 // reasonable, but here we'd like to present the full list
23 // of fields if the literal is empty.
24 let were_fields_specified =
25 record_pat.record_pat_field_list().and_then(|fl| fl.fields().next()).is_some();
26
27 match were_fields_specified {
28 false => un.fields(ctx.db).into_iter().map(|f| (f, f.ty(ctx.db))).collect(),
29 true => return,
30 }
31 }
32 _ => ctx.sema.record_pattern_missing_fields(record_pat),
33 };
34 complete_fields(acc, ctx, missing_fields);
35 }
36 }
37
complete_record_expr_fields( acc: &mut Completions, ctx: &CompletionContext<'_>, record_expr: &ast::RecordExpr, &dot_prefix: &bool, )38 pub(crate) fn complete_record_expr_fields(
39 acc: &mut Completions,
40 ctx: &CompletionContext<'_>,
41 record_expr: &ast::RecordExpr,
42 &dot_prefix: &bool,
43 ) {
44 let ty = ctx.sema.type_of_expr(&Expr::RecordExpr(record_expr.clone()));
45
46 let missing_fields = match ty.as_ref().and_then(|t| t.original.as_adt()) {
47 Some(hir::Adt::Union(un)) => {
48 // ctx.sema.record_literal_missing_fields will always return
49 // an empty Vec on a union literal. This is normally
50 // reasonable, but here we'd like to present the full list
51 // of fields if the literal is empty.
52 let were_fields_specified =
53 record_expr.record_expr_field_list().and_then(|fl| fl.fields().next()).is_some();
54
55 match were_fields_specified {
56 false => un.fields(ctx.db).into_iter().map(|f| (f, f.ty(ctx.db))).collect(),
57 true => return,
58 }
59 }
60 _ => {
61 let missing_fields = ctx.sema.record_literal_missing_fields(record_expr);
62
63 if !missing_fields.is_empty() {
64 cov_mark::hit!(functional_update_field);
65 add_default_update(acc, ctx, ty);
66 }
67 if dot_prefix {
68 cov_mark::hit!(functional_update_one_dot);
69 let mut item =
70 CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), "..");
71 item.insert_text(".");
72 item.add_to(acc, ctx.db);
73 return;
74 }
75 missing_fields
76 }
77 };
78 complete_fields(acc, ctx, missing_fields);
79 }
80
add_default_update( acc: &mut Completions, ctx: &CompletionContext<'_>, ty: Option<hir::TypeInfo>, )81 pub(crate) fn add_default_update(
82 acc: &mut Completions,
83 ctx: &CompletionContext<'_>,
84 ty: Option<hir::TypeInfo>,
85 ) {
86 let default_trait = ctx.famous_defs().core_default_Default();
87 let impls_default_trait = default_trait
88 .zip(ty.as_ref())
89 .map_or(false, |(default_trait, ty)| ty.original.impls_trait(ctx.db, default_trait, &[]));
90 if impls_default_trait {
91 // FIXME: This should make use of scope_def like completions so we get all the other goodies
92 // that is we should handle this like actually completing the default function
93 let completion_text = "..Default::default()";
94 let mut item = CompletionItem::new(SymbolKind::Field, ctx.source_range(), completion_text);
95 let completion_text =
96 completion_text.strip_prefix(ctx.token.text()).unwrap_or(completion_text);
97 item.insert_text(completion_text).set_relevance(CompletionRelevance {
98 postfix_match: Some(CompletionRelevancePostfixMatch::Exact),
99 ..Default::default()
100 });
101 item.add_to(acc, ctx.db);
102 }
103 }
104
complete_fields( acc: &mut Completions, ctx: &CompletionContext<'_>, missing_fields: Vec<(hir::Field, hir::Type)>, )105 fn complete_fields(
106 acc: &mut Completions,
107 ctx: &CompletionContext<'_>,
108 missing_fields: Vec<(hir::Field, hir::Type)>,
109 ) {
110 for (field, ty) in missing_fields {
111 acc.add_field(
112 ctx,
113 &DotAccess {
114 receiver: None,
115 receiver_ty: None,
116 kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal: false },
117 },
118 None,
119 field,
120 &ty,
121 );
122 }
123 }
124
125 #[cfg(test)]
126 mod tests {
127 use ide_db::SnippetCap;
128
129 use crate::{
130 tests::{check_edit, check_edit_with_config, TEST_CONFIG},
131 CompletionConfig,
132 };
133
134 #[test]
literal_struct_completion_edit()135 fn literal_struct_completion_edit() {
136 check_edit(
137 "FooDesc{}",
138 r#"
139 struct FooDesc { pub bar: bool }
140
141 fn create_foo(foo_desc: &FooDesc) -> () { () }
142
143 fn baz() {
144 let foo = create_foo(&$0);
145 }
146 "#,
147 r#"
148 struct FooDesc { pub bar: bool }
149
150 fn create_foo(foo_desc: &FooDesc) -> () { () }
151
152 fn baz() {
153 let foo = create_foo(&FooDesc { bar: ${1:()} }$0);
154 }
155 "#,
156 )
157 }
158
159 #[test]
enum_variant_no_snippets()160 fn enum_variant_no_snippets() {
161 let conf = CompletionConfig { snippet_cap: SnippetCap::new(false), ..TEST_CONFIG };
162 // tuple variant
163 check_edit_with_config(
164 conf.clone(),
165 "Variant()",
166 r#"
167 enum Enum {
168 Variant(usize),
169 }
170
171 impl Enum {
172 fn new(u: usize) -> Self {
173 Self::Va$0
174 }
175 }
176 "#,
177 r#"
178 enum Enum {
179 Variant(usize),
180 }
181
182 impl Enum {
183 fn new(u: usize) -> Self {
184 Self::Variant
185 }
186 }
187 "#,
188 );
189
190 // record variant
191 check_edit_with_config(
192 conf,
193 "Variant{}",
194 r#"
195 enum Enum {
196 Variant{u: usize},
197 }
198
199 impl Enum {
200 fn new(u: usize) -> Self {
201 Self::Va$0
202 }
203 }
204 "#,
205 r#"
206 enum Enum {
207 Variant{u: usize},
208 }
209
210 impl Enum {
211 fn new(u: usize) -> Self {
212 Self::Variant
213 }
214 }
215 "#,
216 )
217 }
218
219 #[test]
literal_struct_impl_self_completion()220 fn literal_struct_impl_self_completion() {
221 check_edit(
222 "Self{}",
223 r#"
224 struct Foo {
225 bar: u64,
226 }
227
228 impl Foo {
229 fn new() -> Foo {
230 Self$0
231 }
232 }
233 "#,
234 r#"
235 struct Foo {
236 bar: u64,
237 }
238
239 impl Foo {
240 fn new() -> Foo {
241 Self { bar: ${1:()} }$0
242 }
243 }
244 "#,
245 );
246
247 check_edit(
248 "Self()",
249 r#"
250 mod submod {
251 pub struct Foo(pub u64);
252 }
253
254 impl submod::Foo {
255 fn new() -> submod::Foo {
256 Self$0
257 }
258 }
259 "#,
260 r#"
261 mod submod {
262 pub struct Foo(pub u64);
263 }
264
265 impl submod::Foo {
266 fn new() -> submod::Foo {
267 Self(${1:()})$0
268 }
269 }
270 "#,
271 )
272 }
273
274 #[test]
literal_struct_completion_from_sub_modules()275 fn literal_struct_completion_from_sub_modules() {
276 check_edit(
277 "submod::Struct{}",
278 r#"
279 mod submod {
280 pub struct Struct {
281 pub a: u64,
282 }
283 }
284
285 fn f() -> submod::Struct {
286 Stru$0
287 }
288 "#,
289 r#"
290 mod submod {
291 pub struct Struct {
292 pub a: u64,
293 }
294 }
295
296 fn f() -> submod::Struct {
297 submod::Struct { a: ${1:()} }$0
298 }
299 "#,
300 )
301 }
302
303 #[test]
literal_struct_complexion_module()304 fn literal_struct_complexion_module() {
305 check_edit(
306 "FooDesc{}",
307 r#"
308 mod _69latrick {
309 pub struct FooDesc { pub six: bool, pub neuf: Vec<String>, pub bar: bool }
310 pub fn create_foo(foo_desc: &FooDesc) -> () { () }
311 }
312
313 fn baz() {
314 use _69latrick::*;
315
316 let foo = create_foo(&$0);
317 }
318 "#,
319 r#"
320 mod _69latrick {
321 pub struct FooDesc { pub six: bool, pub neuf: Vec<String>, pub bar: bool }
322 pub fn create_foo(foo_desc: &FooDesc) -> () { () }
323 }
324
325 fn baz() {
326 use _69latrick::*;
327
328 let foo = create_foo(&FooDesc { six: ${1:()}, neuf: ${2:()}, bar: ${3:()} }$0);
329 }
330 "#,
331 );
332 }
333
334 #[test]
default_completion_edit()335 fn default_completion_edit() {
336 check_edit(
337 "..Default::default()",
338 r#"
339 //- minicore: default
340 struct Struct { foo: u32, bar: usize }
341
342 impl Default for Struct {
343 fn default() -> Self {}
344 }
345
346 fn foo() {
347 let other = Struct {
348 foo: 5,
349 .$0
350 };
351 }
352 "#,
353 r#"
354 struct Struct { foo: u32, bar: usize }
355
356 impl Default for Struct {
357 fn default() -> Self {}
358 }
359
360 fn foo() {
361 let other = Struct {
362 foo: 5,
363 ..Default::default()
364 };
365 }
366 "#,
367 );
368 check_edit(
369 "..Default::default()",
370 r#"
371 //- minicore: default
372 struct Struct { foo: u32, bar: usize }
373
374 impl Default for Struct {
375 fn default() -> Self {}
376 }
377
378 fn foo() {
379 let other = Struct {
380 foo: 5,
381 $0
382 };
383 }
384 "#,
385 r#"
386 struct Struct { foo: u32, bar: usize }
387
388 impl Default for Struct {
389 fn default() -> Self {}
390 }
391
392 fn foo() {
393 let other = Struct {
394 foo: 5,
395 ..Default::default()
396 };
397 }
398 "#,
399 );
400 check_edit(
401 "..Default::default()",
402 r#"
403 //- minicore: default
404 struct Struct { foo: u32, bar: usize }
405
406 impl Default for Struct {
407 fn default() -> Self {}
408 }
409
410 fn foo() {
411 let other = Struct {
412 foo: 5,
413 ..$0
414 };
415 }
416 "#,
417 r#"
418 struct Struct { foo: u32, bar: usize }
419
420 impl Default for Struct {
421 fn default() -> Self {}
422 }
423
424 fn foo() {
425 let other = Struct {
426 foo: 5,
427 ..Default::default()
428 };
429 }
430 "#,
431 );
432 }
433 }
434