aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/completion/complete_record.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src/completion/complete_record.rs')
-rw-r--r--crates/ide/src/completion/complete_record.rs226
1 files changed, 226 insertions, 0 deletions
diff --git a/crates/ide/src/completion/complete_record.rs b/crates/ide/src/completion/complete_record.rs
new file mode 100644
index 000000000..74b94594d
--- /dev/null
+++ b/crates/ide/src/completion/complete_record.rs
@@ -0,0 +1,226 @@
1//! Complete fields in record literals and patterns.
2use crate::completion::{CompletionContext, Completions};
3
4pub(super) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
5 let missing_fields = match (ctx.record_pat_syntax.as_ref(), ctx.record_lit_syntax.as_ref()) {
6 (None, None) => return None,
7 (Some(_), Some(_)) => unreachable!("A record cannot be both a literal and a pattern"),
8 (Some(record_pat), _) => ctx.sema.record_pattern_missing_fields(record_pat),
9 (_, Some(record_lit)) => ctx.sema.record_literal_missing_fields(record_lit),
10 };
11
12 for (field, ty) in missing_fields {
13 acc.add_field(ctx, field, &ty)
14 }
15
16 Some(())
17}
18
19#[cfg(test)]
20mod tests {
21 use expect::{expect, Expect};
22
23 use crate::completion::{test_utils::completion_list, CompletionKind};
24
25 fn check(ra_fixture: &str, expect: Expect) {
26 let actual = completion_list(ra_fixture, CompletionKind::Reference);
27 expect.assert_eq(&actual);
28 }
29
30 #[test]
31 fn test_record_pattern_field() {
32 check(
33 r#"
34struct S { foo: u32 }
35
36fn process(f: S) {
37 match f {
38 S { f<|>: 92 } => (),
39 }
40}
41"#,
42 expect![[r#"
43 fd foo u32
44 "#]],
45 );
46 }
47
48 #[test]
49 fn test_record_pattern_enum_variant() {
50 check(
51 r#"
52enum E { S { foo: u32, bar: () } }
53
54fn process(e: E) {
55 match e {
56 E::S { <|> } => (),
57 }
58}
59"#,
60 expect![[r#"
61 fd bar ()
62 fd foo u32
63 "#]],
64 );
65 }
66
67 #[test]
68 fn test_record_pattern_field_in_simple_macro() {
69 check(
70 r"
71macro_rules! m { ($e:expr) => { $e } }
72struct S { foo: u32 }
73
74fn process(f: S) {
75 m!(match f {
76 S { f<|>: 92 } => (),
77 })
78}
79",
80 expect![[r#"
81 fd foo u32
82 "#]],
83 );
84 }
85
86 #[test]
87 fn only_missing_fields_are_completed_in_destruct_pats() {
88 check(
89 r#"
90struct S {
91 foo1: u32, foo2: u32,
92 bar: u32, baz: u32,
93}
94
95fn main() {
96 let s = S {
97 foo1: 1, foo2: 2,
98 bar: 3, baz: 4,
99 };
100 if let S { foo1, foo2: a, <|> } = s {}
101}
102"#,
103 expect![[r#"
104 fd bar u32
105 fd baz u32
106 "#]],
107 );
108 }
109
110 #[test]
111 fn test_record_literal_field() {
112 check(
113 r#"
114struct A { the_field: u32 }
115fn foo() {
116 A { the<|> }
117}
118"#,
119 expect![[r#"
120 fd the_field u32
121 "#]],
122 );
123 }
124
125 #[test]
126 fn test_record_literal_enum_variant() {
127 check(
128 r#"
129enum E { A { a: u32 } }
130fn foo() {
131 let _ = E::A { <|> }
132}
133"#,
134 expect![[r#"
135 fd a u32
136 "#]],
137 );
138 }
139
140 #[test]
141 fn test_record_literal_two_structs() {
142 check(
143 r#"
144struct A { a: u32 }
145struct B { b: u32 }
146
147fn foo() {
148 let _: A = B { <|> }
149}
150"#,
151 expect![[r#"
152 fd b u32
153 "#]],
154 );
155 }
156
157 #[test]
158 fn test_record_literal_generic_struct() {
159 check(
160 r#"
161struct A<T> { a: T }
162
163fn foo() {
164 let _: A<u32> = A { <|> }
165}
166"#,
167 expect![[r#"
168 fd a u32
169 "#]],
170 );
171 }
172
173 #[test]
174 fn test_record_literal_field_in_simple_macro() {
175 check(
176 r#"
177macro_rules! m { ($e:expr) => { $e } }
178struct A { the_field: u32 }
179fn foo() {
180 m!(A { the<|> })
181}
182"#,
183 expect![[r#"
184 fd the_field u32
185 "#]],
186 );
187 }
188
189 #[test]
190 fn only_missing_fields_are_completed() {
191 check(
192 r#"
193struct S {
194 foo1: u32, foo2: u32,
195 bar: u32, baz: u32,
196}
197
198fn main() {
199 let foo1 = 1;
200 let s = S { foo1, foo2: 5, <|> }
201}
202"#,
203 expect![[r#"
204 fd bar u32
205 fd baz u32
206 "#]],
207 );
208 }
209
210 #[test]
211 fn completes_functional_update() {
212 check(
213 r#"
214struct S { foo1: u32, foo2: u32 }
215
216fn main() {
217 let foo1 = 1;
218 let s = S { foo1, <|> .. loop {} }
219}
220"#,
221 expect![[r#"
222 fd foo2 u32
223 "#]],
224 );
225 }
226}