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