1 //! Completion of paths, i.e. `some::prefix::$0`.
2 
3 use std::iter;
4 
5 use hir::ScopeDef;
6 use rustc_hash::FxHashSet;
7 use syntax::{ast, AstNode};
8 
9 use crate::{
10     context::{PathCompletionContext, PathKind},
11     patterns::ImmediateLocation,
12     CompletionContext, Completions,
13 };
14 
complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext)15 pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
16     if ctx.is_path_disallowed() || ctx.has_impl_or_trait_prev_sibling() {
17         return;
18     }
19     let (path, use_tree_parent, kind) = match ctx.path_context {
20         // let ... else, syntax would come in really handy here right now
21         Some(PathCompletionContext {
22             qualifier: Some(ref qualifier),
23             use_tree_parent,
24             kind,
25             ..
26         }) => (qualifier, use_tree_parent, kind),
27         _ => return,
28     };
29 
30     let resolution = match ctx.sema.resolve_path(path) {
31         Some(res) => res,
32         None => return,
33     };
34 
35     let context_module = ctx.scope.module();
36 
37     match ctx.completion_location {
38         Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
39             if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
40                 for (name, def) in module.scope(ctx.db, context_module) {
41                     if let ScopeDef::MacroDef(macro_def) = def {
42                         if macro_def.is_fn_like() {
43                             acc.add_macro(ctx, Some(name.clone()), macro_def);
44                         }
45                     }
46                     if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = def {
47                         acc.add_resolution(ctx, name, &def);
48                     }
49                 }
50             }
51             return;
52         }
53         _ => (),
54     }
55 
56     match kind {
57         Some(PathKind::Vis { .. }) => {
58             if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
59                 if let Some(current_module) = ctx.scope.module() {
60                     if let Some(next) = current_module
61                         .path_to_root(ctx.db)
62                         .into_iter()
63                         .take_while(|&it| it != module)
64                         .next()
65                     {
66                         if let Some(name) = next.name(ctx.db) {
67                             acc.add_resolution(ctx, name, &ScopeDef::ModuleDef(next.into()));
68                         }
69                     }
70                 }
71             }
72             return;
73         }
74         Some(PathKind::Attr) => {
75             if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
76                 for (name, def) in module.scope(ctx.db, context_module) {
77                     let add_resolution = match def {
78                         ScopeDef::MacroDef(mac) => mac.is_attr(),
79                         ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => true,
80                         _ => false,
81                     };
82                     if add_resolution {
83                         acc.add_resolution(ctx, name, &def);
84                     }
85                 }
86             }
87             return;
88         }
89         Some(PathKind::Use) => {
90             if iter::successors(Some(path.clone()), |p| p.qualifier())
91                 .all(|p| p.segment().and_then(|s| s.super_token()).is_some())
92             {
93                 acc.add_keyword(ctx, "super::");
94             }
95             // only show `self` in a new use-tree when the qualifier doesn't end in self
96             if use_tree_parent
97                 && !matches!(
98                     path.segment().and_then(|it| it.kind()),
99                     Some(ast::PathSegmentKind::SelfKw)
100                 )
101             {
102                 acc.add_keyword(ctx, "self");
103             }
104         }
105         _ => (),
106     }
107 
108     if !matches!(kind, Some(PathKind::Pat)) {
109         // Add associated types on type parameters and `Self`.
110         resolution.assoc_type_shorthand_candidates(ctx.db, |_, alias| {
111             acc.add_type_alias(ctx, alias);
112             None::<()>
113         });
114     }
115 
116     match resolution {
117         hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
118             let module_scope = module.scope(ctx.db, context_module);
119             for (name, def) in module_scope {
120                 if let Some(PathKind::Use) = kind {
121                     if let ScopeDef::Unknown = def {
122                         if let Some(ast::NameLike::NameRef(name_ref)) = ctx.name_syntax.as_ref() {
123                             if name_ref.syntax().text() == name.to_smol_str().as_str() {
124                                 // for `use self::foo$0`, don't suggest `foo` as a completion
125                                 cov_mark::hit!(dont_complete_current_use);
126                                 continue;
127                             }
128                         }
129                     }
130                 }
131 
132                 let add_resolution = match def {
133                     // Don't suggest attribute macros and derives.
134                     ScopeDef::MacroDef(mac) => mac.is_fn_like(),
135                     // no values in type places
136                     ScopeDef::ModuleDef(
137                         hir::ModuleDef::Function(_)
138                         | hir::ModuleDef::Variant(_)
139                         | hir::ModuleDef::Static(_),
140                     )
141                     | ScopeDef::Local(_) => !ctx.expects_type(),
142                     // unless its a constant in a generic arg list position
143                     ScopeDef::ModuleDef(hir::ModuleDef::Const(_)) => {
144                         !ctx.expects_type() || ctx.expects_generic_arg()
145                     }
146                     _ => true,
147                 };
148 
149                 if add_resolution {
150                     acc.add_resolution(ctx, name, &def);
151                 }
152             }
153         }
154         hir::PathResolution::Def(
155             def
156             @
157             (hir::ModuleDef::Adt(_)
158             | hir::ModuleDef::TypeAlias(_)
159             | hir::ModuleDef::BuiltinType(_)),
160         ) => {
161             if let hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def {
162                 add_enum_variants(acc, ctx, e);
163             }
164             let ty = match def {
165                 hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
166                 hir::ModuleDef::TypeAlias(a) => {
167                     let ty = a.ty(ctx.db);
168                     if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
169                         cov_mark::hit!(completes_variant_through_alias);
170                         add_enum_variants(acc, ctx, e);
171                     }
172                     ty
173                 }
174                 hir::ModuleDef::BuiltinType(builtin) => {
175                     let module = match ctx.scope.module() {
176                         Some(it) => it,
177                         None => return,
178                     };
179                     cov_mark::hit!(completes_primitive_assoc_const);
180                     builtin.ty(ctx.db, module)
181                 }
182                 _ => unreachable!(),
183             };
184 
185             // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
186             // (where AssocType is defined on a trait, not an inherent impl)
187 
188             let krate = ctx.krate;
189             if let Some(krate) = krate {
190                 let traits_in_scope = ctx.scope.visible_traits();
191                 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
192                     add_assoc_item(acc, ctx, item);
193                     None::<()>
194                 });
195 
196                 // Iterate assoc types separately
197                 ty.iterate_assoc_items(ctx.db, krate, |item| {
198                     if let hir::AssocItem::TypeAlias(ty) = item {
199                         acc.add_type_alias(ctx, ty)
200                     }
201                     None::<()>
202                 });
203             }
204         }
205         hir::PathResolution::Def(hir::ModuleDef::Trait(t)) => {
206             // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
207             for item in t.items(ctx.db) {
208                 add_assoc_item(acc, ctx, item);
209             }
210         }
211         hir::PathResolution::TypeParam(_) | hir::PathResolution::SelfType(_) => {
212             if let Some(krate) = ctx.krate {
213                 let ty = match resolution {
214                     hir::PathResolution::TypeParam(param) => param.ty(ctx.db),
215                     hir::PathResolution::SelfType(impl_def) => impl_def.self_ty(ctx.db),
216                     _ => return,
217                 };
218 
219                 if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
220                     add_enum_variants(acc, ctx, e);
221                 }
222 
223                 let traits_in_scope = ctx.scope.visible_traits();
224                 let mut seen = FxHashSet::default();
225                 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
226                     // We might iterate candidates of a trait multiple times here, so deduplicate
227                     // them.
228                     if seen.insert(item) {
229                         add_assoc_item(acc, ctx, item);
230                     }
231                     None::<()>
232                 });
233             }
234         }
235         hir::PathResolution::Macro(mac) => acc.add_macro(ctx, None, mac),
236         _ => {}
237     }
238 }
239 
add_assoc_item(acc: &mut Completions, ctx: &CompletionContext, item: hir::AssocItem)240 fn add_assoc_item(acc: &mut Completions, ctx: &CompletionContext, item: hir::AssocItem) {
241     match item {
242         hir::AssocItem::Function(func) if !ctx.expects_type() => acc.add_function(ctx, func, None),
243         hir::AssocItem::Const(ct) if !ctx.expects_type() || ctx.expects_generic_arg() => {
244             acc.add_const(ctx, ct)
245         }
246         hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
247         _ => (),
248     }
249 }
250 
add_enum_variants(acc: &mut Completions, ctx: &CompletionContext, e: hir::Enum)251 fn add_enum_variants(acc: &mut Completions, ctx: &CompletionContext, e: hir::Enum) {
252     if ctx.expects_type() {
253         return;
254     }
255     e.variants(ctx.db).into_iter().for_each(|variant| acc.add_enum_variant(ctx, variant, None));
256 }
257 
258 #[cfg(test)]
259 mod tests {
260     use expect_test::{expect, Expect};
261 
262     use crate::tests::{check_edit, completion_list_no_kw};
263 
check(ra_fixture: &str, expect: Expect)264     fn check(ra_fixture: &str, expect: Expect) {
265         let actual = completion_list_no_kw(ra_fixture);
266         expect.assert_eq(&actual);
267     }
268 
269     #[test]
associated_item_visibility()270     fn associated_item_visibility() {
271         check(
272             r#"
273 //- /lib.rs crate:lib new_source_root:library
274 pub struct S;
275 
276 impl S {
277     pub fn public_method() { }
278     fn private_method() { }
279     pub type PublicType = u32;
280     type PrivateType = u32;
281     pub const PUBLIC_CONST: u32 = 1;
282     const PRIVATE_CONST: u32 = 1;
283 }
284 
285 //- /main.rs crate:main deps:lib new_source_root:local
286 fn foo() { let _ = lib::S::$0 }
287 "#,
288             expect![[r#"
289                 fn public_method() fn()
290                 ct PUBLIC_CONST    pub const PUBLIC_CONST: u32;
291                 ta PublicType      pub type PublicType;
292             "#]],
293         );
294     }
295 
296     #[test]
completes_union_associated_method()297     fn completes_union_associated_method() {
298         check(
299             r#"
300 union U {};
301 impl U { fn m() { } }
302 
303 fn foo() { let _ = U::$0 }
304 "#,
305             expect![[r#"
306                 fn m() fn()
307             "#]],
308         );
309     }
310 
311     #[test]
completes_trait_associated_method_1()312     fn completes_trait_associated_method_1() {
313         check(
314             r#"
315 trait Trait { fn m(); }
316 
317 fn foo() { let _ = Trait::$0 }
318 "#,
319             expect![[r#"
320                 fn m() (as Trait) fn()
321             "#]],
322         );
323     }
324 
325     #[test]
completes_trait_associated_method_2()326     fn completes_trait_associated_method_2() {
327         check(
328             r#"
329 trait Trait { fn m(); }
330 
331 struct S;
332 impl Trait for S {}
333 
334 fn foo() { let _ = S::$0 }
335 "#,
336             expect![[r#"
337                 fn m() (as Trait) fn()
338             "#]],
339         );
340     }
341 
342     #[test]
completes_trait_associated_method_3()343     fn completes_trait_associated_method_3() {
344         check(
345             r#"
346 trait Trait { fn m(); }
347 
348 struct S;
349 impl Trait for S {}
350 
351 fn foo() { let _ = <S as Trait>::$0 }
352 "#,
353             expect![[r#"
354                 fn m() (as Trait) fn()
355             "#]],
356         );
357     }
358 
359     #[test]
completes_ty_param_assoc_ty()360     fn completes_ty_param_assoc_ty() {
361         check(
362             r#"
363 trait Super {
364     type Ty;
365     const CONST: u8;
366     fn func() {}
367     fn method(&self) {}
368 }
369 
370 trait Sub: Super {
371     type SubTy;
372     const C2: ();
373     fn subfunc() {}
374     fn submethod(&self) {}
375 }
376 
377 fn foo<T: Sub>() { T::$0 }
378 "#,
379             expect![[r#"
380                 ta SubTy (as Sub)        type SubTy;
381                 ta Ty (as Super)         type Ty;
382                 ct C2 (as Sub)           const C2: ();
383                 fn subfunc() (as Sub)    fn()
384                 me submethod(…) (as Sub) fn(&self)
385                 ct CONST (as Super)      const CONST: u8;
386                 fn func() (as Super)     fn()
387                 me method(…) (as Super)  fn(&self)
388             "#]],
389         );
390     }
391 
392     #[test]
completes_self_param_assoc_ty()393     fn completes_self_param_assoc_ty() {
394         check(
395             r#"
396 trait Super {
397     type Ty;
398     const CONST: u8 = 0;
399     fn func() {}
400     fn method(&self) {}
401 }
402 
403 trait Sub: Super {
404     type SubTy;
405     const C2: () = ();
406     fn subfunc() {}
407     fn submethod(&self) {}
408 }
409 
410 struct Wrap<T>(T);
411 impl<T> Super for Wrap<T> {}
412 impl<T> Sub for Wrap<T> {
413     fn subfunc() {
414         // Should be able to assume `Self: Sub + Super`
415         Self::$0
416     }
417 }
418 "#,
419             expect![[r#"
420                 ta SubTy (as Sub)        type SubTy;
421                 ta Ty (as Super)         type Ty;
422                 ct CONST (as Super)      const CONST: u8;
423                 fn func() (as Super)     fn()
424                 me method(…) (as Super)  fn(&self)
425                 ct C2 (as Sub)           const C2: ();
426                 fn subfunc() (as Sub)    fn()
427                 me submethod(…) (as Sub) fn(&self)
428             "#]],
429         );
430     }
431 
432     #[test]
completes_type_alias()433     fn completes_type_alias() {
434         check(
435             r#"
436 struct S;
437 impl S { fn foo() {} }
438 type T = S;
439 impl T { fn bar() {} }
440 
441 fn main() { T::$0; }
442 "#,
443             expect![[r#"
444                 fn foo() fn()
445                 fn bar() fn()
446             "#]],
447         );
448     }
449 
450     #[test]
completes_qualified_macros()451     fn completes_qualified_macros() {
452         check(
453             r#"
454 #[macro_export]
455 macro_rules! foo { () => {} }
456 
457 fn main() { let _ = crate::$0 }
458 "#,
459             expect![[r##"
460                 fn main()  fn()
461                 ma foo!(…) #[macro_export] macro_rules! foo
462             "##]],
463         );
464     }
465 
466     #[test]
does_not_complete_non_fn_macros()467     fn does_not_complete_non_fn_macros() {
468         check(
469             r#"
470 mod m {
471     #[rustc_builtin_macro]
472     pub macro Clone {}
473 }
474 
475 fn f() {m::$0}
476 "#,
477             expect![[r#""#]],
478         );
479         check(
480             r#"
481 mod m {
482     #[rustc_builtin_macro]
483     pub macro bench {}
484 }
485 
486 fn f() {m::$0}
487 "#,
488             expect![[r#""#]],
489         );
490     }
491 
492     #[test]
completes_reexported_items_under_correct_name()493     fn completes_reexported_items_under_correct_name() {
494         check(
495             r#"
496 fn foo() { self::m::$0 }
497 
498 mod m {
499     pub use super::p::wrong_fn as right_fn;
500     pub use super::p::WRONG_CONST as RIGHT_CONST;
501     pub use super::p::WrongType as RightType;
502 }
503 mod p {
504     fn wrong_fn() {}
505     const WRONG_CONST: u32 = 1;
506     struct WrongType {};
507 }
508 "#,
509             expect![[r#"
510                 ct RIGHT_CONST
511                 fn right_fn()  fn()
512                 st RightType
513             "#]],
514         );
515 
516         check_edit(
517             "RightType",
518             r#"
519 fn foo() { self::m::$0 }
520 
521 mod m {
522     pub use super::p::wrong_fn as right_fn;
523     pub use super::p::WRONG_CONST as RIGHT_CONST;
524     pub use super::p::WrongType as RightType;
525 }
526 mod p {
527     fn wrong_fn() {}
528     const WRONG_CONST: u32 = 1;
529     struct WrongType {};
530 }
531 "#,
532             r#"
533 fn foo() { self::m::RightType }
534 
535 mod m {
536     pub use super::p::wrong_fn as right_fn;
537     pub use super::p::WRONG_CONST as RIGHT_CONST;
538     pub use super::p::WrongType as RightType;
539 }
540 mod p {
541     fn wrong_fn() {}
542     const WRONG_CONST: u32 = 1;
543     struct WrongType {};
544 }
545 "#,
546         );
547     }
548 
549     #[test]
completes_in_simple_macro_call()550     fn completes_in_simple_macro_call() {
551         check(
552             r#"
553 macro_rules! m { ($e:expr) => { $e } }
554 fn main() { m!(self::f$0); }
555 fn foo() {}
556 "#,
557             expect![[r#"
558                 fn main() fn()
559                 fn foo()  fn()
560             "#]],
561         );
562     }
563 
564     #[test]
function_mod_share_name()565     fn function_mod_share_name() {
566         check(
567             r#"
568 fn foo() { self::m::$0 }
569 
570 mod m {
571     pub mod z {}
572     pub fn z() {}
573 }
574 "#,
575             expect![[r#"
576                 md z
577                 fn z() fn()
578             "#]],
579         );
580     }
581 
582     #[test]
completes_hashmap_new()583     fn completes_hashmap_new() {
584         check(
585             r#"
586 struct RandomState;
587 struct HashMap<K, V, S = RandomState> {}
588 
589 impl<K, V> HashMap<K, V, RandomState> {
590     pub fn new() -> HashMap<K, V, RandomState> { }
591 }
592 fn foo() {
593     HashMap::$0
594 }
595 "#,
596             expect![[r#"
597                 fn new() fn() -> HashMap<K, V, RandomState>
598             "#]],
599         );
600     }
601 
602     #[test]
dont_complete_attr()603     fn dont_complete_attr() {
604         check(
605             r#"
606 mod foo { pub struct Foo; }
607 #[foo::$0]
608 fn f() {}
609 "#,
610             expect![[""]],
611         );
612     }
613 
614     #[test]
completes_variant_through_self()615     fn completes_variant_through_self() {
616         check(
617             r#"
618 enum Foo {
619     Bar,
620     Baz,
621 }
622 
623 impl Foo {
624     fn foo(self) {
625         Self::$0
626     }
627 }
628 "#,
629             expect![[r#"
630                 ev Bar    ()
631                 ev Baz    ()
632                 me foo(…) fn(self)
633             "#]],
634         );
635     }
636 
637     #[test]
completes_primitive_assoc_const()638     fn completes_primitive_assoc_const() {
639         cov_mark::check!(completes_primitive_assoc_const);
640         check(
641             r#"
642 //- /lib.rs crate:lib deps:core
643 fn f() {
644     u8::$0
645 }
646 
647 //- /core.rs crate:core
648 #[lang = "u8"]
649 impl u8 {
650     pub const MAX: Self = 255;
651 
652     pub fn func(self) {}
653 }
654 "#,
655             expect![[r#"
656                 ct MAX     pub const MAX: Self;
657                 me func(…) fn(self)
658             "#]],
659         );
660     }
661 
662     #[test]
completes_variant_through_alias()663     fn completes_variant_through_alias() {
664         cov_mark::check!(completes_variant_through_alias);
665         check(
666             r#"
667 enum Foo {
668     Bar
669 }
670 type Foo2 = Foo;
671 fn main() {
672     Foo2::$0
673 }
674 "#,
675             expect![[r#"
676                 ev Bar ()
677             "#]],
678         );
679     }
680 
681     #[test]
respects_doc_hidden()682     fn respects_doc_hidden() {
683         cov_mark::check!(qualified_path_doc_hidden);
684         check(
685             r#"
686 //- /lib.rs crate:lib deps:dep
687 fn f() {
688     dep::$0
689 }
690 
691 //- /dep.rs crate:dep
692 #[doc(hidden)]
693 #[macro_export]
694 macro_rules! m {
695     () => {}
696 }
697 
698 #[doc(hidden)]
699 pub fn f() {}
700 
701 #[doc(hidden)]
702 pub struct S;
703 
704 #[doc(hidden)]
705 pub mod m {}
706             "#,
707             expect![[r#""#]],
708         )
709     }
710 }
711