]> git.lizzy.rs Git - rust.git/blob - crates/ide_completion/src/completions/qualified_path.rs
Merge #9683
[rust.git] / crates / ide_completion / src / completions / qualified_path.rs
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
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(name_ref) = ctx.name_ref_syntax.as_ref() {
96                             if name_ref.syntax().text() == name.to_string().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                 // FIXME: respect #[doc(hidden)] (see `CompletionContext::is_visible`)
123                 if add_resolution {
124                     acc.add_resolution(ctx, name, &def);
125                 }
126             }
127         }
128         hir::PathResolution::Def(
129             def
130             @
131             (hir::ModuleDef::Adt(_)
132             | hir::ModuleDef::TypeAlias(_)
133             | hir::ModuleDef::BuiltinType(_)),
134         ) => {
135             if let hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def {
136                 add_enum_variants(acc, ctx, e);
137             }
138             let ty = match def {
139                 hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
140                 hir::ModuleDef::TypeAlias(a) => {
141                     let ty = a.ty(ctx.db);
142                     if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
143                         cov_mark::hit!(completes_variant_through_alias);
144                         add_enum_variants(acc, ctx, e);
145                     }
146                     ty
147                 }
148                 hir::ModuleDef::BuiltinType(builtin) => {
149                     let module = match ctx.scope.module() {
150                         Some(it) => it,
151                         None => return,
152                     };
153                     cov_mark::hit!(completes_primitive_assoc_const);
154                     builtin.ty(ctx.db, module)
155                 }
156                 _ => unreachable!(),
157             };
158
159             // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
160             // (where AssocType is defined on a trait, not an inherent impl)
161
162             let krate = ctx.krate;
163             if let Some(krate) = krate {
164                 let traits_in_scope = ctx.scope.traits_in_scope();
165                 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
166                     if !ctx.is_visible(&item) {
167                         return None;
168                     }
169                     add_assoc_item(acc, ctx, item);
170                     None::<()>
171                 });
172
173                 // Iterate assoc types separately
174                 ty.iterate_assoc_items(ctx.db, krate, |item| {
175                     if !ctx.is_visible(&item) {
176                         return None;
177                     }
178                     if let hir::AssocItem::TypeAlias(ty) = item {
179                         acc.add_type_alias(ctx, ty)
180                     }
181                     None::<()>
182                 });
183             }
184         }
185         hir::PathResolution::Def(hir::ModuleDef::Trait(t)) => {
186             // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
187             for item in t.items(ctx.db) {
188                 if !ctx.is_visible(&item) {
189                     continue;
190                 }
191                 add_assoc_item(acc, ctx, item);
192             }
193         }
194         hir::PathResolution::TypeParam(_) | hir::PathResolution::SelfType(_) => {
195             if let Some(krate) = ctx.krate {
196                 let ty = match resolution {
197                     hir::PathResolution::TypeParam(param) => param.ty(ctx.db),
198                     hir::PathResolution::SelfType(impl_def) => impl_def.self_ty(ctx.db),
199                     _ => return,
200                 };
201
202                 if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
203                     add_enum_variants(acc, ctx, e);
204                 }
205
206                 let traits_in_scope = ctx.scope.traits_in_scope();
207                 let mut seen = FxHashSet::default();
208                 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
209                     if !ctx.is_visible(&item) {
210                         return None;
211                     }
212
213                     // We might iterate candidates of a trait multiple times here, so deduplicate
214                     // them.
215                     if seen.insert(item) {
216                         add_assoc_item(acc, ctx, item);
217                     }
218                     None::<()>
219                 });
220             }
221         }
222         _ => {}
223     }
224 }
225
226 fn add_assoc_item(acc: &mut Completions, ctx: &CompletionContext, item: hir::AssocItem) {
227     match item {
228         hir::AssocItem::Function(func) if !ctx.expects_type() => acc.add_function(ctx, func, None),
229         hir::AssocItem::Const(ct) if !ctx.expects_type() || ctx.expects_generic_arg() => {
230             acc.add_const(ctx, ct)
231         }
232         hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
233         _ => (),
234     }
235 }
236
237 fn add_enum_variants(acc: &mut Completions, ctx: &CompletionContext, e: hir::Enum) {
238     if ctx.expects_type() {
239         return;
240     }
241     e.variants(ctx.db).into_iter().for_each(|variant| acc.add_enum_variant(ctx, variant, None));
242 }
243
244 #[cfg(test)]
245 mod tests {
246     use expect_test::{expect, Expect};
247
248     use crate::{
249         tests::{check_edit, filtered_completion_list},
250         CompletionKind,
251     };
252
253     fn check(ra_fixture: &str, expect: Expect) {
254         let actual = filtered_completion_list(ra_fixture, CompletionKind::Reference);
255         expect.assert_eq(&actual);
256     }
257
258     #[test]
259     fn associated_item_visibility() {
260         check(
261             r#"
262 struct S;
263
264 mod m {
265     impl super::S {
266         pub(crate) fn public_method() { }
267         fn private_method() { }
268         pub(crate) type PublicType = u32;
269         type PrivateType = u32;
270         pub(crate) const PUBLIC_CONST: u32 = 1;
271         const PRIVATE_CONST: u32 = 1;
272     }
273 }
274
275 fn foo() { let _ = S::$0 }
276 "#,
277             expect![[r#"
278                 fn public_method() fn()
279                 ct PUBLIC_CONST    pub(crate) const PUBLIC_CONST: u32 = 1;
280                 ta PublicType      pub(crate) type PublicType = u32;
281             "#]],
282         );
283     }
284
285     #[test]
286     fn completes_union_associated_method() {
287         check(
288             r#"
289 union U {};
290 impl U { fn m() { } }
291
292 fn foo() { let _ = U::$0 }
293 "#,
294             expect![[r#"
295                 fn m() fn()
296             "#]],
297         );
298     }
299
300     #[test]
301     fn completes_trait_associated_method_1() {
302         check(
303             r#"
304 trait Trait { fn m(); }
305
306 fn foo() { let _ = Trait::$0 }
307 "#,
308             expect![[r#"
309                 fn m() (as Trait) fn()
310             "#]],
311         );
312     }
313
314     #[test]
315     fn completes_trait_associated_method_2() {
316         check(
317             r#"
318 trait Trait { fn m(); }
319
320 struct S;
321 impl Trait for S {}
322
323 fn foo() { let _ = S::$0 }
324 "#,
325             expect![[r#"
326                 fn m() (as Trait) fn()
327             "#]],
328         );
329     }
330
331     #[test]
332     fn completes_trait_associated_method_3() {
333         check(
334             r#"
335 trait Trait { fn m(); }
336
337 struct S;
338 impl Trait for S {}
339
340 fn foo() { let _ = <S as Trait>::$0 }
341 "#,
342             expect![[r#"
343                 fn m() (as Trait) fn()
344             "#]],
345         );
346     }
347
348     #[test]
349     fn completes_ty_param_assoc_ty() {
350         check(
351             r#"
352 trait Super {
353     type Ty;
354     const CONST: u8;
355     fn func() {}
356     fn method(&self) {}
357 }
358
359 trait Sub: Super {
360     type SubTy;
361     const C2: ();
362     fn subfunc() {}
363     fn submethod(&self) {}
364 }
365
366 fn foo<T: Sub>() { T::$0 }
367 "#,
368             expect![[r#"
369                 ta SubTy (as Sub)        type SubTy;
370                 ta Ty (as Super)         type Ty;
371                 ct C2 (as Sub)           const C2: ();
372                 fn subfunc() (as Sub)    fn()
373                 me submethod(…) (as Sub) fn(&self)
374                 ct CONST (as Super)      const CONST: u8;
375                 fn func() (as Super)     fn()
376                 me method(…) (as Super)  fn(&self)
377             "#]],
378         );
379     }
380
381     #[test]
382     fn completes_self_param_assoc_ty() {
383         check(
384             r#"
385 trait Super {
386     type Ty;
387     const CONST: u8 = 0;
388     fn func() {}
389     fn method(&self) {}
390 }
391
392 trait Sub: Super {
393     type SubTy;
394     const C2: () = ();
395     fn subfunc() {}
396     fn submethod(&self) {}
397 }
398
399 struct Wrap<T>(T);
400 impl<T> Super for Wrap<T> {}
401 impl<T> Sub for Wrap<T> {
402     fn subfunc() {
403         // Should be able to assume `Self: Sub + Super`
404         Self::$0
405     }
406 }
407 "#,
408             expect![[r#"
409                 ta SubTy (as Sub)        type SubTy;
410                 ta Ty (as Super)         type Ty;
411                 ct CONST (as Super)      const CONST: u8 = 0;
412                 fn func() (as Super)     fn()
413                 me method(…) (as Super)  fn(&self)
414                 ct C2 (as Sub)           const C2: () = ();
415                 fn subfunc() (as Sub)    fn()
416                 me submethod(…) (as Sub) fn(&self)
417             "#]],
418         );
419     }
420
421     #[test]
422     fn completes_type_alias() {
423         check(
424             r#"
425 struct S;
426 impl S { fn foo() {} }
427 type T = S;
428 impl T { fn bar() {} }
429
430 fn main() { T::$0; }
431 "#,
432             expect![[r#"
433                 fn foo() fn()
434                 fn bar() fn()
435             "#]],
436         );
437     }
438
439     #[test]
440     fn completes_qualified_macros() {
441         check(
442             r#"
443 #[macro_export]
444 macro_rules! foo { () => {} }
445
446 fn main() { let _ = crate::$0 }
447 "#,
448             expect![[r##"
449                 fn main()  fn()
450                 ma foo!(…) #[macro_export] macro_rules! foo
451             "##]],
452         );
453     }
454
455     #[test]
456     fn does_not_complete_non_fn_macros() {
457         check(
458             r#"
459 mod m {
460     #[rustc_builtin_macro]
461     pub macro Clone {}
462 }
463
464 fn f() {m::$0}
465 "#,
466             expect![[r#""#]],
467         );
468         check(
469             r#"
470 mod m {
471     #[rustc_builtin_macro]
472     pub macro bench {}
473 }
474
475 fn f() {m::$0}
476 "#,
477             expect![[r#""#]],
478         );
479     }
480
481     #[test]
482     fn completes_reexported_items_under_correct_name() {
483         check(
484             r#"
485 fn foo() { self::m::$0 }
486
487 mod m {
488     pub use super::p::wrong_fn as right_fn;
489     pub use super::p::WRONG_CONST as RIGHT_CONST;
490     pub use super::p::WrongType as RightType;
491 }
492 mod p {
493     fn wrong_fn() {}
494     const WRONG_CONST: u32 = 1;
495     struct WrongType {};
496 }
497 "#,
498             expect![[r#"
499                 ct RIGHT_CONST
500                 fn right_fn()  fn()
501                 st RightType
502             "#]],
503         );
504
505         check_edit(
506             "RightType",
507             r#"
508 fn foo() { self::m::$0 }
509
510 mod m {
511     pub use super::p::wrong_fn as right_fn;
512     pub use super::p::WRONG_CONST as RIGHT_CONST;
513     pub use super::p::WrongType as RightType;
514 }
515 mod p {
516     fn wrong_fn() {}
517     const WRONG_CONST: u32 = 1;
518     struct WrongType {};
519 }
520 "#,
521             r#"
522 fn foo() { self::m::RightType }
523
524 mod m {
525     pub use super::p::wrong_fn as right_fn;
526     pub use super::p::WRONG_CONST as RIGHT_CONST;
527     pub use super::p::WrongType as RightType;
528 }
529 mod p {
530     fn wrong_fn() {}
531     const WRONG_CONST: u32 = 1;
532     struct WrongType {};
533 }
534 "#,
535         );
536     }
537
538     #[test]
539     fn completes_in_simple_macro_call() {
540         check(
541             r#"
542 macro_rules! m { ($e:expr) => { $e } }
543 fn main() { m!(self::f$0); }
544 fn foo() {}
545 "#,
546             expect![[r#"
547                 fn main() fn()
548                 fn foo()  fn()
549             "#]],
550         );
551     }
552
553     #[test]
554     fn function_mod_share_name() {
555         check(
556             r#"
557 fn foo() { self::m::$0 }
558
559 mod m {
560     pub mod z {}
561     pub fn z() {}
562 }
563 "#,
564             expect![[r#"
565                 md z
566                 fn z() fn()
567             "#]],
568         );
569     }
570
571     #[test]
572     fn completes_hashmap_new() {
573         check(
574             r#"
575 struct RandomState;
576 struct HashMap<K, V, S = RandomState> {}
577
578 impl<K, V> HashMap<K, V, RandomState> {
579     pub fn new() -> HashMap<K, V, RandomState> { }
580 }
581 fn foo() {
582     HashMap::$0
583 }
584 "#,
585             expect![[r#"
586                 fn new() fn() -> HashMap<K, V, RandomState>
587             "#]],
588         );
589     }
590
591     #[test]
592     fn dont_complete_attr() {
593         check(
594             r#"
595 mod foo { pub struct Foo; }
596 #[foo::$0]
597 fn f() {}
598 "#,
599             expect![[""]],
600         );
601     }
602
603     #[test]
604     fn completes_variant_through_self() {
605         check(
606             r#"
607 enum Foo {
608     Bar,
609     Baz,
610 }
611
612 impl Foo {
613     fn foo(self) {
614         Self::$0
615     }
616 }
617 "#,
618             expect![[r#"
619                 ev Bar    ()
620                 ev Baz    ()
621                 me foo(…) fn(self)
622             "#]],
623         );
624     }
625
626     #[test]
627     fn completes_primitive_assoc_const() {
628         cov_mark::check!(completes_primitive_assoc_const);
629         check(
630             r#"
631 //- /lib.rs crate:lib deps:core
632 fn f() {
633     u8::$0
634 }
635
636 //- /core.rs crate:core
637 #[lang = "u8"]
638 impl u8 {
639     pub const MAX: Self = 255;
640
641     pub fn func(self) {}
642 }
643 "#,
644             expect![[r#"
645                 ct MAX     pub const MAX: Self = 255;
646                 me func(…) fn(self)
647             "#]],
648         );
649     }
650
651     #[test]
652     fn completes_variant_through_alias() {
653         cov_mark::check!(completes_variant_through_alias);
654         check(
655             r#"
656 enum Foo {
657     Bar
658 }
659 type Foo2 = Foo;
660 fn main() {
661     Foo2::$0
662 }
663 "#,
664             expect![[r#"
665                 ev Bar ()
666             "#]],
667         );
668     }
669 }