]> git.lizzy.rs Git - rust.git/blob - crates/ide_completion/src/completions/qualified_path.rs
Merge #9664
[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::HasVisibility;
6 use rustc_hash::FxHashSet;
7 use syntax::{ast, AstNode};
8
9 use crate::{
10     context::PathCompletionContext, patterns::ImmediateLocation, CompletionContext, Completions,
11 };
12
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() {
15         return;
16     }
17     let (path, use_tree_parent) = match &ctx.path_context {
18         Some(PathCompletionContext { qualifier: Some(qualifier), use_tree_parent, .. }) => {
19             (qualifier, *use_tree_parent)
20         }
21         _ => return,
22     };
23
24     let resolution = match ctx.sema.resolve_path(path) {
25         Some(res) => res,
26         None => return,
27     };
28
29     let context_module = ctx.scope.module();
30
31     if let Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) =
32         ctx.completion_location
33     {
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);
39                     }
40                 }
41                 if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = def {
42                     acc.add_resolution(ctx, name, &def);
43                 }
44             }
45         }
46         return;
47     }
48
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())
52         {
53             acc.add_keyword(ctx, "super::");
54         }
55         // only show `self` in a new use-tree when the qualifier doesn't end in self
56         if use_tree_parent
57             && !matches!(
58                 path.segment().and_then(|it| it.kind()),
59                 Some(ast::PathSegmentKind::SelfKw)
60             )
61         {
62             acc.add_keyword(ctx, "self");
63         }
64     }
65
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);
69         None::<()>
70     });
71
72     match resolution {
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);
82                                 continue;
83                             }
84                         }
85                     }
86                 }
87
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(_),
96                     )
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()
101                     }
102                     _ => true,
103                 };
104
105                 if add_resolution {
106                     acc.add_resolution(ctx, name, &def);
107                 }
108             }
109         }
110         hir::PathResolution::Def(
111             def
112             @
113             (hir::ModuleDef::Adt(_)
114             | hir::ModuleDef::TypeAlias(_)
115             | hir::ModuleDef::BuiltinType(_)),
116         ) => {
117             if let hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def {
118                 add_enum_variants(acc, ctx, e);
119             }
120             let ty = match def {
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);
127                     }
128                     ty
129                 }
130                 hir::ModuleDef::BuiltinType(builtin) => {
131                     let module = match ctx.scope.module() {
132                         Some(it) => it,
133                         None => return,
134                     };
135                     cov_mark::hit!(completes_primitive_assoc_const);
136                     builtin.ty(ctx.db, module)
137                 }
138                 _ => unreachable!(),
139             };
140
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)
143
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)) {
149                         return None;
150                     }
151                     add_assoc_item(acc, ctx, item);
152                     None::<()>
153                 });
154
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)) {
158                         return None;
159                     }
160                     if let hir::AssocItem::TypeAlias(ty) = item {
161                         acc.add_type_alias(ctx, ty)
162                     }
163                     None::<()>
164                 });
165             }
166         }
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)) {
171                     continue;
172                 }
173                 add_assoc_item(acc, ctx, item);
174             }
175         }
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),
181                     _ => return,
182                 };
183
184                 if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
185                     add_enum_variants(acc, ctx, e);
186                 }
187
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)) {
192                         return None;
193                     }
194
195                     // We might iterate candidates of a trait multiple times here, so deduplicate
196                     // them.
197                     if seen.insert(item) {
198                         add_assoc_item(acc, ctx, item);
199                     }
200                     None::<()>
201                 });
202             }
203         }
204         _ => {}
205     }
206 }
207
208 fn add_assoc_item(acc: &mut Completions, ctx: &CompletionContext, item: hir::AssocItem) {
209     match item {
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)
213         }
214         hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
215         _ => (),
216     }
217 }
218
219 fn add_enum_variants(acc: &mut Completions, ctx: &CompletionContext, e: hir::Enum) {
220     if ctx.expects_type() {
221         return;
222     }
223     e.variants(ctx.db).into_iter().for_each(|variant| acc.add_enum_variant(ctx, variant, None));
224 }
225
226 #[cfg(test)]
227 mod tests {
228     use expect_test::{expect, Expect};
229
230     use crate::{
231         tests::{check_edit, filtered_completion_list},
232         CompletionKind,
233     };
234
235     fn check(ra_fixture: &str, expect: Expect) {
236         let actual = filtered_completion_list(ra_fixture, CompletionKind::Reference);
237         expect.assert_eq(&actual);
238     }
239
240     fn check_builtin(ra_fixture: &str, expect: Expect) {
241         let actual = filtered_completion_list(ra_fixture, CompletionKind::BuiltinType);
242         expect.assert_eq(&actual);
243     }
244
245     #[test]
246     fn dont_complete_primitive_in_use() {
247         check_builtin(r#"use self::$0;"#, expect![[""]]);
248     }
249
250     #[test]
251     fn dont_complete_primitive_in_module_scope() {
252         check_builtin(r#"fn foo() { self::$0 }"#, expect![[""]]);
253     }
254
255     #[test]
256     fn completes_enum_variant() {
257         check(
258             r#"
259 enum E { Foo, Bar(i32) }
260 fn foo() { let _ = E::$0 }
261 "#,
262             expect![[r#"
263                 ev Foo    ()
264                 ev Bar(…) (i32)
265             "#]],
266         );
267     }
268
269     #[test]
270     fn completes_struct_associated_items() {
271         check(
272             r#"
273 //- /lib.rs
274 struct S;
275
276 impl S {
277     fn a() {}
278     fn b(&self) {}
279     const C: i32 = 42;
280     type T = i32;
281 }
282
283 fn foo() { let _ = S::$0 }
284 "#,
285             expect![[r#"
286                 fn a()  fn()
287                 me b(…) fn(&self)
288                 ct C    const C: i32 = 42;
289                 ta T    type T = i32;
290             "#]],
291         );
292     }
293
294     #[test]
295     fn associated_item_visibility() {
296         check(
297             r#"
298 struct S;
299
300 mod m {
301     impl super::S {
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;
308     }
309 }
310
311 fn foo() { let _ = S::$0 }
312 "#,
313             expect![[r#"
314                 fn public_method() fn()
315                 ct PUBLIC_CONST    pub(crate) const PUBLIC_CONST: u32 = 1;
316                 ta PublicType      pub(crate) type PublicType = u32;
317             "#]],
318         );
319     }
320
321     #[test]
322     fn completes_enum_associated_method() {
323         check(
324             r#"
325 enum E {};
326 impl E { fn m() { } }
327
328 fn foo() { let _ = E::$0 }
329         "#,
330             expect![[r#"
331                 fn m() fn()
332             "#]],
333         );
334     }
335
336     #[test]
337     fn completes_union_associated_method() {
338         check(
339             r#"
340 union U {};
341 impl U { fn m() { } }
342
343 fn foo() { let _ = U::$0 }
344 "#,
345             expect![[r#"
346                 fn m() fn()
347             "#]],
348         );
349     }
350
351     #[test]
352     fn completes_trait_associated_method_1() {
353         check(
354             r#"
355 trait Trait { fn m(); }
356
357 fn foo() { let _ = Trait::$0 }
358 "#,
359             expect![[r#"
360                 fn m() (as Trait) fn()
361             "#]],
362         );
363     }
364
365     #[test]
366     fn completes_trait_associated_method_2() {
367         check(
368             r#"
369 trait Trait { fn m(); }
370
371 struct S;
372 impl Trait for S {}
373
374 fn foo() { let _ = S::$0 }
375 "#,
376             expect![[r#"
377                 fn m() (as Trait) fn()
378             "#]],
379         );
380     }
381
382     #[test]
383     fn completes_trait_associated_method_3() {
384         check(
385             r#"
386 trait Trait { fn m(); }
387
388 struct S;
389 impl Trait for S {}
390
391 fn foo() { let _ = <S as Trait>::$0 }
392 "#,
393             expect![[r#"
394                 fn m() (as Trait) fn()
395             "#]],
396         );
397     }
398
399     #[test]
400     fn completes_ty_param_assoc_ty() {
401         check(
402             r#"
403 trait Super {
404     type Ty;
405     const CONST: u8;
406     fn func() {}
407     fn method(&self) {}
408 }
409
410 trait Sub: Super {
411     type SubTy;
412     const C2: ();
413     fn subfunc() {}
414     fn submethod(&self) {}
415 }
416
417 fn foo<T: Sub>() { T::$0 }
418 "#,
419             expect![[r#"
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)
428             "#]],
429         );
430     }
431
432     #[test]
433     fn completes_self_param_assoc_ty() {
434         check(
435             r#"
436 trait Super {
437     type Ty;
438     const CONST: u8 = 0;
439     fn func() {}
440     fn method(&self) {}
441 }
442
443 trait Sub: Super {
444     type SubTy;
445     const C2: () = ();
446     fn subfunc() {}
447     fn submethod(&self) {}
448 }
449
450 struct Wrap<T>(T);
451 impl<T> Super for Wrap<T> {}
452 impl<T> Sub for Wrap<T> {
453     fn subfunc() {
454         // Should be able to assume `Self: Sub + Super`
455         Self::$0
456     }
457 }
458 "#,
459             expect![[r#"
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)
468             "#]],
469         );
470     }
471
472     #[test]
473     fn completes_type_alias() {
474         check(
475             r#"
476 struct S;
477 impl S { fn foo() {} }
478 type T = S;
479 impl T { fn bar() {} }
480
481 fn main() { T::$0; }
482 "#,
483             expect![[r#"
484                 fn foo() fn()
485                 fn bar() fn()
486             "#]],
487         );
488     }
489
490     #[test]
491     fn completes_qualified_macros() {
492         check(
493             r#"
494 #[macro_export]
495 macro_rules! foo { () => {} }
496
497 fn main() { let _ = crate::$0 }
498 "#,
499             expect![[r##"
500                 fn main()  fn()
501                 ma foo!(…) #[macro_export] macro_rules! foo
502             "##]],
503         );
504     }
505
506     #[test]
507     fn does_not_complete_non_fn_macros() {
508         check(
509             r#"
510 mod m {
511     #[rustc_builtin_macro]
512     pub macro Clone {}
513 }
514
515 fn f() {m::$0}
516 "#,
517             expect![[r#""#]],
518         );
519         check(
520             r#"
521 mod m {
522     #[rustc_builtin_macro]
523     pub macro bench {}
524 }
525
526 fn f() {m::$0}
527 "#,
528             expect![[r#""#]],
529         );
530     }
531
532     #[test]
533     fn completes_reexported_items_under_correct_name() {
534         check(
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             expect![[r#"
550                 ct RIGHT_CONST
551                 fn right_fn()  fn()
552                 st RightType
553             "#]],
554         );
555
556         check_edit(
557             "RightType",
558             r#"
559 fn foo() { self::m::$0 }
560
561 mod m {
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;
565 }
566 mod p {
567     fn wrong_fn() {}
568     const WRONG_CONST: u32 = 1;
569     struct WrongType {};
570 }
571 "#,
572             r#"
573 fn foo() { self::m::RightType }
574
575 mod m {
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;
579 }
580 mod p {
581     fn wrong_fn() {}
582     const WRONG_CONST: u32 = 1;
583     struct WrongType {};
584 }
585 "#,
586         );
587     }
588
589     #[test]
590     fn completes_in_simple_macro_call() {
591         check(
592             r#"
593 macro_rules! m { ($e:expr) => { $e } }
594 fn main() { m!(self::f$0); }
595 fn foo() {}
596 "#,
597             expect![[r#"
598                 fn main() fn()
599                 fn foo()  fn()
600             "#]],
601         );
602     }
603
604     #[test]
605     fn function_mod_share_name() {
606         check(
607             r#"
608 fn foo() { self::m::$0 }
609
610 mod m {
611     pub mod z {}
612     pub fn z() {}
613 }
614 "#,
615             expect![[r#"
616                 md z
617                 fn z() fn()
618             "#]],
619         );
620     }
621
622     #[test]
623     fn completes_hashmap_new() {
624         check(
625             r#"
626 struct RandomState;
627 struct HashMap<K, V, S = RandomState> {}
628
629 impl<K, V> HashMap<K, V, RandomState> {
630     pub fn new() -> HashMap<K, V, RandomState> { }
631 }
632 fn foo() {
633     HashMap::$0
634 }
635 "#,
636             expect![[r#"
637                 fn new() fn() -> HashMap<K, V, RandomState>
638             "#]],
639         );
640     }
641
642     #[test]
643     fn dont_complete_attr() {
644         check(
645             r#"
646 mod foo { pub struct Foo; }
647 #[foo::$0]
648 fn f() {}
649 "#,
650             expect![[""]],
651         );
652     }
653
654     #[test]
655     fn completes_variant_through_self() {
656         check(
657             r#"
658 enum Foo {
659     Bar,
660     Baz,
661 }
662
663 impl Foo {
664     fn foo(self) {
665         Self::$0
666     }
667 }
668 "#,
669             expect![[r#"
670                 ev Bar    ()
671                 ev Baz    ()
672                 me foo(…) fn(self)
673             "#]],
674         );
675     }
676
677     #[test]
678     fn completes_primitive_assoc_const() {
679         cov_mark::check!(completes_primitive_assoc_const);
680         check(
681             r#"
682 //- /lib.rs crate:lib deps:core
683 fn f() {
684     u8::$0
685 }
686
687 //- /core.rs crate:core
688 #[lang = "u8"]
689 impl u8 {
690     pub const MAX: Self = 255;
691
692     pub fn func(self) {}
693 }
694 "#,
695             expect![[r#"
696                 ct MAX     pub const MAX: Self = 255;
697                 me func(…) fn(self)
698             "#]],
699         );
700     }
701
702     #[test]
703     fn completes_variant_through_alias() {
704         cov_mark::check!(completes_variant_through_alias);
705         check(
706             r#"
707 enum Foo {
708     Bar
709 }
710 type Foo2 = Foo;
711 fn main() {
712     Foo2::$0
713 }
714 "#,
715             expect![[r#"
716                 ev Bar ()
717             "#]],
718         );
719     }
720 }