1 //! Complete fields in record literals and patterns.
2 use ide_db::{helpers::FamousDefs, SymbolKind};
3 use syntax::{ast::Expr, T};
4
5 use crate::{
6 patterns::ImmediateLocation, CompletionContext, CompletionItem, CompletionItemKind, Completions,
7 };
8
complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()>9 pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
10 let missing_fields = match &ctx.completion_location {
11 Some(
12 ImmediateLocation::RecordExpr(record_expr)
13 | ImmediateLocation::RecordExprUpdate(record_expr),
14 ) => {
15 let ty = ctx.sema.type_of_expr(&Expr::RecordExpr(record_expr.clone()));
16 let default_trait = FamousDefs(&ctx.sema, ctx.krate).core_default_Default();
17 let impl_default_trait = default_trait.zip(ty).map_or(false, |(default_trait, ty)| {
18 ty.original.impls_trait(ctx.db, default_trait, &[])
19 });
20
21 let missing_fields = ctx.sema.record_literal_missing_fields(record_expr);
22 if impl_default_trait && !missing_fields.is_empty() && ctx.path_qual().is_none() {
23 let completion_text = "..Default::default()";
24 let mut item =
25 CompletionItem::new(SymbolKind::Field, ctx.source_range(), completion_text);
26 let completion_text =
27 completion_text.strip_prefix(ctx.token.text()).unwrap_or(completion_text);
28 item.insert_text(completion_text);
29 item.add_to(acc);
30 }
31 if ctx.previous_token_is(T![.]) {
32 let mut item =
33 CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), "..");
34 item.insert_text(".");
35 item.add_to(acc);
36 return None;
37 }
38 missing_fields
39 }
40 Some(ImmediateLocation::RecordPat(record_pat)) => {
41 ctx.sema.record_pattern_missing_fields(record_pat)
42 }
43 _ => return None,
44 };
45
46 for (field, ty) in missing_fields {
47 acc.add_field(ctx, None, field, &ty);
48 }
49
50 Some(())
51 }
52
complete_record_literal( acc: &mut Completions, ctx: &CompletionContext, ) -> Option<()>53 pub(crate) fn complete_record_literal(
54 acc: &mut Completions,
55 ctx: &CompletionContext,
56 ) -> Option<()> {
57 if !ctx.expects_expression() {
58 return None;
59 }
60
61 if let hir::Adt::Struct(strukt) = ctx.expected_type.as_ref()?.as_adt()? {
62 acc.add_struct_literal(ctx, strukt, None);
63 }
64
65 Some(())
66 }
67
68 #[cfg(test)]
69 mod tests {
70 use crate::tests::check_edit;
71
72 #[test]
literal_struct_completion_edit()73 fn literal_struct_completion_edit() {
74 check_edit(
75 "FooDesc {…}",
76 r#"
77 struct FooDesc { pub bar: bool }
78
79 fn create_foo(foo_desc: &FooDesc) -> () { () }
80
81 fn baz() {
82 let foo = create_foo(&$0);
83 }
84 "#,
85 r#"
86 struct FooDesc { pub bar: bool }
87
88 fn create_foo(foo_desc: &FooDesc) -> () { () }
89
90 fn baz() {
91 let foo = create_foo(&FooDesc { bar: ${1:()} }$0);
92 }
93 "#,
94 )
95 }
96
97 #[test]
literal_struct_complexion_module()98 fn literal_struct_complexion_module() {
99 check_edit(
100 "FooDesc {…}",
101 r#"
102 mod _69latrick {
103 pub struct FooDesc { pub six: bool, pub neuf: Vec<String>, pub bar: bool }
104 pub fn create_foo(foo_desc: &FooDesc) -> () { () }
105 }
106
107 fn baz() {
108 use _69latrick::*;
109
110 let foo = create_foo(&$0);
111 }
112 "#,
113 r#"
114 mod _69latrick {
115 pub struct FooDesc { pub six: bool, pub neuf: Vec<String>, pub bar: bool }
116 pub fn create_foo(foo_desc: &FooDesc) -> () { () }
117 }
118
119 fn baz() {
120 use _69latrick::*;
121
122 let foo = create_foo(&FooDesc { six: ${1:()}, neuf: ${2:()}, bar: ${3:()} }$0);
123 }
124 "#,
125 );
126 }
127
128 #[test]
default_completion_edit()129 fn default_completion_edit() {
130 check_edit(
131 "..Default::default()",
132 r#"
133 //- minicore: default
134 struct Struct { foo: u32, bar: usize }
135
136 impl Default for Struct {
137 fn default() -> Self {}
138 }
139
140 fn foo() {
141 let other = Struct {
142 foo: 5,
143 .$0
144 };
145 }
146 "#,
147 r#"
148 struct Struct { foo: u32, bar: usize }
149
150 impl Default for Struct {
151 fn default() -> Self {}
152 }
153
154 fn foo() {
155 let other = Struct {
156 foo: 5,
157 ..Default::default()
158 };
159 }
160 "#,
161 );
162 check_edit(
163 "..Default::default()",
164 r#"
165 //- minicore: default
166 struct Struct { foo: u32, bar: usize }
167
168 impl Default for Struct {
169 fn default() -> Self {}
170 }
171
172 fn foo() {
173 let other = Struct {
174 foo: 5,
175 $0
176 };
177 }
178 "#,
179 r#"
180 struct Struct { foo: u32, bar: usize }
181
182 impl Default for Struct {
183 fn default() -> Self {}
184 }
185
186 fn foo() {
187 let other = Struct {
188 foo: 5,
189 ..Default::default()
190 };
191 }
192 "#,
193 );
194 check_edit(
195 "..Default::default()",
196 r#"
197 //- minicore: default
198 struct Struct { foo: u32, bar: usize }
199
200 impl Default for Struct {
201 fn default() -> Self {}
202 }
203
204 fn foo() {
205 let other = Struct {
206 foo: 5,
207 ..$0
208 };
209 }
210 "#,
211 r#"
212 struct Struct { foo: u32, bar: usize }
213
214 impl Default for Struct {
215 fn default() -> Self {}
216 }
217
218 fn foo() {
219 let other = Struct {
220 foo: 5,
221 ..Default::default()
222 };
223 }
224 "#,
225 );
226 }
227 }
228