]> git.lizzy.rs Git - rust.git/blob - crates/completion/src/completions/qualified_path.rs
Merge #7706
[rust.git] / crates / completion / src / completions / qualified_path.rs
1 //! Completion of paths, i.e. `some::prefix::$0`.
2
3 use hir::{Adt, HasVisibility, PathResolution, ScopeDef};
4 use rustc_hash::FxHashSet;
5 use syntax::AstNode;
6 use test_utils::mark;
7
8 use crate::{CompletionContext, Completions};
9
10 pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
11     let path = match &ctx.path_qual {
12         Some(path) => path.clone(),
13         None => return,
14     };
15
16     if ctx.attribute_under_caret.is_some() || ctx.mod_declaration_under_caret.is_some() {
17         return;
18     }
19
20     let context_module = ctx.scope.module();
21
22     let resolution = match ctx.sema.resolve_path(&path) {
23         Some(res) => res,
24         None => return,
25     };
26
27     // Add associated types on type parameters and `Self`.
28     resolution.assoc_type_shorthand_candidates(ctx.db, |alias| {
29         acc.add_type_alias(ctx, alias);
30         None::<()>
31     });
32
33     match resolution {
34         PathResolution::Def(hir::ModuleDef::Module(module)) => {
35             let module_scope = module.scope(ctx.db, context_module);
36             for (name, def) in module_scope {
37                 if ctx.use_item_syntax.is_some() {
38                     if let ScopeDef::Unknown = def {
39                         if let Some(name_ref) = ctx.name_ref_syntax.as_ref() {
40                             if name_ref.syntax().text() == name.to_string().as_str() {
41                                 // for `use self::foo$0`, don't suggest `foo` as a completion
42                                 mark::hit!(dont_complete_current_use);
43                                 continue;
44                             }
45                         }
46                     }
47                 }
48
49                 acc.add_resolution(ctx, name.to_string(), &def);
50             }
51         }
52         PathResolution::Def(def @ hir::ModuleDef::Adt(_))
53         | PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_))
54         | PathResolution::Def(def @ hir::ModuleDef::BuiltinType(_)) => {
55             if let hir::ModuleDef::Adt(Adt::Enum(e)) = def {
56                 for variant in e.variants(ctx.db) {
57                     acc.add_enum_variant(ctx, variant, None);
58                 }
59             }
60             let ty = match def {
61                 hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
62                 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
63                 hir::ModuleDef::BuiltinType(builtin) => {
64                     let module = match ctx.scope.module() {
65                         Some(it) => it,
66                         None => return,
67                     };
68                     builtin.ty(ctx.db, module)
69                 }
70                 _ => unreachable!(),
71             };
72
73             // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
74             // (where AssocType is defined on a trait, not an inherent impl)
75
76             let krate = ctx.krate;
77             if let Some(krate) = krate {
78                 let traits_in_scope = ctx.scope.traits_in_scope();
79                 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
80                     if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
81                         return None;
82                     }
83                     match item {
84                         hir::AssocItem::Function(func) => {
85                             acc.add_function(ctx, func, None);
86                         }
87                         hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
88                         hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
89                     }
90                     None::<()>
91                 });
92
93                 // Iterate assoc types separately
94                 ty.iterate_assoc_items(ctx.db, krate, |item| {
95                     if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
96                         return None;
97                     }
98                     match item {
99                         hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}
100                         hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
101                     }
102                     None::<()>
103                 });
104             }
105         }
106         PathResolution::Def(hir::ModuleDef::Trait(t)) => {
107             // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
108             for item in t.items(ctx.db) {
109                 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
110                     continue;
111                 }
112                 match item {
113                     hir::AssocItem::Function(func) => {
114                         acc.add_function(ctx, func, None);
115                     }
116                     hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
117                     hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
118                 }
119             }
120         }
121         PathResolution::TypeParam(_) | PathResolution::SelfType(_) => {
122             if let Some(krate) = ctx.krate {
123                 let ty = match resolution {
124                     PathResolution::TypeParam(param) => param.ty(ctx.db),
125                     PathResolution::SelfType(impl_def) => impl_def.target_ty(ctx.db),
126                     _ => return,
127                 };
128
129                 if let Some(Adt::Enum(e)) = ty.as_adt() {
130                     for variant in e.variants(ctx.db) {
131                         acc.add_enum_variant(ctx, variant, None);
132                     }
133                 }
134
135                 let traits_in_scope = ctx.scope.traits_in_scope();
136                 let mut seen = FxHashSet::default();
137                 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
138                     if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
139                         return None;
140                     }
141
142                     // We might iterate candidates of a trait multiple times here, so deduplicate
143                     // them.
144                     if seen.insert(item) {
145                         match item {
146                             hir::AssocItem::Function(func) => {
147                                 acc.add_function(ctx, func, None);
148                             }
149                             hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
150                             hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
151                         }
152                     }
153                     None::<()>
154                 });
155             }
156         }
157         _ => {}
158     }
159 }
160
161 #[cfg(test)]
162 mod tests {
163     use expect_test::{expect, Expect};
164     use test_utils::mark;
165
166     use crate::{
167         test_utils::{check_edit, completion_list},
168         CompletionKind,
169     };
170
171     fn check(ra_fixture: &str, expect: Expect) {
172         let actual = completion_list(ra_fixture, CompletionKind::Reference);
173         expect.assert_eq(&actual);
174     }
175
176     fn check_builtin(ra_fixture: &str, expect: Expect) {
177         let actual = completion_list(ra_fixture, CompletionKind::BuiltinType);
178         expect.assert_eq(&actual);
179     }
180
181     #[test]
182     fn dont_complete_current_use() {
183         mark::check!(dont_complete_current_use);
184         check(r#"use self::foo$0;"#, expect![[""]]);
185     }
186
187     #[test]
188     fn dont_complete_current_use_in_braces_with_glob() {
189         check(
190             r#"
191 mod foo { pub struct S; }
192 use self::{foo::*, bar$0};
193 "#,
194             expect![[r#"
195                 st S
196                 md foo
197             "#]],
198         );
199     }
200
201     #[test]
202     fn dont_complete_primitive_in_use() {
203         check_builtin(r#"use self::$0;"#, expect![[""]]);
204     }
205
206     #[test]
207     fn dont_complete_primitive_in_module_scope() {
208         check_builtin(r#"fn foo() { self::$0 }"#, expect![[""]]);
209     }
210
211     #[test]
212     fn completes_primitives() {
213         check_builtin(
214             r#"fn main() { let _: $0 = 92; }"#,
215             expect![[r#"
216                 bt u32
217                 bt bool
218                 bt u8
219                 bt isize
220                 bt u16
221                 bt u64
222                 bt u128
223                 bt f32
224                 bt i128
225                 bt i16
226                 bt str
227                 bt i64
228                 bt char
229                 bt f64
230                 bt i32
231                 bt i8
232                 bt usize
233             "#]],
234         );
235     }
236
237     #[test]
238     fn completes_mod_with_same_name_as_function() {
239         check(
240             r#"
241 use self::my::$0;
242
243 mod my { pub struct Bar; }
244 fn my() {}
245 "#,
246             expect![[r#"
247                 st Bar
248             "#]],
249         );
250     }
251
252     #[test]
253     fn filters_visibility() {
254         check(
255             r#"
256 use self::my::$0;
257
258 mod my {
259     struct Bar;
260     pub struct Foo;
261     pub use Bar as PublicBar;
262 }
263 "#,
264             expect![[r#"
265                 st Foo
266                 st PublicBar
267             "#]],
268         );
269     }
270
271     #[test]
272     fn completes_use_item_starting_with_self() {
273         check(
274             r#"
275 use self::m::$0;
276
277 mod m { pub struct Bar; }
278 "#,
279             expect![[r#"
280                 st Bar
281             "#]],
282         );
283     }
284
285     #[test]
286     fn completes_use_item_starting_with_crate() {
287         check(
288             r#"
289 //- /lib.rs
290 mod foo;
291 struct Spam;
292 //- /foo.rs
293 use crate::Sp$0
294 "#,
295             expect![[r#"
296                 md foo
297                 st Spam
298             "#]],
299         );
300     }
301
302     #[test]
303     fn completes_nested_use_tree() {
304         check(
305             r#"
306 //- /lib.rs
307 mod foo;
308 struct Spam;
309 //- /foo.rs
310 use crate::{Sp$0};
311 "#,
312             expect![[r#"
313                 md foo
314                 st Spam
315             "#]],
316         );
317     }
318
319     #[test]
320     fn completes_deeply_nested_use_tree() {
321         check(
322             r#"
323 //- /lib.rs
324 mod foo;
325 pub mod bar {
326     pub mod baz {
327         pub struct Spam;
328     }
329 }
330 //- /foo.rs
331 use crate::{bar::{baz::Sp$0}};
332 "#,
333             expect![[r#"
334                 st Spam
335             "#]],
336         );
337     }
338
339     #[test]
340     fn completes_enum_variant() {
341         check(
342             r#"
343 enum E { Foo, Bar(i32) }
344 fn foo() { let _ = E::$0 }
345 "#,
346             expect![[r#"
347                 ev Foo    ()
348                 ev Bar(…) (i32)
349             "#]],
350         );
351     }
352
353     #[test]
354     fn completes_struct_associated_items() {
355         check(
356             r#"
357 //- /lib.rs
358 struct S;
359
360 impl S {
361     fn a() {}
362     fn b(&self) {}
363     const C: i32 = 42;
364     type T = i32;
365 }
366
367 fn foo() { let _ = S::$0 }
368 "#,
369             expect![[r#"
370                 fn a()  -> ()
371                 me b(…) -> ()
372                 ct C    const C: i32 = 42;
373                 ta T    type T = i32;
374             "#]],
375         );
376     }
377
378     #[test]
379     fn associated_item_visibility() {
380         check(
381             r#"
382 struct S;
383
384 mod m {
385     impl super::S {
386         pub(crate) fn public_method() { }
387         fn private_method() { }
388         pub(crate) type PublicType = u32;
389         type PrivateType = u32;
390         pub(crate) const PUBLIC_CONST: u32 = 1;
391         const PRIVATE_CONST: u32 = 1;
392     }
393 }
394
395 fn foo() { let _ = S::$0 }
396 "#,
397             expect![[r#"
398                 fn public_method() -> ()
399                 ct PUBLIC_CONST    pub(crate) const PUBLIC_CONST: u32 = 1;
400                 ta PublicType      pub(crate) type PublicType = u32;
401             "#]],
402         );
403     }
404
405     #[test]
406     fn completes_enum_associated_method() {
407         check(
408             r#"
409 enum E {};
410 impl E { fn m() { } }
411
412 fn foo() { let _ = E::$0 }
413         "#,
414             expect![[r#"
415                 fn m() -> ()
416             "#]],
417         );
418     }
419
420     #[test]
421     fn completes_union_associated_method() {
422         check(
423             r#"
424 union U {};
425 impl U { fn m() { } }
426
427 fn foo() { let _ = U::$0 }
428 "#,
429             expect![[r#"
430                 fn m() -> ()
431             "#]],
432         );
433     }
434
435     #[test]
436     fn completes_use_paths_across_crates() {
437         check(
438             r#"
439 //- /main.rs crate:main deps:foo
440 use foo::$0;
441
442 //- /foo/lib.rs crate:foo
443 pub mod bar { pub struct S; }
444 "#,
445             expect![[r#"
446                 md bar
447             "#]],
448         );
449     }
450
451     #[test]
452     fn completes_trait_associated_method_1() {
453         check(
454             r#"
455 trait Trait { fn m(); }
456
457 fn foo() { let _ = Trait::$0 }
458 "#,
459             expect![[r#"
460                 fn m() -> ()
461             "#]],
462         );
463     }
464
465     #[test]
466     fn completes_trait_associated_method_2() {
467         check(
468             r#"
469 trait Trait { fn m(); }
470
471 struct S;
472 impl Trait for S {}
473
474 fn foo() { let _ = S::$0 }
475 "#,
476             expect![[r#"
477                 fn m() -> ()
478             "#]],
479         );
480     }
481
482     #[test]
483     fn completes_trait_associated_method_3() {
484         check(
485             r#"
486 trait Trait { fn m(); }
487
488 struct S;
489 impl Trait for S {}
490
491 fn foo() { let _ = <S as Trait>::$0 }
492 "#,
493             expect![[r#"
494                 fn m() -> ()
495             "#]],
496         );
497     }
498
499     #[test]
500     fn completes_ty_param_assoc_ty() {
501         check(
502             r#"
503 trait Super {
504     type Ty;
505     const CONST: u8;
506     fn func() {}
507     fn method(&self) {}
508 }
509
510 trait Sub: Super {
511     type SubTy;
512     const C2: ();
513     fn subfunc() {}
514     fn submethod(&self) {}
515 }
516
517 fn foo<T: Sub>() { T::$0 }
518 "#,
519             expect![[r#"
520                 ta SubTy        type SubTy;
521                 ta Ty           type Ty;
522                 ct C2           const C2: ();
523                 fn subfunc()    -> ()
524                 me submethod(…) -> ()
525                 ct CONST        const CONST: u8;
526                 fn func()       -> ()
527                 me method(…)    -> ()
528             "#]],
529         );
530     }
531
532     #[test]
533     fn completes_self_param_assoc_ty() {
534         check(
535             r#"
536 trait Super {
537     type Ty;
538     const CONST: u8 = 0;
539     fn func() {}
540     fn method(&self) {}
541 }
542
543 trait Sub: Super {
544     type SubTy;
545     const C2: () = ();
546     fn subfunc() {}
547     fn submethod(&self) {}
548 }
549
550 struct Wrap<T>(T);
551 impl<T> Super for Wrap<T> {}
552 impl<T> Sub for Wrap<T> {
553     fn subfunc() {
554         // Should be able to assume `Self: Sub + Super`
555         Self::$0
556     }
557 }
558 "#,
559             expect![[r#"
560                 ta SubTy        type SubTy;
561                 ta Ty           type Ty;
562                 ct CONST        const CONST: u8 = 0;
563                 fn func()       -> ()
564                 me method(…)    -> ()
565                 ct C2           const C2: () = ();
566                 fn subfunc()    -> ()
567                 me submethod(…) -> ()
568             "#]],
569         );
570     }
571
572     #[test]
573     fn completes_type_alias() {
574         check(
575             r#"
576 struct S;
577 impl S { fn foo() {} }
578 type T = S;
579 impl T { fn bar() {} }
580
581 fn main() { T::$0; }
582 "#,
583             expect![[r#"
584                 fn foo() -> ()
585                 fn bar() -> ()
586             "#]],
587         );
588     }
589
590     #[test]
591     fn completes_qualified_macros() {
592         check(
593             r#"
594 #[macro_export]
595 macro_rules! foo { () => {} }
596
597 fn main() { let _ = crate::$0 }
598         "#,
599             expect![[r##"
600                 fn main()  -> ()
601                 ma foo!(…) #[macro_export] macro_rules! foo
602             "##]],
603         );
604     }
605
606     #[test]
607     fn test_super_super_completion() {
608         check(
609             r#"
610 mod a {
611     const A: usize = 0;
612     mod b {
613         const B: usize = 0;
614         mod c { use super::super::$0 }
615     }
616 }
617 "#,
618             expect![[r#"
619                 md b
620                 ct A
621             "#]],
622         );
623     }
624
625     #[test]
626     fn completes_reexported_items_under_correct_name() {
627         check(
628             r#"
629 fn foo() { self::m::$0 }
630
631 mod m {
632     pub use super::p::wrong_fn as right_fn;
633     pub use super::p::WRONG_CONST as RIGHT_CONST;
634     pub use super::p::WrongType as RightType;
635 }
636 mod p {
637     fn wrong_fn() {}
638     const WRONG_CONST: u32 = 1;
639     struct WrongType {};
640 }
641 "#,
642             expect![[r#"
643                 ct RIGHT_CONST
644                 fn right_fn()  -> ()
645                 st RightType
646             "#]],
647         );
648
649         check_edit(
650             "RightType",
651             r#"
652 fn foo() { self::m::$0 }
653
654 mod m {
655     pub use super::p::wrong_fn as right_fn;
656     pub use super::p::WRONG_CONST as RIGHT_CONST;
657     pub use super::p::WrongType as RightType;
658 }
659 mod p {
660     fn wrong_fn() {}
661     const WRONG_CONST: u32 = 1;
662     struct WrongType {};
663 }
664 "#,
665             r#"
666 fn foo() { self::m::RightType }
667
668 mod m {
669     pub use super::p::wrong_fn as right_fn;
670     pub use super::p::WRONG_CONST as RIGHT_CONST;
671     pub use super::p::WrongType as RightType;
672 }
673 mod p {
674     fn wrong_fn() {}
675     const WRONG_CONST: u32 = 1;
676     struct WrongType {};
677 }
678 "#,
679         );
680     }
681
682     #[test]
683     fn completes_in_simple_macro_call() {
684         check(
685             r#"
686 macro_rules! m { ($e:expr) => { $e } }
687 fn main() { m!(self::f$0); }
688 fn foo() {}
689 "#,
690             expect![[r#"
691                 fn main() -> ()
692                 fn foo()  -> ()
693             "#]],
694         );
695     }
696
697     #[test]
698     fn function_mod_share_name() {
699         check(
700             r#"
701 fn foo() { self::m::$0 }
702
703 mod m {
704     pub mod z {}
705     pub fn z() {}
706 }
707 "#,
708             expect![[r#"
709                 md z
710                 fn z() -> ()
711             "#]],
712         );
713     }
714
715     #[test]
716     fn completes_hashmap_new() {
717         check(
718             r#"
719 struct RandomState;
720 struct HashMap<K, V, S = RandomState> {}
721
722 impl<K, V> HashMap<K, V, RandomState> {
723     pub fn new() -> HashMap<K, V, RandomState> { }
724 }
725 fn foo() {
726     HashMap::$0
727 }
728 "#,
729             expect![[r#"
730                 fn new() -> HashMap<K, V, RandomState>
731             "#]],
732         );
733     }
734
735     #[test]
736     fn dont_complete_attr() {
737         check(
738             r#"
739 mod foo { pub struct Foo; }
740 #[foo::$0]
741 fn f() {}
742 "#,
743             expect![[""]],
744         );
745     }
746
747     #[test]
748     fn completes_function() {
749         check(
750             r#"
751 fn foo(
752     a: i32,
753     b: i32
754 ) {
755
756 }
757
758 fn main() {
759     fo$0
760 }
761 "#,
762             expect![[r#"
763                 fn main() -> ()
764                 fn foo(…) -> ()
765             "#]],
766         );
767     }
768
769     #[test]
770     fn completes_self_enum() {
771         check(
772             r#"
773 enum Foo {
774     Bar,
775     Baz,
776 }
777
778 impl Foo {
779     fn foo(self) {
780         Self::$0
781     }
782 }
783 "#,
784             expect![[r#"
785                 ev Bar    ()
786                 ev Baz    ()
787                 me foo(…) -> ()
788             "#]],
789         );
790     }
791
792     #[test]
793     fn completes_primitive_assoc_const() {
794         check(
795             r#"
796 //- /lib.rs crate:lib deps:core
797 fn f() {
798     u8::$0
799 }
800
801 //- /core.rs crate:core
802 #[lang = "u8"]
803 impl u8 {
804     pub const MAX: Self = 255;
805
806     pub fn func(self) {}
807 }
808 "#,
809             expect![[r#"
810                 ct MAX     pub const MAX: Self = 255;
811                 me func(…) -> ()
812             "#]],
813         );
814     }
815 }