diff options
Diffstat (limited to 'crates/completion/src/completions/unqualified_path.rs')
-rw-r--r-- | crates/completion/src/completions/unqualified_path.rs | 679 |
1 files changed, 679 insertions, 0 deletions
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs new file mode 100644 index 000000000..7df58e1da --- /dev/null +++ b/crates/completion/src/completions/unqualified_path.rs | |||
@@ -0,0 +1,679 @@ | |||
1 | //! Completion of names from the current scope, e.g. locals and imported items. | ||
2 | |||
3 | use hir::{Adt, ModuleDef, ScopeDef, Type}; | ||
4 | use syntax::AstNode; | ||
5 | use test_utils::mark; | ||
6 | |||
7 | use crate::{CompletionContext, Completions}; | ||
8 | |||
9 | pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { | ||
10 | if !(ctx.is_trivial_path || ctx.is_pat_binding_or_const) { | ||
11 | return; | ||
12 | } | ||
13 | if ctx.record_lit_syntax.is_some() | ||
14 | || ctx.record_pat_syntax.is_some() | ||
15 | || ctx.attribute_under_caret.is_some() | ||
16 | || ctx.mod_declaration_under_caret.is_some() | ||
17 | { | ||
18 | return; | ||
19 | } | ||
20 | |||
21 | if let Some(ty) = &ctx.expected_type { | ||
22 | complete_enum_variants(acc, ctx, ty); | ||
23 | } | ||
24 | |||
25 | if ctx.is_pat_binding_or_const { | ||
26 | return; | ||
27 | } | ||
28 | |||
29 | ctx.scope.process_all_names(&mut |name, res| { | ||
30 | if ctx.use_item_syntax.is_some() { | ||
31 | if let (ScopeDef::Unknown, Some(name_ref)) = (&res, &ctx.name_ref_syntax) { | ||
32 | if name_ref.syntax().text() == name.to_string().as_str() { | ||
33 | mark::hit!(self_fulfilling_completion); | ||
34 | return; | ||
35 | } | ||
36 | } | ||
37 | } | ||
38 | acc.add_resolution(ctx, name.to_string(), &res) | ||
39 | }); | ||
40 | } | ||
41 | |||
42 | fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) { | ||
43 | if let Some(Adt::Enum(enum_data)) = ty.as_adt() { | ||
44 | let variants = enum_data.variants(ctx.db); | ||
45 | |||
46 | let module = if let Some(module) = ctx.scope.module() { | ||
47 | // Compute path from the completion site if available. | ||
48 | module | ||
49 | } else { | ||
50 | // Otherwise fall back to the enum's definition site. | ||
51 | enum_data.module(ctx.db) | ||
52 | }; | ||
53 | |||
54 | for variant in variants { | ||
55 | if let Some(path) = module.find_use_path(ctx.db, ModuleDef::from(variant)) { | ||
56 | // Variants with trivial paths are already added by the existing completion logic, | ||
57 | // so we should avoid adding these twice | ||
58 | if path.segments.len() > 1 { | ||
59 | acc.add_qualified_enum_variant(ctx, variant, path); | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | } | ||
64 | } | ||
65 | |||
66 | #[cfg(test)] | ||
67 | mod tests { | ||
68 | use expect_test::{expect, Expect}; | ||
69 | use test_utils::mark; | ||
70 | |||
71 | use crate::{ | ||
72 | test_utils::{check_edit, completion_list}, | ||
73 | CompletionKind, | ||
74 | }; | ||
75 | |||
76 | fn check(ra_fixture: &str, expect: Expect) { | ||
77 | let actual = completion_list(ra_fixture, CompletionKind::Reference); | ||
78 | expect.assert_eq(&actual) | ||
79 | } | ||
80 | |||
81 | #[test] | ||
82 | fn self_fulfilling_completion() { | ||
83 | mark::check!(self_fulfilling_completion); | ||
84 | check( | ||
85 | r#" | ||
86 | use foo<|> | ||
87 | use std::collections; | ||
88 | "#, | ||
89 | expect![[r#" | ||
90 | ?? collections | ||
91 | "#]], | ||
92 | ); | ||
93 | } | ||
94 | |||
95 | #[test] | ||
96 | fn bind_pat_and_path_ignore_at() { | ||
97 | check( | ||
98 | r#" | ||
99 | enum Enum { A, B } | ||
100 | fn quux(x: Option<Enum>) { | ||
101 | match x { | ||
102 | None => (), | ||
103 | Some(en<|> @ Enum::A) => (), | ||
104 | } | ||
105 | } | ||
106 | "#, | ||
107 | expect![[""]], | ||
108 | ); | ||
109 | } | ||
110 | |||
111 | #[test] | ||
112 | fn bind_pat_and_path_ignore_ref() { | ||
113 | check( | ||
114 | r#" | ||
115 | enum Enum { A, B } | ||
116 | fn quux(x: Option<Enum>) { | ||
117 | match x { | ||
118 | None => (), | ||
119 | Some(ref en<|>) => (), | ||
120 | } | ||
121 | } | ||
122 | "#, | ||
123 | expect![[""]], | ||
124 | ); | ||
125 | } | ||
126 | |||
127 | #[test] | ||
128 | fn bind_pat_and_path() { | ||
129 | check( | ||
130 | r#" | ||
131 | enum Enum { A, B } | ||
132 | fn quux(x: Option<Enum>) { | ||
133 | match x { | ||
134 | None => (), | ||
135 | Some(En<|>) => (), | ||
136 | } | ||
137 | } | ||
138 | "#, | ||
139 | expect![[r#" | ||
140 | en Enum | ||
141 | "#]], | ||
142 | ); | ||
143 | } | ||
144 | |||
145 | #[test] | ||
146 | fn completes_bindings_from_let() { | ||
147 | check( | ||
148 | r#" | ||
149 | fn quux(x: i32) { | ||
150 | let y = 92; | ||
151 | 1 + <|>; | ||
152 | let z = (); | ||
153 | } | ||
154 | "#, | ||
155 | expect![[r#" | ||
156 | fn quux(…) fn quux(x: i32) | ||
157 | bn x i32 | ||
158 | bn y i32 | ||
159 | "#]], | ||
160 | ); | ||
161 | } | ||
162 | |||
163 | #[test] | ||
164 | fn completes_bindings_from_if_let() { | ||
165 | check( | ||
166 | r#" | ||
167 | fn quux() { | ||
168 | if let Some(x) = foo() { | ||
169 | let y = 92; | ||
170 | }; | ||
171 | if let Some(a) = bar() { | ||
172 | let b = 62; | ||
173 | 1 + <|> | ||
174 | } | ||
175 | } | ||
176 | "#, | ||
177 | expect![[r#" | ||
178 | bn a | ||
179 | bn b i32 | ||
180 | fn quux() fn quux() | ||
181 | "#]], | ||
182 | ); | ||
183 | } | ||
184 | |||
185 | #[test] | ||
186 | fn completes_bindings_from_for() { | ||
187 | check( | ||
188 | r#" | ||
189 | fn quux() { | ||
190 | for x in &[1, 2, 3] { <|> } | ||
191 | } | ||
192 | "#, | ||
193 | expect![[r#" | ||
194 | fn quux() fn quux() | ||
195 | bn x | ||
196 | "#]], | ||
197 | ); | ||
198 | } | ||
199 | |||
200 | #[test] | ||
201 | fn completes_if_prefix_is_keyword() { | ||
202 | mark::check!(completes_if_prefix_is_keyword); | ||
203 | check_edit( | ||
204 | "wherewolf", | ||
205 | r#" | ||
206 | fn main() { | ||
207 | let wherewolf = 92; | ||
208 | drop(where<|>) | ||
209 | } | ||
210 | "#, | ||
211 | r#" | ||
212 | fn main() { | ||
213 | let wherewolf = 92; | ||
214 | drop(wherewolf) | ||
215 | } | ||
216 | "#, | ||
217 | ) | ||
218 | } | ||
219 | |||
220 | #[test] | ||
221 | fn completes_generic_params() { | ||
222 | check( | ||
223 | r#"fn quux<T>() { <|> }"#, | ||
224 | expect![[r#" | ||
225 | tp T | ||
226 | fn quux() fn quux<T>() | ||
227 | "#]], | ||
228 | ); | ||
229 | } | ||
230 | |||
231 | #[test] | ||
232 | fn completes_generic_params_in_struct() { | ||
233 | check( | ||
234 | r#"struct S<T> { x: <|>}"#, | ||
235 | expect![[r#" | ||
236 | st S<…> | ||
237 | tp Self | ||
238 | tp T | ||
239 | "#]], | ||
240 | ); | ||
241 | } | ||
242 | |||
243 | #[test] | ||
244 | fn completes_self_in_enum() { | ||
245 | check( | ||
246 | r#"enum X { Y(<|>) }"#, | ||
247 | expect![[r#" | ||
248 | tp Self | ||
249 | en X | ||
250 | "#]], | ||
251 | ); | ||
252 | } | ||
253 | |||
254 | #[test] | ||
255 | fn completes_module_items() { | ||
256 | check( | ||
257 | r#" | ||
258 | struct S; | ||
259 | enum E {} | ||
260 | fn quux() { <|> } | ||
261 | "#, | ||
262 | expect![[r#" | ||
263 | en E | ||
264 | st S | ||
265 | fn quux() fn quux() | ||
266 | "#]], | ||
267 | ); | ||
268 | } | ||
269 | |||
270 | /// Regression test for issue #6091. | ||
271 | #[test] | ||
272 | fn correctly_completes_module_items_prefixed_with_underscore() { | ||
273 | check_edit( | ||
274 | "_alpha", | ||
275 | r#" | ||
276 | fn main() { | ||
277 | _<|> | ||
278 | } | ||
279 | fn _alpha() {} | ||
280 | "#, | ||
281 | r#" | ||
282 | fn main() { | ||
283 | _alpha()$0 | ||
284 | } | ||
285 | fn _alpha() {} | ||
286 | "#, | ||
287 | ) | ||
288 | } | ||
289 | |||
290 | #[test] | ||
291 | fn completes_extern_prelude() { | ||
292 | check( | ||
293 | r#" | ||
294 | //- /lib.rs crate:main deps:other_crate | ||
295 | use <|>; | ||
296 | |||
297 | //- /other_crate/lib.rs crate:other_crate | ||
298 | // nothing here | ||
299 | "#, | ||
300 | expect![[r#" | ||
301 | md other_crate | ||
302 | "#]], | ||
303 | ); | ||
304 | } | ||
305 | |||
306 | #[test] | ||
307 | fn completes_module_items_in_nested_modules() { | ||
308 | check( | ||
309 | r#" | ||
310 | struct Foo; | ||
311 | mod m { | ||
312 | struct Bar; | ||
313 | fn quux() { <|> } | ||
314 | } | ||
315 | "#, | ||
316 | expect![[r#" | ||
317 | st Bar | ||
318 | fn quux() fn quux() | ||
319 | "#]], | ||
320 | ); | ||
321 | } | ||
322 | |||
323 | #[test] | ||
324 | fn completes_return_type() { | ||
325 | check( | ||
326 | r#" | ||
327 | struct Foo; | ||
328 | fn x() -> <|> | ||
329 | "#, | ||
330 | expect![[r#" | ||
331 | st Foo | ||
332 | fn x() fn x() | ||
333 | "#]], | ||
334 | ); | ||
335 | } | ||
336 | |||
337 | #[test] | ||
338 | fn dont_show_both_completions_for_shadowing() { | ||
339 | check( | ||
340 | r#" | ||
341 | fn foo() { | ||
342 | let bar = 92; | ||
343 | { | ||
344 | let bar = 62; | ||
345 | drop(<|>) | ||
346 | } | ||
347 | } | ||
348 | "#, | ||
349 | // FIXME: should be only one bar here | ||
350 | expect![[r#" | ||
351 | bn bar i32 | ||
352 | bn bar i32 | ||
353 | fn foo() fn foo() | ||
354 | "#]], | ||
355 | ); | ||
356 | } | ||
357 | |||
358 | #[test] | ||
359 | fn completes_self_in_methods() { | ||
360 | check( | ||
361 | r#"impl S { fn foo(&self) { <|> } }"#, | ||
362 | expect![[r#" | ||
363 | tp Self | ||
364 | bn self &{unknown} | ||
365 | "#]], | ||
366 | ); | ||
367 | } | ||
368 | |||
369 | #[test] | ||
370 | fn completes_prelude() { | ||
371 | check( | ||
372 | r#" | ||
373 | //- /main.rs crate:main deps:std | ||
374 | fn foo() { let x: <|> } | ||
375 | |||
376 | //- /std/lib.rs crate:std | ||
377 | #[prelude_import] | ||
378 | use prelude::*; | ||
379 | |||
380 | mod prelude { struct Option; } | ||
381 | "#, | ||
382 | expect![[r#" | ||
383 | st Option | ||
384 | fn foo() fn foo() | ||
385 | md std | ||
386 | "#]], | ||
387 | ); | ||
388 | } | ||
389 | |||
390 | #[test] | ||
391 | fn completes_std_prelude_if_core_is_defined() { | ||
392 | check( | ||
393 | r#" | ||
394 | //- /main.rs crate:main deps:core,std | ||
395 | fn foo() { let x: <|> } | ||
396 | |||
397 | //- /core/lib.rs crate:core | ||
398 | #[prelude_import] | ||
399 | use prelude::*; | ||
400 | |||
401 | mod prelude { struct Option; } | ||
402 | |||
403 | //- /std/lib.rs crate:std deps:core | ||
404 | #[prelude_import] | ||
405 | use prelude::*; | ||
406 | |||
407 | mod prelude { struct String; } | ||
408 | "#, | ||
409 | expect![[r#" | ||
410 | st String | ||
411 | md core | ||
412 | fn foo() fn foo() | ||
413 | md std | ||
414 | "#]], | ||
415 | ); | ||
416 | } | ||
417 | |||
418 | #[test] | ||
419 | fn completes_macros_as_value() { | ||
420 | check( | ||
421 | r#" | ||
422 | macro_rules! foo { () => {} } | ||
423 | |||
424 | #[macro_use] | ||
425 | mod m1 { | ||
426 | macro_rules! bar { () => {} } | ||
427 | } | ||
428 | |||
429 | mod m2 { | ||
430 | macro_rules! nope { () => {} } | ||
431 | |||
432 | #[macro_export] | ||
433 | macro_rules! baz { () => {} } | ||
434 | } | ||
435 | |||
436 | fn main() { let v = <|> } | ||
437 | "#, | ||
438 | expect![[r##" | ||
439 | ma bar!(…) macro_rules! bar | ||
440 | ma baz!(…) #[macro_export] | ||
441 | macro_rules! baz | ||
442 | ma foo!(…) macro_rules! foo | ||
443 | md m1 | ||
444 | md m2 | ||
445 | fn main() fn main() | ||
446 | "##]], | ||
447 | ); | ||
448 | } | ||
449 | |||
450 | #[test] | ||
451 | fn completes_both_macro_and_value() { | ||
452 | check( | ||
453 | r#" | ||
454 | macro_rules! foo { () => {} } | ||
455 | fn foo() { <|> } | ||
456 | "#, | ||
457 | expect![[r#" | ||
458 | ma foo!(…) macro_rules! foo | ||
459 | fn foo() fn foo() | ||
460 | "#]], | ||
461 | ); | ||
462 | } | ||
463 | |||
464 | #[test] | ||
465 | fn completes_macros_as_type() { | ||
466 | check( | ||
467 | r#" | ||
468 | macro_rules! foo { () => {} } | ||
469 | fn main() { let x: <|> } | ||
470 | "#, | ||
471 | expect![[r#" | ||
472 | ma foo!(…) macro_rules! foo | ||
473 | fn main() fn main() | ||
474 | "#]], | ||
475 | ); | ||
476 | } | ||
477 | |||
478 | #[test] | ||
479 | fn completes_macros_as_stmt() { | ||
480 | check( | ||
481 | r#" | ||
482 | macro_rules! foo { () => {} } | ||
483 | fn main() { <|> } | ||
484 | "#, | ||
485 | expect![[r#" | ||
486 | ma foo!(…) macro_rules! foo | ||
487 | fn main() fn main() | ||
488 | "#]], | ||
489 | ); | ||
490 | } | ||
491 | |||
492 | #[test] | ||
493 | fn completes_local_item() { | ||
494 | check( | ||
495 | r#" | ||
496 | fn main() { | ||
497 | return f<|>; | ||
498 | fn frobnicate() {} | ||
499 | } | ||
500 | "#, | ||
501 | expect![[r#" | ||
502 | fn frobnicate() fn frobnicate() | ||
503 | fn main() fn main() | ||
504 | "#]], | ||
505 | ); | ||
506 | } | ||
507 | |||
508 | #[test] | ||
509 | fn completes_in_simple_macro_1() { | ||
510 | check( | ||
511 | r#" | ||
512 | macro_rules! m { ($e:expr) => { $e } } | ||
513 | fn quux(x: i32) { | ||
514 | let y = 92; | ||
515 | m!(<|>); | ||
516 | } | ||
517 | "#, | ||
518 | expect![[r#" | ||
519 | ma m!(…) macro_rules! m | ||
520 | fn quux(…) fn quux(x: i32) | ||
521 | bn x i32 | ||
522 | bn y i32 | ||
523 | "#]], | ||
524 | ); | ||
525 | } | ||
526 | |||
527 | #[test] | ||
528 | fn completes_in_simple_macro_2() { | ||
529 | check( | ||
530 | r" | ||
531 | macro_rules! m { ($e:expr) => { $e } } | ||
532 | fn quux(x: i32) { | ||
533 | let y = 92; | ||
534 | m!(x<|>); | ||
535 | } | ||
536 | ", | ||
537 | expect![[r#" | ||
538 | ma m!(…) macro_rules! m | ||
539 | fn quux(…) fn quux(x: i32) | ||
540 | bn x i32 | ||
541 | bn y i32 | ||
542 | "#]], | ||
543 | ); | ||
544 | } | ||
545 | |||
546 | #[test] | ||
547 | fn completes_in_simple_macro_without_closing_parens() { | ||
548 | check( | ||
549 | r#" | ||
550 | macro_rules! m { ($e:expr) => { $e } } | ||
551 | fn quux(x: i32) { | ||
552 | let y = 92; | ||
553 | m!(x<|> | ||
554 | } | ||
555 | "#, | ||
556 | expect![[r#" | ||
557 | ma m!(…) macro_rules! m | ||
558 | fn quux(…) fn quux(x: i32) | ||
559 | bn x i32 | ||
560 | bn y i32 | ||
561 | "#]], | ||
562 | ); | ||
563 | } | ||
564 | |||
565 | #[test] | ||
566 | fn completes_unresolved_uses() { | ||
567 | check( | ||
568 | r#" | ||
569 | use spam::Quux; | ||
570 | |||
571 | fn main() { <|> } | ||
572 | "#, | ||
573 | expect![[r#" | ||
574 | ?? Quux | ||
575 | fn main() fn main() | ||
576 | "#]], | ||
577 | ); | ||
578 | } | ||
579 | #[test] | ||
580 | fn completes_enum_variant_matcharm() { | ||
581 | check( | ||
582 | r#" | ||
583 | enum Foo { Bar, Baz, Quux } | ||
584 | |||
585 | fn main() { | ||
586 | let foo = Foo::Quux; | ||
587 | match foo { Qu<|> } | ||
588 | } | ||
589 | "#, | ||
590 | expect![[r#" | ||
591 | en Foo | ||
592 | ev Foo::Bar () | ||
593 | ev Foo::Baz () | ||
594 | ev Foo::Quux () | ||
595 | "#]], | ||
596 | ) | ||
597 | } | ||
598 | |||
599 | #[test] | ||
600 | fn completes_enum_variant_iflet() { | ||
601 | check( | ||
602 | r#" | ||
603 | enum Foo { Bar, Baz, Quux } | ||
604 | |||
605 | fn main() { | ||
606 | let foo = Foo::Quux; | ||
607 | if let Qu<|> = foo { } | ||
608 | } | ||
609 | "#, | ||
610 | expect![[r#" | ||
611 | en Foo | ||
612 | ev Foo::Bar () | ||
613 | ev Foo::Baz () | ||
614 | ev Foo::Quux () | ||
615 | "#]], | ||
616 | ) | ||
617 | } | ||
618 | |||
619 | #[test] | ||
620 | fn completes_enum_variant_basic_expr() { | ||
621 | check( | ||
622 | r#" | ||
623 | enum Foo { Bar, Baz, Quux } | ||
624 | fn main() { let foo: Foo = Q<|> } | ||
625 | "#, | ||
626 | expect![[r#" | ||
627 | en Foo | ||
628 | ev Foo::Bar () | ||
629 | ev Foo::Baz () | ||
630 | ev Foo::Quux () | ||
631 | fn main() fn main() | ||
632 | "#]], | ||
633 | ) | ||
634 | } | ||
635 | |||
636 | #[test] | ||
637 | fn completes_enum_variant_from_module() { | ||
638 | check( | ||
639 | r#" | ||
640 | mod m { pub enum E { V } } | ||
641 | fn f() -> m::E { V<|> } | ||
642 | "#, | ||
643 | expect![[r#" | ||
644 | fn f() fn f() -> m::E | ||
645 | md m | ||
646 | ev m::E::V () | ||
647 | "#]], | ||
648 | ) | ||
649 | } | ||
650 | |||
651 | #[test] | ||
652 | fn dont_complete_attr() { | ||
653 | check( | ||
654 | r#" | ||
655 | struct Foo; | ||
656 | #[<|>] | ||
657 | fn f() {} | ||
658 | "#, | ||
659 | expect![[""]], | ||
660 | ) | ||
661 | } | ||
662 | |||
663 | #[test] | ||
664 | fn completes_type_or_trait_in_impl_block() { | ||
665 | check( | ||
666 | r#" | ||
667 | trait MyTrait {} | ||
668 | struct MyStruct {} | ||
669 | |||
670 | impl My<|> | ||
671 | "#, | ||
672 | expect![[r#" | ||
673 | st MyStruct | ||
674 | tt MyTrait | ||
675 | tp Self | ||
676 | "#]], | ||
677 | ) | ||
678 | } | ||
679 | } | ||