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