1 //! Completion of paths, i.e. `some::prefix::$0`.
5 use hir::HasVisibility;
6 use rustc_hash::FxHashSet;
7 use syntax::{ast, AstNode};
10 context::PathCompletionContext, patterns::ImmediateLocation, CompletionContext, Completions,
13 pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
14 if ctx.is_path_disallowed() || ctx.has_impl_or_trait_prev_sibling() {
17 let (path, use_tree_parent) = match &ctx.path_context {
18 Some(PathCompletionContext { qualifier: Some(qualifier), use_tree_parent, .. }) => {
19 (qualifier, *use_tree_parent)
24 let resolution = match ctx.sema.resolve_path(path) {
29 let context_module = ctx.scope.module();
31 if let Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) =
32 ctx.completion_location
34 if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
35 for (name, def) in module.scope(ctx.db, context_module) {
36 if let hir::ScopeDef::MacroDef(macro_def) = def {
37 if macro_def.is_fn_like() {
38 acc.add_macro(ctx, Some(name.clone()), macro_def);
41 if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = def {
42 acc.add_resolution(ctx, name, &def);
49 if ctx.in_use_tree() {
50 if iter::successors(Some(path.clone()), |p| p.qualifier())
51 .all(|p| p.segment().and_then(|s| s.super_token()).is_some())
53 acc.add_keyword(ctx, "super::");
55 // only show `self` in a new use-tree when the qualifier doesn't end in self
58 path.segment().and_then(|it| it.kind()),
59 Some(ast::PathSegmentKind::SelfKw)
62 acc.add_keyword(ctx, "self");
66 // Add associated types on type parameters and `Self`.
67 resolution.assoc_type_shorthand_candidates(ctx.db, |_, alias| {
68 acc.add_type_alias(ctx, alias);
73 hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
74 let module_scope = module.scope(ctx.db, context_module);
75 for (name, def) in module_scope {
76 if ctx.in_use_tree() {
77 if let hir::ScopeDef::Unknown = def {
78 if let Some(name_ref) = ctx.name_ref_syntax.as_ref() {
79 if name_ref.syntax().text() == name.to_string().as_str() {
80 // for `use self::foo$0`, don't suggest `foo` as a completion
81 cov_mark::hit!(dont_complete_current_use);
88 let add_resolution = match def {
89 // Don't suggest attribute macros and derives.
90 hir::ScopeDef::MacroDef(mac) => mac.is_fn_like(),
91 // no values in type places
92 hir::ScopeDef::ModuleDef(
93 hir::ModuleDef::Function(_)
94 | hir::ModuleDef::Variant(_)
95 | hir::ModuleDef::Static(_),
97 | hir::ScopeDef::Local(_) => !ctx.expects_type(),
98 // unless its a constant in a generic arg list position
99 hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(_)) => {
100 !ctx.expects_type() || ctx.expects_generic_arg()
106 acc.add_resolution(ctx, name, &def);
110 hir::PathResolution::Def(
113 (hir::ModuleDef::Adt(_)
114 | hir::ModuleDef::TypeAlias(_)
115 | hir::ModuleDef::BuiltinType(_)),
117 if let hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def {
118 add_enum_variants(acc, ctx, e);
121 hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
122 hir::ModuleDef::TypeAlias(a) => {
123 let ty = a.ty(ctx.db);
124 if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
125 cov_mark::hit!(completes_variant_through_alias);
126 add_enum_variants(acc, ctx, e);
130 hir::ModuleDef::BuiltinType(builtin) => {
131 let module = match ctx.scope.module() {
135 cov_mark::hit!(completes_primitive_assoc_const);
136 builtin.ty(ctx.db, module)
141 // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
142 // (where AssocType is defined on a trait, not an inherent impl)
144 let krate = ctx.krate;
145 if let Some(krate) = krate {
146 let traits_in_scope = ctx.scope.traits_in_scope();
147 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
148 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
151 add_assoc_item(acc, ctx, item);
155 // Iterate assoc types separately
156 ty.iterate_assoc_items(ctx.db, krate, |item| {
157 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
160 if let hir::AssocItem::TypeAlias(ty) = item {
161 acc.add_type_alias(ctx, ty)
167 hir::PathResolution::Def(hir::ModuleDef::Trait(t)) => {
168 // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
169 for item in t.items(ctx.db) {
170 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
173 add_assoc_item(acc, ctx, item);
176 hir::PathResolution::TypeParam(_) | hir::PathResolution::SelfType(_) => {
177 if let Some(krate) = ctx.krate {
178 let ty = match resolution {
179 hir::PathResolution::TypeParam(param) => param.ty(ctx.db),
180 hir::PathResolution::SelfType(impl_def) => impl_def.self_ty(ctx.db),
184 if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
185 add_enum_variants(acc, ctx, e);
188 let traits_in_scope = ctx.scope.traits_in_scope();
189 let mut seen = FxHashSet::default();
190 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
191 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
195 // We might iterate candidates of a trait multiple times here, so deduplicate
197 if seen.insert(item) {
198 add_assoc_item(acc, ctx, item);
208 fn add_assoc_item(acc: &mut Completions, ctx: &CompletionContext, item: hir::AssocItem) {
210 hir::AssocItem::Function(func) if !ctx.expects_type() => acc.add_function(ctx, func, None),
211 hir::AssocItem::Const(ct) if !ctx.expects_type() || ctx.expects_generic_arg() => {
212 acc.add_const(ctx, ct)
214 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
219 fn add_enum_variants(acc: &mut Completions, ctx: &CompletionContext, e: hir::Enum) {
220 if ctx.expects_type() {
223 e.variants(ctx.db).into_iter().for_each(|variant| acc.add_enum_variant(ctx, variant, None));
228 use expect_test::{expect, Expect};
231 tests::{check_edit, filtered_completion_list},
235 fn check(ra_fixture: &str, expect: Expect) {
236 let actual = filtered_completion_list(ra_fixture, CompletionKind::Reference);
237 expect.assert_eq(&actual);
240 fn check_builtin(ra_fixture: &str, expect: Expect) {
241 let actual = filtered_completion_list(ra_fixture, CompletionKind::BuiltinType);
242 expect.assert_eq(&actual);
246 fn dont_complete_primitive_in_use() {
247 check_builtin(r#"use self::$0;"#, expect![[""]]);
251 fn dont_complete_primitive_in_module_scope() {
252 check_builtin(r#"fn foo() { self::$0 }"#, expect![[""]]);
256 fn completes_enum_variant() {
259 enum E { Foo, Bar(i32) }
260 fn foo() { let _ = E::$0 }
270 fn completes_struct_associated_items() {
283 fn foo() { let _ = S::$0 }
288 ct C const C: i32 = 42;
295 fn associated_item_visibility() {
302 pub(crate) fn public_method() { }
303 fn private_method() { }
304 pub(crate) type PublicType = u32;
305 type PrivateType = u32;
306 pub(crate) const PUBLIC_CONST: u32 = 1;
307 const PRIVATE_CONST: u32 = 1;
311 fn foo() { let _ = S::$0 }
314 fn public_method() fn()
315 ct PUBLIC_CONST pub(crate) const PUBLIC_CONST: u32 = 1;
316 ta PublicType pub(crate) type PublicType = u32;
322 fn completes_enum_associated_method() {
326 impl E { fn m() { } }
328 fn foo() { let _ = E::$0 }
337 fn completes_union_associated_method() {
341 impl U { fn m() { } }
343 fn foo() { let _ = U::$0 }
352 fn completes_trait_associated_method_1() {
355 trait Trait { fn m(); }
357 fn foo() { let _ = Trait::$0 }
360 fn m() (as Trait) fn()
366 fn completes_trait_associated_method_2() {
369 trait Trait { fn m(); }
374 fn foo() { let _ = S::$0 }
377 fn m() (as Trait) fn()
383 fn completes_trait_associated_method_3() {
386 trait Trait { fn m(); }
391 fn foo() { let _ = <S as Trait>::$0 }
394 fn m() (as Trait) fn()
400 fn completes_ty_param_assoc_ty() {
414 fn submethod(&self) {}
417 fn foo<T: Sub>() { T::$0 }
420 ta SubTy (as Sub) type SubTy;
421 ta Ty (as Super) type Ty;
422 ct C2 (as Sub) const C2: ();
423 fn subfunc() (as Sub) fn()
424 me submethod(…) (as Sub) fn(&self)
425 ct CONST (as Super) const CONST: u8;
426 fn func() (as Super) fn()
427 me method(…) (as Super) fn(&self)
433 fn completes_self_param_assoc_ty() {
447 fn submethod(&self) {}
451 impl<T> Super for Wrap<T> {}
452 impl<T> Sub for Wrap<T> {
454 // Should be able to assume `Self: Sub + Super`
460 ta SubTy (as Sub) type SubTy;
461 ta Ty (as Super) type Ty;
462 ct CONST (as Super) const CONST: u8 = 0;
463 fn func() (as Super) fn()
464 me method(…) (as Super) fn(&self)
465 ct C2 (as Sub) const C2: () = ();
466 fn subfunc() (as Sub) fn()
467 me submethod(…) (as Sub) fn(&self)
473 fn completes_type_alias() {
477 impl S { fn foo() {} }
479 impl T { fn bar() {} }
491 fn completes_qualified_macros() {
495 macro_rules! foo { () => {} }
497 fn main() { let _ = crate::$0 }
501 ma foo!(…) #[macro_export] macro_rules! foo
507 fn does_not_complete_non_fn_macros() {
511 #[rustc_builtin_macro]
522 #[rustc_builtin_macro]
533 fn completes_reexported_items_under_correct_name() {
536 fn foo() { self::m::$0 }
539 pub use super::p::wrong_fn as right_fn;
540 pub use super::p::WRONG_CONST as RIGHT_CONST;
541 pub use super::p::WrongType as RightType;
545 const WRONG_CONST: u32 = 1;
559 fn foo() { self::m::$0 }
562 pub use super::p::wrong_fn as right_fn;
563 pub use super::p::WRONG_CONST as RIGHT_CONST;
564 pub use super::p::WrongType as RightType;
568 const WRONG_CONST: u32 = 1;
573 fn foo() { self::m::RightType }
576 pub use super::p::wrong_fn as right_fn;
577 pub use super::p::WRONG_CONST as RIGHT_CONST;
578 pub use super::p::WrongType as RightType;
582 const WRONG_CONST: u32 = 1;
590 fn completes_in_simple_macro_call() {
593 macro_rules! m { ($e:expr) => { $e } }
594 fn main() { m!(self::f$0); }
605 fn function_mod_share_name() {
608 fn foo() { self::m::$0 }
623 fn completes_hashmap_new() {
627 struct HashMap<K, V, S = RandomState> {}
629 impl<K, V> HashMap<K, V, RandomState> {
630 pub fn new() -> HashMap<K, V, RandomState> { }
637 fn new() fn() -> HashMap<K, V, RandomState>
643 fn dont_complete_attr() {
646 mod foo { pub struct Foo; }
655 fn completes_variant_through_self() {
678 fn completes_primitive_assoc_const() {
679 cov_mark::check!(completes_primitive_assoc_const);
682 //- /lib.rs crate:lib deps:core
687 //- /core.rs crate:core
690 pub const MAX: Self = 255;
696 ct MAX pub const MAX: Self = 255;
703 fn completes_variant_through_alias() {
704 cov_mark::check!(completes_variant_through_alias);