diff options
Diffstat (limited to 'crates/ide_completion/src/completions/unqualified_path.rs')
-rw-r--r-- | crates/ide_completion/src/completions/unqualified_path.rs | 90 |
1 files changed, 68 insertions, 22 deletions
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index 7875500c1..ede07f605 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs | |||
@@ -1,7 +1,6 @@ | |||
1 | //! Completion of names from the current scope, e.g. locals and imported items. | 1 | //! Completion of names from the current scope, e.g. locals and imported items. |
2 | 2 | ||
3 | use hir::ScopeDef; | 3 | use hir::ScopeDef; |
4 | use syntax::AstNode; | ||
5 | 4 | ||
6 | use crate::{CompletionContext, Completions}; | 5 | use crate::{CompletionContext, Completions}; |
7 | 6 | ||
@@ -9,14 +8,30 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC | |||
9 | if !ctx.is_trivial_path { | 8 | if !ctx.is_trivial_path { |
10 | return; | 9 | return; |
11 | } | 10 | } |
12 | if ctx.record_lit_syntax.is_some() | 11 | if ctx.is_path_disallowed() || ctx.expects_item() { |
13 | || ctx.record_pat_syntax.is_some() | 12 | return; |
14 | || ctx.attribute_under_caret.is_some() | 13 | } |
15 | || ctx.mod_declaration_under_caret.is_some() | 14 | if ctx.expects_assoc_item() { |
16 | { | 15 | ctx.scope.process_all_names(&mut |name, def| { |
16 | if let ScopeDef::MacroDef(macro_def) = def { | ||
17 | acc.add_macro(ctx, Some(name.to_string()), macro_def); | ||
18 | } | ||
19 | if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = def { | ||
20 | acc.add_resolution(ctx, name.to_string(), &def); | ||
21 | } | ||
22 | }); | ||
17 | return; | 23 | return; |
18 | } | 24 | } |
19 | 25 | ||
26 | if ctx.expects_use_tree() { | ||
27 | cov_mark::hit!(only_completes_modules_in_import); | ||
28 | ctx.scope.process_all_names(&mut |name, res| { | ||
29 | if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res { | ||
30 | acc.add_resolution(ctx, name.to_string(), &res); | ||
31 | } | ||
32 | }); | ||
33 | return; | ||
34 | } | ||
20 | if let Some(hir::Adt::Enum(e)) = | 35 | if let Some(hir::Adt::Enum(e)) = |
21 | ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) | 36 | ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) |
22 | { | 37 | { |
@@ -30,14 +45,6 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC | |||
30 | cov_mark::hit!(skip_lifetime_completion); | 45 | cov_mark::hit!(skip_lifetime_completion); |
31 | return; | 46 | return; |
32 | } | 47 | } |
33 | if ctx.use_item_syntax.is_some() { | ||
34 | if let (ScopeDef::Unknown, Some(name_ref)) = (&res, &ctx.name_ref_syntax) { | ||
35 | if name_ref.syntax().text() == name.to_string().as_str() { | ||
36 | cov_mark::hit!(self_fulfilling_completion); | ||
37 | return; | ||
38 | } | ||
39 | } | ||
40 | } | ||
41 | acc.add_resolution(ctx, name.to_string(), &res); | 48 | acc.add_resolution(ctx, name.to_string(), &res); |
42 | }); | 49 | }); |
43 | } | 50 | } |
@@ -61,15 +68,17 @@ mod tests { | |||
61 | } | 68 | } |
62 | 69 | ||
63 | #[test] | 70 | #[test] |
64 | fn self_fulfilling_completion() { | 71 | fn only_completes_modules_in_import() { |
65 | cov_mark::check!(self_fulfilling_completion); | 72 | cov_mark::check!(only_completes_modules_in_import); |
66 | check( | 73 | check( |
67 | r#" | 74 | r#" |
68 | use foo$0 | 75 | use f$0 |
69 | use std::collections; | 76 | |
77 | struct Foo; | ||
78 | mod foo {} | ||
70 | "#, | 79 | "#, |
71 | expect![[r#" | 80 | expect![[r#" |
72 | ?? collections | 81 | md foo |
73 | "#]], | 82 | "#]], |
74 | ); | 83 | ); |
75 | } | 84 | } |
@@ -86,7 +95,7 @@ fn quux(x: Option<Enum>) { | |||
86 | } | 95 | } |
87 | } | 96 | } |
88 | "#, | 97 | "#, |
89 | expect![[""]], | 98 | expect![[r#""#]], |
90 | ); | 99 | ); |
91 | } | 100 | } |
92 | 101 | ||
@@ -102,7 +111,7 @@ fn quux(x: Option<Enum>) { | |||
102 | } | 111 | } |
103 | } | 112 | } |
104 | "#, | 113 | "#, |
105 | expect![[""]], | 114 | expect![[r#""#]], |
106 | ); | 115 | ); |
107 | } | 116 | } |
108 | 117 | ||
@@ -651,7 +660,7 @@ fn f() {} | |||
651 | } | 660 | } |
652 | 661 | ||
653 | #[test] | 662 | #[test] |
654 | fn completes_type_or_trait_in_impl_block() { | 663 | fn completes_target_type_or_trait_in_impl_block() { |
655 | check( | 664 | check( |
656 | r#" | 665 | r#" |
657 | trait MyTrait {} | 666 | trait MyTrait {} |
@@ -666,4 +675,41 @@ impl My$0 | |||
666 | "#]], | 675 | "#]], |
667 | ) | 676 | ) |
668 | } | 677 | } |
678 | |||
679 | #[test] | ||
680 | fn completes_in_assoc_item_list() { | ||
681 | check( | ||
682 | r#" | ||
683 | macro_rules! foo {} | ||
684 | mod bar {} | ||
685 | |||
686 | struct MyStruct {} | ||
687 | impl MyStruct { | ||
688 | $0 | ||
689 | } | ||
690 | "#, | ||
691 | expect![[r#" | ||
692 | md bar | ||
693 | ma foo! macro_rules! foo | ||
694 | "#]], | ||
695 | ) | ||
696 | } | ||
697 | |||
698 | // FIXME: The completions here currently come from `macro_in_item_position`, but they shouldn't | ||
699 | #[test] | ||
700 | fn completes_in_item_list() { | ||
701 | check( | ||
702 | r#" | ||
703 | struct MyStruct {} | ||
704 | macro_rules! foo {} | ||
705 | mod bar {} | ||
706 | |||
707 | $0 | ||
708 | "#, | ||
709 | expect![[r#" | ||
710 | md bar | ||
711 | ma foo!(…) macro_rules! foo | ||
712 | "#]], | ||
713 | ) | ||
714 | } | ||
669 | } | 715 | } |