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