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