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