aboutsummaryrefslogtreecommitdiff
path: root/crates/completion/src/completions/qualified_path.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/completion/src/completions/qualified_path.rs')
-rw-r--r--crates/completion/src/completions/qualified_path.rs783
1 files changed, 0 insertions, 783 deletions
diff --git a/crates/completion/src/completions/qualified_path.rs b/crates/completion/src/completions/qualified_path.rs
deleted file mode 100644
index 33df26761..000000000
--- a/crates/completion/src/completions/qualified_path.rs
+++ /dev/null
@@ -1,783 +0,0 @@
1//! Completion of paths, i.e. `some::prefix::$0`.
2
3use hir::{Adt, HasVisibility, PathResolution, ScopeDef};
4use rustc_hash::FxHashSet;
5use syntax::AstNode;
6use test_utils::mark;
7
8use crate::{CompletionContext, Completions};
9
10pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
11 let path = match &ctx.path_qual {
12 Some(path) => path.clone(),
13 None => return,
14 };
15
16 if ctx.attribute_under_caret.is_some() || ctx.mod_declaration_under_caret.is_some() {
17 return;
18 }
19
20 let context_module = ctx.scope.module();
21
22 let resolution = match ctx.sema.resolve_path(&path) {
23 Some(res) => res,
24 None => return,
25 };
26
27 // Add associated types on type parameters and `Self`.
28 resolution.assoc_type_shorthand_candidates(ctx.db, |alias| {
29 acc.add_type_alias(ctx, alias);
30 None::<()>
31 });
32
33 match resolution {
34 PathResolution::Def(hir::ModuleDef::Module(module)) => {
35 let module_scope = module.scope(ctx.db, context_module);
36 for (name, def) in module_scope {
37 if ctx.use_item_syntax.is_some() {
38 if let ScopeDef::Unknown = def {
39 if let Some(name_ref) = ctx.name_ref_syntax.as_ref() {
40 if name_ref.syntax().text() == name.to_string().as_str() {
41 // for `use self::foo$0`, don't suggest `foo` as a completion
42 mark::hit!(dont_complete_current_use);
43 continue;
44 }
45 }
46 }
47 }
48
49 acc.add_resolution(ctx, name.to_string(), &def);
50 }
51 }
52 PathResolution::Def(def @ hir::ModuleDef::Adt(_))
53 | PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_)) => {
54 if let hir::ModuleDef::Adt(Adt::Enum(e)) = def {
55 for variant in e.variants(ctx.db) {
56 acc.add_enum_variant(ctx, variant, None);
57 }
58 }
59 let ty = match def {
60 hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
61 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
62 _ => unreachable!(),
63 };
64
65 // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
66 // (where AssocType is defined on a trait, not an inherent impl)
67
68 let krate = ctx.krate;
69 if let Some(krate) = krate {
70 let traits_in_scope = ctx.scope.traits_in_scope();
71 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
72 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
73 return None;
74 }
75 match item {
76 hir::AssocItem::Function(func) => {
77 acc.add_function(ctx, func, None);
78 }
79 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
80 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
81 }
82 None::<()>
83 });
84
85 // Iterate assoc types separately
86 ty.iterate_assoc_items(ctx.db, krate, |item| {
87 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
88 return None;
89 }
90 match item {
91 hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}
92 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
93 }
94 None::<()>
95 });
96 }
97 }
98 PathResolution::Def(hir::ModuleDef::Trait(t)) => {
99 // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
100 for item in t.items(ctx.db) {
101 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
102 continue;
103 }
104 match item {
105 hir::AssocItem::Function(func) => {
106 acc.add_function(ctx, func, None);
107 }
108 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
109 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
110 }
111 }
112 }
113 PathResolution::TypeParam(_) | PathResolution::SelfType(_) => {
114 if let Some(krate) = ctx.krate {
115 let ty = match resolution {
116 PathResolution::TypeParam(param) => param.ty(ctx.db),
117 PathResolution::SelfType(impl_def) => impl_def.target_ty(ctx.db),
118 _ => return,
119 };
120
121 if let Some(Adt::Enum(e)) = ty.as_adt() {
122 for variant in e.variants(ctx.db) {
123 acc.add_enum_variant(ctx, variant, None);
124 }
125 }
126
127 let traits_in_scope = ctx.scope.traits_in_scope();
128 let mut seen = FxHashSet::default();
129 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
130 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
131 return None;
132 }
133
134 // We might iterate candidates of a trait multiple times here, so deduplicate
135 // them.
136 if seen.insert(item) {
137 match item {
138 hir::AssocItem::Function(func) => {
139 acc.add_function(ctx, func, None);
140 }
141 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
142 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
143 }
144 }
145 None::<()>
146 });
147 }
148 }
149 _ => {}
150 }
151}
152
153#[cfg(test)]
154mod tests {
155 use expect_test::{expect, Expect};
156 use test_utils::mark;
157
158 use crate::{
159 test_utils::{check_edit, completion_list},
160 CompletionKind,
161 };
162
163 fn check(ra_fixture: &str, expect: Expect) {
164 let actual = completion_list(ra_fixture, CompletionKind::Reference);
165 expect.assert_eq(&actual);
166 }
167
168 fn check_builtin(ra_fixture: &str, expect: Expect) {
169 let actual = completion_list(ra_fixture, CompletionKind::BuiltinType);
170 expect.assert_eq(&actual);
171 }
172
173 #[test]
174 fn dont_complete_current_use() {
175 mark::check!(dont_complete_current_use);
176 check(r#"use self::foo$0;"#, expect![[""]]);
177 }
178
179 #[test]
180 fn dont_complete_current_use_in_braces_with_glob() {
181 check(
182 r#"
183mod foo { pub struct S; }
184use self::{foo::*, bar$0};
185"#,
186 expect![[r#"
187 st S
188 md foo
189 "#]],
190 );
191 }
192
193 #[test]
194 fn dont_complete_primitive_in_use() {
195 check_builtin(r#"use self::$0;"#, expect![[""]]);
196 }
197
198 #[test]
199 fn dont_complete_primitive_in_module_scope() {
200 check_builtin(r#"fn foo() { self::$0 }"#, expect![[""]]);
201 }
202
203 #[test]
204 fn completes_primitives() {
205 check_builtin(
206 r#"fn main() { let _: $0 = 92; }"#,
207 expect![[r#"
208 bt u32
209 bt bool
210 bt u8
211 bt isize
212 bt u16
213 bt u64
214 bt u128
215 bt f32
216 bt i128
217 bt i16
218 bt str
219 bt i64
220 bt char
221 bt f64
222 bt i32
223 bt i8
224 bt usize
225 "#]],
226 );
227 }
228
229 #[test]
230 fn completes_mod_with_same_name_as_function() {
231 check(
232 r#"
233use self::my::$0;
234
235mod my { pub struct Bar; }
236fn my() {}
237"#,
238 expect![[r#"
239 st Bar
240 "#]],
241 );
242 }
243
244 #[test]
245 fn filters_visibility() {
246 check(
247 r#"
248use self::my::$0;
249
250mod my {
251 struct Bar;
252 pub struct Foo;
253 pub use Bar as PublicBar;
254}
255"#,
256 expect![[r#"
257 st Foo
258 st PublicBar
259 "#]],
260 );
261 }
262
263 #[test]
264 fn completes_use_item_starting_with_self() {
265 check(
266 r#"
267use self::m::$0;
268
269mod m { pub struct Bar; }
270"#,
271 expect![[r#"
272 st Bar
273 "#]],
274 );
275 }
276
277 #[test]
278 fn completes_use_item_starting_with_crate() {
279 check(
280 r#"
281//- /lib.rs
282mod foo;
283struct Spam;
284//- /foo.rs
285use crate::Sp$0
286"#,
287 expect![[r#"
288 md foo
289 st Spam
290 "#]],
291 );
292 }
293
294 #[test]
295 fn completes_nested_use_tree() {
296 check(
297 r#"
298//- /lib.rs
299mod foo;
300struct Spam;
301//- /foo.rs
302use crate::{Sp$0};
303"#,
304 expect![[r#"
305 md foo
306 st Spam
307 "#]],
308 );
309 }
310
311 #[test]
312 fn completes_deeply_nested_use_tree() {
313 check(
314 r#"
315//- /lib.rs
316mod foo;
317pub mod bar {
318 pub mod baz {
319 pub struct Spam;
320 }
321}
322//- /foo.rs
323use crate::{bar::{baz::Sp$0}};
324"#,
325 expect![[r#"
326 st Spam
327 "#]],
328 );
329 }
330
331 #[test]
332 fn completes_enum_variant() {
333 check(
334 r#"
335enum E { Foo, Bar(i32) }
336fn foo() { let _ = E::$0 }
337"#,
338 expect![[r#"
339 ev Foo ()
340 ev Bar(…) (i32)
341 "#]],
342 );
343 }
344
345 #[test]
346 fn completes_struct_associated_items() {
347 check(
348 r#"
349//- /lib.rs
350struct S;
351
352impl S {
353 fn a() {}
354 fn b(&self) {}
355 const C: i32 = 42;
356 type T = i32;
357}
358
359fn foo() { let _ = S::$0 }
360"#,
361 expect![[r#"
362 fn a() fn a()
363 me b(…) fn b(&self)
364 ct C const C: i32 = 42;
365 ta T type T = i32;
366 "#]],
367 );
368 }
369
370 #[test]
371 fn associated_item_visibility() {
372 check(
373 r#"
374struct S;
375
376mod m {
377 impl super::S {
378 pub(crate) fn public_method() { }
379 fn private_method() { }
380 pub(crate) type PublicType = u32;
381 type PrivateType = u32;
382 pub(crate) const PUBLIC_CONST: u32 = 1;
383 const PRIVATE_CONST: u32 = 1;
384 }
385}
386
387fn foo() { let _ = S::$0 }
388"#,
389 expect![[r#"
390 fn public_method() pub(crate) fn public_method()
391 ct PUBLIC_CONST pub(crate) const PUBLIC_CONST: u32 = 1;
392 ta PublicType pub(crate) type PublicType = u32;
393 "#]],
394 );
395 }
396
397 #[test]
398 fn completes_enum_associated_method() {
399 check(
400 r#"
401enum E {};
402impl E { fn m() { } }
403
404fn foo() { let _ = E::$0 }
405 "#,
406 expect![[r#"
407 fn m() fn m()
408 "#]],
409 );
410 }
411
412 #[test]
413 fn completes_union_associated_method() {
414 check(
415 r#"
416union U {};
417impl U { fn m() { } }
418
419fn foo() { let _ = U::$0 }
420"#,
421 expect![[r#"
422 fn m() fn m()
423 "#]],
424 );
425 }
426
427 #[test]
428 fn completes_use_paths_across_crates() {
429 check(
430 r#"
431//- /main.rs crate:main deps:foo
432use foo::$0;
433
434//- /foo/lib.rs crate:foo
435pub mod bar { pub struct S; }
436"#,
437 expect![[r#"
438 md bar
439 "#]],
440 );
441 }
442
443 #[test]
444 fn completes_trait_associated_method_1() {
445 check(
446 r#"
447trait Trait { fn m(); }
448
449fn foo() { let _ = Trait::$0 }
450"#,
451 expect![[r#"
452 fn m() fn m()
453 "#]],
454 );
455 }
456
457 #[test]
458 fn completes_trait_associated_method_2() {
459 check(
460 r#"
461trait Trait { fn m(); }
462
463struct S;
464impl Trait for S {}
465
466fn foo() { let _ = S::$0 }
467"#,
468 expect![[r#"
469 fn m() fn m()
470 "#]],
471 );
472 }
473
474 #[test]
475 fn completes_trait_associated_method_3() {
476 check(
477 r#"
478trait Trait { fn m(); }
479
480struct S;
481impl Trait for S {}
482
483fn foo() { let _ = <S as Trait>::$0 }
484"#,
485 expect![[r#"
486 fn m() fn m()
487 "#]],
488 );
489 }
490
491 #[test]
492 fn completes_ty_param_assoc_ty() {
493 check(
494 r#"
495trait Super {
496 type Ty;
497 const CONST: u8;
498 fn func() {}
499 fn method(&self) {}
500}
501
502trait Sub: Super {
503 type SubTy;
504 const C2: ();
505 fn subfunc() {}
506 fn submethod(&self) {}
507}
508
509fn foo<T: Sub>() { T::$0 }
510"#,
511 expect![[r#"
512 ta SubTy type SubTy;
513 ta Ty type Ty;
514 ct C2 const C2: ();
515 fn subfunc() fn subfunc()
516 me submethod(…) fn submethod(&self)
517 ct CONST const CONST: u8;
518 fn func() fn func()
519 me method(…) fn method(&self)
520 "#]],
521 );
522 }
523
524 #[test]
525 fn completes_self_param_assoc_ty() {
526 check(
527 r#"
528trait Super {
529 type Ty;
530 const CONST: u8 = 0;
531 fn func() {}
532 fn method(&self) {}
533}
534
535trait Sub: Super {
536 type SubTy;
537 const C2: () = ();
538 fn subfunc() {}
539 fn submethod(&self) {}
540}
541
542struct Wrap<T>(T);
543impl<T> Super for Wrap<T> {}
544impl<T> Sub for Wrap<T> {
545 fn subfunc() {
546 // Should be able to assume `Self: Sub + Super`
547 Self::$0
548 }
549}
550"#,
551 expect![[r#"
552 ta SubTy type SubTy;
553 ta Ty type Ty;
554 ct CONST const CONST: u8 = 0;
555 fn func() fn func()
556 me method(…) fn method(&self)
557 ct C2 const C2: () = ();
558 fn subfunc() fn subfunc()
559 me submethod(…) fn submethod(&self)
560 "#]],
561 );
562 }
563
564 #[test]
565 fn completes_type_alias() {
566 check(
567 r#"
568struct S;
569impl S { fn foo() {} }
570type T = S;
571impl T { fn bar() {} }
572
573fn main() { T::$0; }
574"#,
575 expect![[r#"
576 fn foo() fn foo()
577 fn bar() fn bar()
578 "#]],
579 );
580 }
581
582 #[test]
583 fn completes_qualified_macros() {
584 check(
585 r#"
586#[macro_export]
587macro_rules! foo { () => {} }
588
589fn main() { let _ = crate::$0 }
590 "#,
591 expect![[r##"
592 fn main() fn main()
593 ma foo!(…) #[macro_export] macro_rules! foo
594 "##]],
595 );
596 }
597
598 #[test]
599 fn test_super_super_completion() {
600 check(
601 r#"
602mod a {
603 const A: usize = 0;
604 mod b {
605 const B: usize = 0;
606 mod c { use super::super::$0 }
607 }
608}
609"#,
610 expect![[r#"
611 md b
612 ct A
613 "#]],
614 );
615 }
616
617 #[test]
618 fn completes_reexported_items_under_correct_name() {
619 check(
620 r#"
621fn foo() { self::m::$0 }
622
623mod m {
624 pub use super::p::wrong_fn as right_fn;
625 pub use super::p::WRONG_CONST as RIGHT_CONST;
626 pub use super::p::WrongType as RightType;
627}
628mod p {
629 fn wrong_fn() {}
630 const WRONG_CONST: u32 = 1;
631 struct WrongType {};
632}
633"#,
634 expect![[r#"
635 ct RIGHT_CONST
636 fn right_fn() fn wrong_fn()
637 st RightType
638 "#]],
639 );
640
641 check_edit(
642 "RightType",
643 r#"
644fn foo() { self::m::$0 }
645
646mod m {
647 pub use super::p::wrong_fn as right_fn;
648 pub use super::p::WRONG_CONST as RIGHT_CONST;
649 pub use super::p::WrongType as RightType;
650}
651mod p {
652 fn wrong_fn() {}
653 const WRONG_CONST: u32 = 1;
654 struct WrongType {};
655}
656"#,
657 r#"
658fn foo() { self::m::RightType }
659
660mod m {
661 pub use super::p::wrong_fn as right_fn;
662 pub use super::p::WRONG_CONST as RIGHT_CONST;
663 pub use super::p::WrongType as RightType;
664}
665mod p {
666 fn wrong_fn() {}
667 const WRONG_CONST: u32 = 1;
668 struct WrongType {};
669}
670"#,
671 );
672 }
673
674 #[test]
675 fn completes_in_simple_macro_call() {
676 check(
677 r#"
678macro_rules! m { ($e:expr) => { $e } }
679fn main() { m!(self::f$0); }
680fn foo() {}
681"#,
682 expect![[r#"
683 fn main() fn main()
684 fn foo() fn foo()
685 "#]],
686 );
687 }
688
689 #[test]
690 fn function_mod_share_name() {
691 check(
692 r#"
693fn foo() { self::m::$0 }
694
695mod m {
696 pub mod z {}
697 pub fn z() {}
698}
699"#,
700 expect![[r#"
701 md z
702 fn z() pub fn z()
703 "#]],
704 );
705 }
706
707 #[test]
708 fn completes_hashmap_new() {
709 check(
710 r#"
711struct RandomState;
712struct HashMap<K, V, S = RandomState> {}
713
714impl<K, V> HashMap<K, V, RandomState> {
715 pub fn new() -> HashMap<K, V, RandomState> { }
716}
717fn foo() {
718 HashMap::$0
719}
720"#,
721 expect![[r#"
722 fn new() pub fn new() -> HashMap<K, V, RandomState>
723 "#]],
724 );
725 }
726
727 #[test]
728 fn dont_complete_attr() {
729 check(
730 r#"
731mod foo { pub struct Foo; }
732#[foo::$0]
733fn f() {}
734"#,
735 expect![[""]],
736 );
737 }
738
739 #[test]
740 fn completes_function() {
741 check(
742 r#"
743fn foo(
744 a: i32,
745 b: i32
746) {
747
748}
749
750fn main() {
751 fo$0
752}
753"#,
754 expect![[r#"
755 fn main() fn main()
756 fn foo(…) fn foo(a: i32, b: i32)
757 "#]],
758 );
759 }
760
761 #[test]
762 fn completes_self_enum() {
763 check(
764 r#"
765enum Foo {
766 Bar,
767 Baz,
768}
769
770impl Foo {
771 fn foo(self) {
772 Self::$0
773 }
774}
775"#,
776 expect![[r#"
777 ev Bar ()
778 ev Baz ()
779 me foo(…) fn foo(self)
780 "#]],
781 );
782 }
783}