diff options
Diffstat (limited to 'crates/ra_ide/src/completion')
-rw-r--r-- | crates/ra_ide/src/completion/complete_keyword.rs | 414 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_record.rs | 546 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/completion_item.rs | 20 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/presentation.rs | 25 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/test_utils.rs | 23 |
5 files changed, 447 insertions, 581 deletions
diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index e599cc3d1..34d061f5a 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs | |||
@@ -174,289 +174,289 @@ fn complete_return( | |||
174 | 174 | ||
175 | #[cfg(test)] | 175 | #[cfg(test)] |
176 | mod tests { | 176 | mod tests { |
177 | use crate::completion::{test_utils::completion_list, CompletionKind}; | 177 | use expect::{expect, Expect}; |
178 | use insta::assert_snapshot; | ||
179 | 178 | ||
180 | fn get_keyword_completions(code: &str) -> String { | 179 | use crate::completion::{ |
181 | completion_list(code, CompletionKind::Keyword) | 180 | test_utils::{check_edit, completion_list}, |
181 | CompletionKind, | ||
182 | }; | ||
183 | |||
184 | fn check(ra_fixture: &str, expect: Expect) { | ||
185 | let actual = completion_list(ra_fixture, CompletionKind::Keyword); | ||
186 | expect.assert_eq(&actual) | ||
182 | } | 187 | } |
183 | 188 | ||
184 | #[test] | 189 | #[test] |
185 | fn test_keywords_in_use_stmt() { | 190 | fn test_keywords_in_use_stmt() { |
186 | assert_snapshot!( | 191 | check( |
187 | get_keyword_completions(r"use <|>"), | 192 | r"use <|>", |
188 | @r###" | 193 | expect![[r#" |
189 | kw crate:: | 194 | kw crate:: |
190 | kw self | 195 | kw self |
191 | kw super:: | 196 | kw super:: |
192 | "### | 197 | "#]], |
193 | ); | 198 | ); |
194 | 199 | ||
195 | assert_snapshot!( | 200 | check( |
196 | get_keyword_completions(r"use a::<|>"), | 201 | r"use a::<|>", |
197 | @r###" | 202 | expect![[r#" |
198 | kw self | 203 | kw self |
199 | kw super:: | 204 | kw super:: |
200 | "### | 205 | "#]], |
201 | ); | 206 | ); |
202 | 207 | ||
203 | assert_snapshot!( | 208 | check( |
204 | get_keyword_completions(r"use a::{b, <|>}"), | 209 | r"use a::{b, <|>}", |
205 | @r###" | 210 | expect![[r#" |
206 | kw self | 211 | kw self |
207 | kw super:: | 212 | kw super:: |
208 | "### | 213 | "#]], |
209 | ); | 214 | ); |
210 | } | 215 | } |
211 | 216 | ||
212 | #[test] | 217 | #[test] |
213 | fn test_keywords_at_source_file_level() { | 218 | fn test_keywords_at_source_file_level() { |
214 | assert_snapshot!( | 219 | check( |
215 | get_keyword_completions(r"m<|>"), | 220 | r"m<|>", |
216 | @r###" | 221 | expect![[r#" |
217 | kw const | 222 | kw const |
218 | kw enum | 223 | kw enum |
219 | kw extern | 224 | kw extern |
220 | kw fn | 225 | kw fn |
221 | kw impl | 226 | kw impl |
222 | kw mod | 227 | kw mod |
223 | kw pub | 228 | kw pub |
224 | kw static | 229 | kw static |
225 | kw struct | 230 | kw struct |
226 | kw trait | 231 | kw trait |
227 | kw type | 232 | kw type |
228 | kw union | 233 | kw union |
229 | kw unsafe | 234 | kw unsafe |
230 | kw use | 235 | kw use |
231 | "### | 236 | "#]], |
232 | ); | 237 | ); |
233 | } | 238 | } |
234 | 239 | ||
235 | #[test] | 240 | #[test] |
236 | fn test_keywords_in_function() { | 241 | fn test_keywords_in_function() { |
237 | assert_snapshot!( | 242 | check( |
238 | get_keyword_completions(r"fn quux() { <|> }"), | 243 | r"fn quux() { <|> }", |
239 | @r###" | 244 | expect![[r#" |
240 | kw const | 245 | kw const |
241 | kw extern | 246 | kw extern |
242 | kw fn | 247 | kw fn |
243 | kw if | 248 | kw if |
244 | kw if let | 249 | kw if let |
245 | kw impl | 250 | kw impl |
246 | kw let | 251 | kw let |
247 | kw loop | 252 | kw loop |
248 | kw match | 253 | kw match |
249 | kw mod | 254 | kw mod |
250 | kw return | 255 | kw return |
251 | kw static | 256 | kw static |
252 | kw trait | 257 | kw trait |
253 | kw type | 258 | kw type |
254 | kw unsafe | 259 | kw unsafe |
255 | kw use | 260 | kw use |
256 | kw while | 261 | kw while |
257 | "### | 262 | "#]], |
258 | ); | 263 | ); |
259 | } | 264 | } |
260 | 265 | ||
261 | #[test] | 266 | #[test] |
262 | fn test_keywords_inside_block() { | 267 | fn test_keywords_inside_block() { |
263 | assert_snapshot!( | 268 | check( |
264 | get_keyword_completions(r"fn quux() { if true { <|> } }"), | 269 | r"fn quux() { if true { <|> } }", |
265 | @r###" | 270 | expect![[r#" |
266 | kw const | 271 | kw const |
267 | kw extern | 272 | kw extern |
268 | kw fn | 273 | kw fn |
269 | kw if | 274 | kw if |
270 | kw if let | 275 | kw if let |
271 | kw impl | 276 | kw impl |
272 | kw let | 277 | kw let |
273 | kw loop | 278 | kw loop |
274 | kw match | 279 | kw match |
275 | kw mod | 280 | kw mod |
276 | kw return | 281 | kw return |
277 | kw static | 282 | kw static |
278 | kw trait | 283 | kw trait |
279 | kw type | 284 | kw type |
280 | kw unsafe | 285 | kw unsafe |
281 | kw use | 286 | kw use |
282 | kw while | 287 | kw while |
283 | "### | 288 | "#]], |
284 | ); | 289 | ); |
285 | } | 290 | } |
286 | 291 | ||
287 | #[test] | 292 | #[test] |
288 | fn test_keywords_after_if() { | 293 | fn test_keywords_after_if() { |
289 | assert_snapshot!( | 294 | check( |
290 | get_keyword_completions( | 295 | r#"fn quux() { if true { () } <|> }"#, |
291 | r" | 296 | expect![[r#" |
292 | fn quux() { | 297 | kw const |
293 | if true { | 298 | kw else |
294 | () | 299 | kw else if |
295 | } <|> | 300 | kw extern |
296 | } | 301 | kw fn |
297 | ", | 302 | kw if |
298 | ), | 303 | kw if let |
299 | @r###" | 304 | kw impl |
300 | kw const | 305 | kw let |
301 | kw else | 306 | kw loop |
302 | kw else if | 307 | kw match |
303 | kw extern | 308 | kw mod |
304 | kw fn | 309 | kw return |
305 | kw if | 310 | kw static |
306 | kw if let | 311 | kw trait |
307 | kw impl | 312 | kw type |
308 | kw let | 313 | kw unsafe |
309 | kw loop | 314 | kw use |
310 | kw match | 315 | kw while |
311 | kw mod | 316 | "#]], |
312 | kw return | 317 | ); |
313 | kw static | 318 | check_edit( |
314 | kw trait | 319 | "else", |
315 | kw type | 320 | r#"fn quux() { if true { () } <|> }"#, |
316 | kw unsafe | 321 | r#"fn quux() { if true { () } else {$0} }"#, |
317 | kw use | ||
318 | kw while | ||
319 | "### | ||
320 | ); | 322 | ); |
321 | } | 323 | } |
322 | 324 | ||
323 | #[test] | 325 | #[test] |
324 | fn test_keywords_in_match_arm() { | 326 | fn test_keywords_in_match_arm() { |
325 | assert_snapshot!( | 327 | check( |
326 | get_keyword_completions( | 328 | r#" |
327 | r" | 329 | fn quux() -> i32 { |
328 | fn quux() -> i32 { | 330 | match () { |
329 | match () { | 331 | () => <|> |
330 | () => <|> | 332 | } |
331 | } | 333 | } |
332 | } | 334 | "#, |
333 | ", | 335 | expect![[r#" |
334 | ), | 336 | kw if |
335 | @r###" | 337 | kw if let |
336 | kw if | 338 | kw loop |
337 | kw if let | 339 | kw match |
338 | kw loop | 340 | kw return |
339 | kw match | 341 | kw unsafe |
340 | kw return | 342 | "#]], |
341 | kw unsafe | ||
342 | "### | ||
343 | ); | 343 | ); |
344 | } | 344 | } |
345 | 345 | ||
346 | #[test] | 346 | #[test] |
347 | fn test_keywords_in_trait_def() { | 347 | fn test_keywords_in_trait_def() { |
348 | assert_snapshot!( | 348 | check( |
349 | get_keyword_completions(r"trait My { <|> }"), | 349 | r"trait My { <|> }", |
350 | @r###" | 350 | expect![[r#" |
351 | kw const | 351 | kw const |
352 | kw fn | 352 | kw fn |
353 | kw type | 353 | kw type |
354 | kw unsafe | 354 | kw unsafe |
355 | "### | 355 | "#]], |
356 | ); | 356 | ); |
357 | } | 357 | } |
358 | 358 | ||
359 | #[test] | 359 | #[test] |
360 | fn test_keywords_in_impl_def() { | 360 | fn test_keywords_in_impl_def() { |
361 | assert_snapshot!( | 361 | check( |
362 | get_keyword_completions(r"impl My { <|> }"), | 362 | r"impl My { <|> }", |
363 | @r###" | 363 | expect![[r#" |
364 | kw const | 364 | kw const |
365 | kw fn | 365 | kw fn |
366 | kw pub | 366 | kw pub |
367 | kw type | 367 | kw type |
368 | kw unsafe | 368 | kw unsafe |
369 | "### | 369 | "#]], |
370 | ); | 370 | ); |
371 | } | 371 | } |
372 | 372 | ||
373 | #[test] | 373 | #[test] |
374 | fn test_keywords_in_loop() { | 374 | fn test_keywords_in_loop() { |
375 | assert_snapshot!( | 375 | check( |
376 | get_keyword_completions(r"fn my() { loop { <|> } }"), | 376 | r"fn my() { loop { <|> } }", |
377 | @r###" | 377 | expect![[r#" |
378 | kw break | 378 | kw break |
379 | kw const | 379 | kw const |
380 | kw continue | 380 | kw continue |
381 | kw extern | 381 | kw extern |
382 | kw fn | 382 | kw fn |
383 | kw if | 383 | kw if |
384 | kw if let | 384 | kw if let |
385 | kw impl | 385 | kw impl |
386 | kw let | 386 | kw let |
387 | kw loop | 387 | kw loop |
388 | kw match | 388 | kw match |
389 | kw mod | 389 | kw mod |
390 | kw return | 390 | kw return |
391 | kw static | 391 | kw static |
392 | kw trait | 392 | kw trait |
393 | kw type | 393 | kw type |
394 | kw unsafe | 394 | kw unsafe |
395 | kw use | 395 | kw use |
396 | kw while | 396 | kw while |
397 | "### | 397 | "#]], |
398 | ); | 398 | ); |
399 | } | 399 | } |
400 | 400 | ||
401 | #[test] | 401 | #[test] |
402 | fn test_keywords_after_unsafe_in_item_list() { | 402 | fn test_keywords_after_unsafe_in_item_list() { |
403 | assert_snapshot!( | 403 | check( |
404 | get_keyword_completions(r"unsafe <|>"), | 404 | r"unsafe <|>", |
405 | @r###" | 405 | expect![[r#" |
406 | kw fn | 406 | kw fn |
407 | kw impl | 407 | kw impl |
408 | kw trait | 408 | kw trait |
409 | "### | 409 | "#]], |
410 | ); | 410 | ); |
411 | } | 411 | } |
412 | 412 | ||
413 | #[test] | 413 | #[test] |
414 | fn test_keywords_after_unsafe_in_block_expr() { | 414 | fn test_keywords_after_unsafe_in_block_expr() { |
415 | assert_snapshot!( | 415 | check( |
416 | get_keyword_completions(r"fn my_fn() { unsafe <|> }"), | 416 | r"fn my_fn() { unsafe <|> }", |
417 | @r###" | 417 | expect![[r#" |
418 | kw fn | 418 | kw fn |
419 | kw impl | 419 | kw impl |
420 | kw trait | 420 | kw trait |
421 | "### | 421 | "#]], |
422 | ); | 422 | ); |
423 | } | 423 | } |
424 | 424 | ||
425 | #[test] | 425 | #[test] |
426 | fn test_mut_in_ref_and_in_fn_parameters_list() { | 426 | fn test_mut_in_ref_and_in_fn_parameters_list() { |
427 | assert_snapshot!( | 427 | check( |
428 | get_keyword_completions(r"fn my_fn(&<|>) {}"), | 428 | r"fn my_fn(&<|>) {}", |
429 | @r###" | 429 | expect![[r#" |
430 | kw mut | 430 | kw mut |
431 | "### | 431 | "#]], |
432 | ); | 432 | ); |
433 | assert_snapshot!( | 433 | check( |
434 | get_keyword_completions(r"fn my_fn(<|>) {}"), | 434 | r"fn my_fn(<|>) {}", |
435 | @r###" | 435 | expect![[r#" |
436 | kw mut | 436 | kw mut |
437 | "### | 437 | "#]], |
438 | ); | 438 | ); |
439 | assert_snapshot!( | 439 | check( |
440 | get_keyword_completions(r"fn my_fn() { let &<|> }"), | 440 | r"fn my_fn() { let &<|> }", |
441 | @r###" | 441 | expect![[r#" |
442 | kw mut | 442 | kw mut |
443 | "### | 443 | "#]], |
444 | ); | 444 | ); |
445 | } | 445 | } |
446 | 446 | ||
447 | #[test] | 447 | #[test] |
448 | fn test_where_keyword() { | 448 | fn test_where_keyword() { |
449 | assert_snapshot!( | 449 | check( |
450 | get_keyword_completions(r"trait A <|>"), | 450 | r"trait A <|>", |
451 | @r###" | 451 | expect![[r#" |
452 | kw where | 452 | kw where |
453 | "### | 453 | "#]], |
454 | ); | 454 | ); |
455 | assert_snapshot!( | 455 | check( |
456 | get_keyword_completions(r"impl A <|>"), | 456 | r"impl A <|>", |
457 | @r###" | 457 | expect![[r#" |
458 | kw where | 458 | kw where |
459 | "### | 459 | "#]], |
460 | ); | 460 | ); |
461 | } | 461 | } |
462 | } | 462 | } |
diff --git a/crates/ra_ide/src/completion/complete_record.rs b/crates/ra_ide/src/completion/complete_record.rs index 13eb2f79f..74b94594d 100644 --- a/crates/ra_ide/src/completion/complete_record.rs +++ b/crates/ra_ide/src/completion/complete_record.rs | |||
@@ -18,389 +18,209 @@ pub(super) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> | |||
18 | 18 | ||
19 | #[cfg(test)] | 19 | #[cfg(test)] |
20 | mod tests { | 20 | mod tests { |
21 | mod record_pat_tests { | 21 | use expect::{expect, Expect}; |
22 | use insta::assert_debug_snapshot; | ||
23 | 22 | ||
24 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; | 23 | use crate::completion::{test_utils::completion_list, CompletionKind}; |
25 | 24 | ||
26 | fn complete(code: &str) -> Vec<CompletionItem> { | 25 | fn check(ra_fixture: &str, expect: Expect) { |
27 | do_completion(code, CompletionKind::Reference) | 26 | let actual = completion_list(ra_fixture, CompletionKind::Reference); |
28 | } | 27 | expect.assert_eq(&actual); |
29 | 28 | } | |
30 | #[test] | ||
31 | fn test_record_pattern_field() { | ||
32 | let completions = complete( | ||
33 | r" | ||
34 | struct S { foo: u32 } | ||
35 | |||
36 | fn process(f: S) { | ||
37 | match f { | ||
38 | S { f<|>: 92 } => (), | ||
39 | } | ||
40 | } | ||
41 | ", | ||
42 | ); | ||
43 | assert_debug_snapshot!(completions, @r###" | ||
44 | [ | ||
45 | CompletionItem { | ||
46 | label: "foo", | ||
47 | source_range: 68..69, | ||
48 | delete: 68..69, | ||
49 | insert: "foo", | ||
50 | kind: Field, | ||
51 | detail: "u32", | ||
52 | }, | ||
53 | ] | ||
54 | "###); | ||
55 | } | ||
56 | |||
57 | #[test] | ||
58 | fn test_record_pattern_enum_variant() { | ||
59 | let completions = complete( | ||
60 | r" | ||
61 | enum E { | ||
62 | S { foo: u32, bar: () } | ||
63 | } | ||
64 | |||
65 | fn process(e: E) { | ||
66 | match e { | ||
67 | E::S { <|> } => (), | ||
68 | } | ||
69 | } | ||
70 | ", | ||
71 | ); | ||
72 | assert_debug_snapshot!(completions, @r###" | ||
73 | [ | ||
74 | CompletionItem { | ||
75 | label: "bar", | ||
76 | source_range: 88..88, | ||
77 | delete: 88..88, | ||
78 | insert: "bar", | ||
79 | kind: Field, | ||
80 | detail: "()", | ||
81 | }, | ||
82 | CompletionItem { | ||
83 | label: "foo", | ||
84 | source_range: 88..88, | ||
85 | delete: 88..88, | ||
86 | insert: "foo", | ||
87 | kind: Field, | ||
88 | detail: "u32", | ||
89 | }, | ||
90 | ] | ||
91 | "###); | ||
92 | } | ||
93 | 29 | ||
94 | #[test] | 30 | #[test] |
95 | fn test_record_pattern_field_in_simple_macro() { | 31 | fn test_record_pattern_field() { |
96 | let completions = complete( | 32 | check( |
97 | r" | 33 | r#" |
98 | macro_rules! m { ($e:expr) => { $e } } | 34 | struct S { foo: u32 } |
99 | struct S { foo: u32 } | ||
100 | 35 | ||
101 | fn process(f: S) { | 36 | fn process(f: S) { |
102 | m!(match f { | 37 | match f { |
103 | S { f<|>: 92 } => (), | 38 | S { f<|>: 92 } => (), |
104 | }) | 39 | } |
105 | } | 40 | } |
106 | ", | 41 | "#, |
107 | ); | 42 | expect![[r#" |
108 | assert_debug_snapshot!(completions, @r###" | 43 | fd foo u32 |
109 | [ | 44 | "#]], |
110 | CompletionItem { | 45 | ); |
111 | label: "foo", | 46 | } |
112 | source_range: 110..111, | ||
113 | delete: 110..111, | ||
114 | insert: "foo", | ||
115 | kind: Field, | ||
116 | detail: "u32", | ||
117 | }, | ||
118 | ] | ||
119 | "###); | ||
120 | } | ||
121 | 47 | ||
122 | #[test] | 48 | #[test] |
123 | fn only_missing_fields_are_completed_in_destruct_pats() { | 49 | fn test_record_pattern_enum_variant() { |
124 | let completions = complete( | 50 | check( |
125 | r" | 51 | r#" |
126 | struct S { | 52 | enum E { S { foo: u32, bar: () } } |
127 | foo1: u32, | ||
128 | foo2: u32, | ||
129 | bar: u32, | ||
130 | baz: u32, | ||
131 | } | ||
132 | 53 | ||
133 | fn main() { | 54 | fn process(e: E) { |
134 | let s = S { | 55 | match e { |
135 | foo1: 1, | 56 | E::S { <|> } => (), |
136 | foo2: 2, | 57 | } |
137 | bar: 3, | 58 | } |
138 | baz: 4, | 59 | "#, |
139 | }; | 60 | expect![[r#" |
140 | if let S { foo1, foo2: a, <|> } = s {} | 61 | fd bar () |
141 | } | 62 | fd foo u32 |
142 | ", | 63 | "#]], |
143 | ); | 64 | ); |
144 | assert_debug_snapshot!(completions, @r###" | ||
145 | [ | ||
146 | CompletionItem { | ||
147 | label: "bar", | ||
148 | source_range: 203..203, | ||
149 | delete: 203..203, | ||
150 | insert: "bar", | ||
151 | kind: Field, | ||
152 | detail: "u32", | ||
153 | }, | ||
154 | CompletionItem { | ||
155 | label: "baz", | ||
156 | source_range: 203..203, | ||
157 | delete: 203..203, | ||
158 | insert: "baz", | ||
159 | kind: Field, | ||
160 | detail: "u32", | ||
161 | }, | ||
162 | ] | ||
163 | "###); | ||
164 | } | ||
165 | } | 65 | } |
166 | 66 | ||
167 | mod record_lit_tests { | 67 | #[test] |
168 | use insta::assert_debug_snapshot; | 68 | fn test_record_pattern_field_in_simple_macro() { |
169 | 69 | check( | |
170 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; | 70 | r" |
71 | macro_rules! m { ($e:expr) => { $e } } | ||
72 | struct S { foo: u32 } | ||
73 | |||
74 | fn process(f: S) { | ||
75 | m!(match f { | ||
76 | S { f<|>: 92 } => (), | ||
77 | }) | ||
78 | } | ||
79 | ", | ||
80 | expect![[r#" | ||
81 | fd foo u32 | ||
82 | "#]], | ||
83 | ); | ||
84 | } | ||
171 | 85 | ||
172 | fn complete(code: &str) -> Vec<CompletionItem> { | 86 | #[test] |
173 | do_completion(code, CompletionKind::Reference) | 87 | fn only_missing_fields_are_completed_in_destruct_pats() { |
174 | } | 88 | check( |
89 | r#" | ||
90 | struct S { | ||
91 | foo1: u32, foo2: u32, | ||
92 | bar: u32, baz: u32, | ||
93 | } | ||
175 | 94 | ||
176 | #[test] | 95 | fn main() { |
177 | fn test_record_literal_deprecated_field() { | 96 | let s = S { |
178 | let completions = complete( | 97 | foo1: 1, foo2: 2, |
179 | r" | 98 | bar: 3, baz: 4, |
180 | struct A { | 99 | }; |
181 | #[deprecated] | 100 | if let S { foo1, foo2: a, <|> } = s {} |
182 | the_field: u32, | 101 | } |
183 | } | 102 | "#, |
184 | fn foo() { | 103 | expect![[r#" |
185 | A { the<|> } | 104 | fd bar u32 |
186 | } | 105 | fd baz u32 |
187 | ", | 106 | "#]], |
188 | ); | 107 | ); |
189 | assert_debug_snapshot!(completions, @r###" | 108 | } |
190 | [ | ||
191 | CompletionItem { | ||
192 | label: "the_field", | ||
193 | source_range: 69..72, | ||
194 | delete: 69..72, | ||
195 | insert: "the_field", | ||
196 | kind: Field, | ||
197 | detail: "u32", | ||
198 | deprecated: true, | ||
199 | }, | ||
200 | ] | ||
201 | "###); | ||
202 | } | ||
203 | 109 | ||
204 | #[test] | 110 | #[test] |
205 | fn test_record_literal_field() { | 111 | fn test_record_literal_field() { |
206 | let completions = complete( | 112 | check( |
207 | r" | 113 | r#" |
208 | struct A { the_field: u32 } | 114 | struct A { the_field: u32 } |
209 | fn foo() { | 115 | fn foo() { |
210 | A { the<|> } | 116 | A { the<|> } |
211 | } | 117 | } |
212 | ", | 118 | "#, |
213 | ); | 119 | expect![[r#" |
214 | assert_debug_snapshot!(completions, @r###" | 120 | fd the_field u32 |
215 | [ | 121 | "#]], |
216 | CompletionItem { | 122 | ); |
217 | label: "the_field", | 123 | } |
218 | source_range: 46..49, | ||
219 | delete: 46..49, | ||
220 | insert: "the_field", | ||
221 | kind: Field, | ||
222 | detail: "u32", | ||
223 | }, | ||
224 | ] | ||
225 | "###); | ||
226 | } | ||
227 | 124 | ||
228 | #[test] | 125 | #[test] |
229 | fn test_record_literal_enum_variant() { | 126 | fn test_record_literal_enum_variant() { |
230 | let completions = complete( | 127 | check( |
231 | r" | 128 | r#" |
232 | enum E { | 129 | enum E { A { a: u32 } } |
233 | A { a: u32 } | 130 | fn foo() { |
234 | } | 131 | let _ = E::A { <|> } |
235 | fn foo() { | 132 | } |
236 | let _ = E::A { <|> } | 133 | "#, |
237 | } | 134 | expect![[r#" |
238 | ", | 135 | fd a u32 |
239 | ); | 136 | "#]], |
240 | assert_debug_snapshot!(completions, @r###" | 137 | ); |
241 | [ | 138 | } |
242 | CompletionItem { | ||
243 | label: "a", | ||
244 | source_range: 58..58, | ||
245 | delete: 58..58, | ||
246 | insert: "a", | ||
247 | kind: Field, | ||
248 | detail: "u32", | ||
249 | }, | ||
250 | ] | ||
251 | "###); | ||
252 | } | ||
253 | 139 | ||
254 | #[test] | 140 | #[test] |
255 | fn test_record_literal_two_structs() { | 141 | fn test_record_literal_two_structs() { |
256 | let completions = complete( | 142 | check( |
257 | r" | 143 | r#" |
258 | struct A { a: u32 } | 144 | struct A { a: u32 } |
259 | struct B { b: u32 } | 145 | struct B { b: u32 } |
260 | 146 | ||
261 | fn foo() { | 147 | fn foo() { |
262 | let _: A = B { <|> } | 148 | let _: A = B { <|> } |
263 | } | 149 | } |
264 | ", | 150 | "#, |
265 | ); | 151 | expect![[r#" |
266 | assert_debug_snapshot!(completions, @r###" | 152 | fd b u32 |
267 | [ | 153 | "#]], |
268 | CompletionItem { | 154 | ); |
269 | label: "b", | 155 | } |
270 | source_range: 70..70, | ||
271 | delete: 70..70, | ||
272 | insert: "b", | ||
273 | kind: Field, | ||
274 | detail: "u32", | ||
275 | }, | ||
276 | ] | ||
277 | "###); | ||
278 | } | ||
279 | 156 | ||
280 | #[test] | 157 | #[test] |
281 | fn test_record_literal_generic_struct() { | 158 | fn test_record_literal_generic_struct() { |
282 | let completions = complete( | 159 | check( |
283 | r" | 160 | r#" |
284 | struct A<T> { a: T } | 161 | struct A<T> { a: T } |
285 | 162 | ||
286 | fn foo() { | 163 | fn foo() { |
287 | let _: A<u32> = A { <|> } | 164 | let _: A<u32> = A { <|> } |
288 | } | 165 | } |
289 | ", | 166 | "#, |
290 | ); | 167 | expect![[r#" |
291 | assert_debug_snapshot!(completions, @r###" | 168 | fd a u32 |
292 | [ | 169 | "#]], |
293 | CompletionItem { | 170 | ); |
294 | label: "a", | 171 | } |
295 | source_range: 56..56, | ||
296 | delete: 56..56, | ||
297 | insert: "a", | ||
298 | kind: Field, | ||
299 | detail: "u32", | ||
300 | }, | ||
301 | ] | ||
302 | "###); | ||
303 | } | ||
304 | 172 | ||
305 | #[test] | 173 | #[test] |
306 | fn test_record_literal_field_in_simple_macro() { | 174 | fn test_record_literal_field_in_simple_macro() { |
307 | let completions = complete( | 175 | check( |
308 | r" | 176 | r#" |
309 | macro_rules! m { ($e:expr) => { $e } } | 177 | macro_rules! m { ($e:expr) => { $e } } |
310 | struct A { the_field: u32 } | 178 | struct A { the_field: u32 } |
311 | fn foo() { | 179 | fn foo() { |
312 | m!(A { the<|> }) | 180 | m!(A { the<|> }) |
313 | } | 181 | } |
314 | ", | 182 | "#, |
315 | ); | 183 | expect![[r#" |
316 | assert_debug_snapshot!(completions, @r###" | 184 | fd the_field u32 |
317 | [ | 185 | "#]], |
318 | CompletionItem { | 186 | ); |
319 | label: "the_field", | 187 | } |
320 | source_range: 88..91, | ||
321 | delete: 88..91, | ||
322 | insert: "the_field", | ||
323 | kind: Field, | ||
324 | detail: "u32", | ||
325 | }, | ||
326 | ] | ||
327 | "###); | ||
328 | } | ||
329 | 188 | ||
330 | #[test] | 189 | #[test] |
331 | fn only_missing_fields_are_completed() { | 190 | fn only_missing_fields_are_completed() { |
332 | let completions = complete( | 191 | check( |
333 | r" | 192 | r#" |
334 | struct S { | 193 | struct S { |
335 | foo1: u32, | 194 | foo1: u32, foo2: u32, |
336 | foo2: u32, | 195 | bar: u32, baz: u32, |
337 | bar: u32, | 196 | } |
338 | baz: u32, | ||
339 | } | ||
340 | 197 | ||
341 | fn main() { | 198 | fn main() { |
342 | let foo1 = 1; | 199 | let foo1 = 1; |
343 | let s = S { | 200 | let s = S { foo1, foo2: 5, <|> } |
344 | foo1, | 201 | } |
345 | foo2: 5, | 202 | "#, |
346 | <|> | 203 | expect![[r#" |
347 | } | 204 | fd bar u32 |
348 | } | 205 | fd baz u32 |
349 | ", | 206 | "#]], |
350 | ); | 207 | ); |
351 | assert_debug_snapshot!(completions, @r###" | 208 | } |
352 | [ | ||
353 | CompletionItem { | ||
354 | label: "bar", | ||
355 | source_range: 157..157, | ||
356 | delete: 157..157, | ||
357 | insert: "bar", | ||
358 | kind: Field, | ||
359 | detail: "u32", | ||
360 | }, | ||
361 | CompletionItem { | ||
362 | label: "baz", | ||
363 | source_range: 157..157, | ||
364 | delete: 157..157, | ||
365 | insert: "baz", | ||
366 | kind: Field, | ||
367 | detail: "u32", | ||
368 | }, | ||
369 | ] | ||
370 | "###); | ||
371 | } | ||
372 | 209 | ||
373 | #[test] | 210 | #[test] |
374 | fn completes_functional_update() { | 211 | fn completes_functional_update() { |
375 | let completions = complete( | 212 | check( |
376 | r" | 213 | r#" |
377 | struct S { | 214 | struct S { foo1: u32, foo2: u32 } |
378 | foo1: u32, | ||
379 | foo2: u32, | ||
380 | } | ||
381 | 215 | ||
382 | fn main() { | 216 | fn main() { |
383 | let foo1 = 1; | 217 | let foo1 = 1; |
384 | let s = S { | 218 | let s = S { foo1, <|> .. loop {} } |
385 | foo1, | 219 | } |
386 | <|> | 220 | "#, |
387 | .. loop {} | 221 | expect![[r#" |
388 | } | 222 | fd foo2 u32 |
389 | } | 223 | "#]], |
390 | ", | 224 | ); |
391 | ); | ||
392 | assert_debug_snapshot!(completions, @r###" | ||
393 | [ | ||
394 | CompletionItem { | ||
395 | label: "foo2", | ||
396 | source_range: 112..112, | ||
397 | delete: 112..112, | ||
398 | insert: "foo2", | ||
399 | kind: Field, | ||
400 | detail: "u32", | ||
401 | }, | ||
402 | ] | ||
403 | "###); | ||
404 | } | ||
405 | } | 225 | } |
406 | } | 226 | } |
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs index 98348b349..4db371d57 100644 --- a/crates/ra_ide/src/completion/completion_item.rs +++ b/crates/ra_ide/src/completion/completion_item.rs | |||
@@ -129,24 +129,24 @@ impl CompletionItemKind { | |||
129 | #[cfg(test)] | 129 | #[cfg(test)] |
130 | pub(crate) fn tag(&self) -> &'static str { | 130 | pub(crate) fn tag(&self) -> &'static str { |
131 | match self { | 131 | match self { |
132 | CompletionItemKind::Snippet => "sn", | 132 | CompletionItemKind::Attribute => "at", |
133 | CompletionItemKind::Keyword => "kw", | 133 | CompletionItemKind::Binding => "bn", |
134 | CompletionItemKind::Module => "md", | ||
135 | CompletionItemKind::Function => "fn", | ||
136 | CompletionItemKind::BuiltinType => "bt", | 134 | CompletionItemKind::BuiltinType => "bt", |
137 | CompletionItemKind::Struct => "st", | 135 | CompletionItemKind::Const => "ct", |
138 | CompletionItemKind::Enum => "en", | 136 | CompletionItemKind::Enum => "en", |
139 | CompletionItemKind::EnumVariant => "ev", | 137 | CompletionItemKind::EnumVariant => "ev", |
140 | CompletionItemKind::Binding => "bn", | ||
141 | CompletionItemKind::Field => "fd", | 138 | CompletionItemKind::Field => "fd", |
139 | CompletionItemKind::Function => "fn", | ||
140 | CompletionItemKind::Keyword => "kw", | ||
141 | CompletionItemKind::Macro => "ma", | ||
142 | CompletionItemKind::Method => "me", | ||
143 | CompletionItemKind::Module => "md", | ||
144 | CompletionItemKind::Snippet => "sn", | ||
142 | CompletionItemKind::Static => "sc", | 145 | CompletionItemKind::Static => "sc", |
143 | CompletionItemKind::Const => "ct", | 146 | CompletionItemKind::Struct => "st", |
144 | CompletionItemKind::Trait => "tt", | 147 | CompletionItemKind::Trait => "tt", |
145 | CompletionItemKind::TypeAlias => "ta", | 148 | CompletionItemKind::TypeAlias => "ta", |
146 | CompletionItemKind::Method => "me", | ||
147 | CompletionItemKind::TypeParam => "tp", | 149 | CompletionItemKind::TypeParam => "tp", |
148 | CompletionItemKind::Macro => "ma", | ||
149 | CompletionItemKind::Attribute => "at", | ||
150 | } | 150 | } |
151 | } | 151 | } |
152 | } | 152 | } |
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index b18279746..bd274bd74 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs | |||
@@ -606,6 +606,31 @@ mod tests { | |||
606 | ] | 606 | ] |
607 | "### | 607 | "### |
608 | ); | 608 | ); |
609 | |||
610 | assert_debug_snapshot!(do_reference_completion( | ||
611 | r#" | ||
612 | struct A { | ||
613 | #[deprecated] | ||
614 | the_field: u32, | ||
615 | } | ||
616 | fn foo() { | ||
617 | A { the<|> } | ||
618 | } | ||
619 | "#, | ||
620 | ), | ||
621 | @r###" | ||
622 | [ | ||
623 | CompletionItem { | ||
624 | label: "the_field", | ||
625 | source_range: 69..72, | ||
626 | delete: 69..72, | ||
627 | insert: "the_field", | ||
628 | kind: Field, | ||
629 | detail: "u32", | ||
630 | deprecated: true, | ||
631 | }, | ||
632 | ] | ||
633 | "###); | ||
609 | } | 634 | } |
610 | 635 | ||
611 | #[test] | 636 | #[test] |
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs index 5c01654cc..9c036eac7 100644 --- a/crates/ra_ide/src/completion/test_utils.rs +++ b/crates/ra_ide/src/completion/test_utils.rs | |||
@@ -1,7 +1,10 @@ | |||
1 | //! Runs completion for testing purposes. | 1 | //! Runs completion for testing purposes. |
2 | 2 | ||
3 | use hir::Semantics; | 3 | use hir::Semantics; |
4 | use itertools::Itertools; | ||
4 | use ra_syntax::{AstNode, NodeOrToken, SyntaxElement}; | 5 | use ra_syntax::{AstNode, NodeOrToken, SyntaxElement}; |
6 | use stdx::format_to; | ||
7 | use test_utils::assert_eq_text; | ||
5 | 8 | ||
6 | use crate::{ | 9 | use crate::{ |
7 | completion::{completion_item::CompletionKind, CompletionConfig}, | 10 | completion::{completion_item::CompletionKind, CompletionConfig}, |
@@ -42,10 +45,28 @@ pub(crate) fn completion_list_with_options( | |||
42 | kind_completions.sort_by_key(|c| c.label().to_owned()); | 45 | kind_completions.sort_by_key(|c| c.label().to_owned()); |
43 | kind_completions | 46 | kind_completions |
44 | .into_iter() | 47 | .into_iter() |
45 | .map(|it| format!("{} {}\n", it.kind().unwrap().tag(), it.label())) | 48 | .map(|it| { |
49 | let mut buf = format!("{} {}", it.kind().unwrap().tag(), it.label()); | ||
50 | if let Some(detail) = it.detail() { | ||
51 | format_to!(buf, " {}", detail); | ||
52 | } | ||
53 | format_to!(buf, "\n"); | ||
54 | buf | ||
55 | }) | ||
46 | .collect() | 56 | .collect() |
47 | } | 57 | } |
48 | 58 | ||
59 | pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) { | ||
60 | let (analysis, position) = analysis_and_position(ra_fixture_before); | ||
61 | let completions: Vec<CompletionItem> = | ||
62 | analysis.completions(&CompletionConfig::default(), position).unwrap().unwrap().into(); | ||
63 | let (completion,) = | ||
64 | completions.into_iter().filter(|it| it.label() == what).collect_tuple().unwrap(); | ||
65 | let mut actual = analysis.file_text(position.file_id).unwrap().to_string(); | ||
66 | completion.text_edit().apply(&mut actual); | ||
67 | assert_eq_text!(ra_fixture_after, &actual) | ||
68 | } | ||
69 | |||
49 | pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -> bool) { | 70 | pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -> bool) { |
50 | let (analysis, pos) = analysis_and_position(code); | 71 | let (analysis, pos) = analysis_and_position(code); |
51 | analysis | 72 | analysis |