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