diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-03-20 07:32:19 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-03-20 07:32:19 +0000 |
commit | 1878fbe8bd60c7f9e58fda6dc7788e5f44ad0f89 (patch) | |
tree | 5dd13a24ef92a10bd686a80bbb2e59b83bf015d0 /crates/ra_ide/src/completion | |
parent | 1ba03c6995015b3143a417ed07437f0c9028a97d (diff) | |
parent | ec24c090063b3b86349f7812b716412d83dad069 (diff) |
Merge #3541
3541: Completition for type name? #3418 r=matklad a=slyngbaek
Iterate through TupleStructPat's until a MatchArm if
one exists. Store in a new is_pat_bind_and_path bool
and allow the `complete_scope` to find matches.
Added some tests to ensure it works in simple and nested cases.
Co-authored-by: Steffen Lyngbaek <[email protected]>
Diffstat (limited to 'crates/ra_ide/src/completion')
-rw-r--r-- | crates/ra_ide/src/completion/complete_pattern.rs | 50 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_scope.rs | 83 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/completion_context.rs | 13 |
3 files changed, 143 insertions, 3 deletions
diff --git a/crates/ra_ide/src/completion/complete_pattern.rs b/crates/ra_ide/src/completion/complete_pattern.rs index cb84bb934..bc8fade6f 100644 --- a/crates/ra_ide/src/completion/complete_pattern.rs +++ b/crates/ra_ide/src/completion/complete_pattern.rs | |||
@@ -56,6 +56,20 @@ mod tests { | |||
56 | assert_debug_snapshot!(completions, @r###" | 56 | assert_debug_snapshot!(completions, @r###" |
57 | [ | 57 | [ |
58 | CompletionItem { | 58 | CompletionItem { |
59 | label: "Bar", | ||
60 | source_range: [246; 246), | ||
61 | delete: [246; 246), | ||
62 | insert: "Bar", | ||
63 | kind: Struct, | ||
64 | }, | ||
65 | CompletionItem { | ||
66 | label: "E", | ||
67 | source_range: [246; 246), | ||
68 | delete: [246; 246), | ||
69 | insert: "E", | ||
70 | kind: Enum, | ||
71 | }, | ||
72 | CompletionItem { | ||
59 | label: "E", | 73 | label: "E", |
60 | source_range: [246; 246), | 74 | source_range: [246; 246), |
61 | delete: [246; 246), | 75 | delete: [246; 246), |
@@ -70,6 +84,20 @@ mod tests { | |||
70 | kind: EnumVariant, | 84 | kind: EnumVariant, |
71 | }, | 85 | }, |
72 | CompletionItem { | 86 | CompletionItem { |
87 | label: "X", | ||
88 | source_range: [246; 246), | ||
89 | delete: [246; 246), | ||
90 | insert: "X", | ||
91 | kind: EnumVariant, | ||
92 | }, | ||
93 | CompletionItem { | ||
94 | label: "Z", | ||
95 | source_range: [246; 246), | ||
96 | delete: [246; 246), | ||
97 | insert: "Z", | ||
98 | kind: Const, | ||
99 | }, | ||
100 | CompletionItem { | ||
73 | label: "Z", | 101 | label: "Z", |
74 | source_range: [246; 246), | 102 | source_range: [246; 246), |
75 | delete: [246; 246), | 103 | delete: [246; 246), |
@@ -83,6 +111,13 @@ mod tests { | |||
83 | insert: "m", | 111 | insert: "m", |
84 | kind: Module, | 112 | kind: Module, |
85 | }, | 113 | }, |
114 | CompletionItem { | ||
115 | label: "m", | ||
116 | source_range: [246; 246), | ||
117 | delete: [246; 246), | ||
118 | insert: "m", | ||
119 | kind: Module, | ||
120 | }, | ||
86 | ] | 121 | ] |
87 | "###); | 122 | "###); |
88 | } | 123 | } |
@@ -110,6 +145,21 @@ mod tests { | |||
110 | insert: "E", | 145 | insert: "E", |
111 | kind: Enum, | 146 | kind: Enum, |
112 | }, | 147 | }, |
148 | CompletionItem { | ||
149 | label: "E", | ||
150 | source_range: [151; 151), | ||
151 | delete: [151; 151), | ||
152 | insert: "E", | ||
153 | kind: Enum, | ||
154 | }, | ||
155 | CompletionItem { | ||
156 | label: "m!", | ||
157 | source_range: [151; 151), | ||
158 | delete: [151; 151), | ||
159 | insert: "m!($0)", | ||
160 | kind: Macro, | ||
161 | detail: "macro_rules! m", | ||
162 | }, | ||
113 | ] | 163 | ] |
114 | "###); | 164 | "###); |
115 | } | 165 | } |
diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs index 81d3cc1b6..2ca552733 100644 --- a/crates/ra_ide/src/completion/complete_scope.rs +++ b/crates/ra_ide/src/completion/complete_scope.rs | |||
@@ -1,13 +1,19 @@ | |||
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 crate::completion::{CompletionContext, Completions}; | 3 | use crate::completion::{CompletionContext, Completions}; |
4 | use hir::{ModuleDef, ScopeDef}; | ||
4 | 5 | ||
5 | pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { | 6 | pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { |
6 | if !ctx.is_trivial_path { | 7 | if !ctx.is_trivial_path && !ctx.is_pat_binding_and_path { |
7 | return; | 8 | return; |
8 | } | 9 | } |
9 | 10 | ||
10 | ctx.scope().process_all_names(&mut |name, res| acc.add_resolution(ctx, name.to_string(), &res)); | 11 | ctx.scope().process_all_names(&mut |name, res| match (ctx.is_pat_binding_and_path, &res) { |
12 | (true, ScopeDef::ModuleDef(ModuleDef::Function(..))) => (), | ||
13 | (true, ScopeDef::ModuleDef(ModuleDef::Static(..))) => (), | ||
14 | (true, ScopeDef::Local(..)) => (), | ||
15 | _ => acc.add_resolution(ctx, name.to_string(), &res), | ||
16 | }); | ||
11 | } | 17 | } |
12 | 18 | ||
13 | #[cfg(test)] | 19 | #[cfg(test)] |
@@ -21,6 +27,79 @@ mod tests { | |||
21 | } | 27 | } |
22 | 28 | ||
23 | #[test] | 29 | #[test] |
30 | fn bind_pat_and_path_ignore_at() { | ||
31 | assert_debug_snapshot!( | ||
32 | do_reference_completion( | ||
33 | r" | ||
34 | enum Enum { | ||
35 | A, | ||
36 | B, | ||
37 | } | ||
38 | fn quux(x: Option<Enum>) { | ||
39 | match x { | ||
40 | None => (), | ||
41 | Some(en<|> @ Enum::A) => (), | ||
42 | } | ||
43 | } | ||
44 | " | ||
45 | ), | ||
46 | @r###"[]"### | ||
47 | ); | ||
48 | } | ||
49 | |||
50 | #[test] | ||
51 | fn bind_pat_and_path_ignore_ref() { | ||
52 | assert_debug_snapshot!( | ||
53 | do_reference_completion( | ||
54 | r" | ||
55 | enum Enum { | ||
56 | A, | ||
57 | B, | ||
58 | } | ||
59 | fn quux(x: Option<Enum>) { | ||
60 | match x { | ||
61 | None => (), | ||
62 | Some(ref en<|>) => (), | ||
63 | } | ||
64 | } | ||
65 | " | ||
66 | ), | ||
67 | @r###"[]"### | ||
68 | ); | ||
69 | } | ||
70 | |||
71 | #[test] | ||
72 | fn bind_pat_and_path() { | ||
73 | assert_debug_snapshot!( | ||
74 | do_reference_completion( | ||
75 | r" | ||
76 | enum Enum { | ||
77 | A, | ||
78 | B, | ||
79 | } | ||
80 | fn quux(x: Option<Enum>) { | ||
81 | match x { | ||
82 | None => (), | ||
83 | Some(En<|>) => (), | ||
84 | } | ||
85 | } | ||
86 | " | ||
87 | ), | ||
88 | @r###" | ||
89 | [ | ||
90 | CompletionItem { | ||
91 | label: "Enum", | ||
92 | source_range: [231; 233), | ||
93 | delete: [231; 233), | ||
94 | insert: "Enum", | ||
95 | kind: Enum, | ||
96 | }, | ||
97 | ] | ||
98 | "### | ||
99 | ); | ||
100 | } | ||
101 | |||
102 | #[test] | ||
24 | fn completes_bindings_from_let() { | 103 | fn completes_bindings_from_let() { |
25 | assert_debug_snapshot!( | 104 | assert_debug_snapshot!( |
26 | do_reference_completion( | 105 | do_reference_completion( |
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index 54589a2a8..319e33b61 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs | |||
@@ -36,6 +36,9 @@ pub(crate) struct CompletionContext<'a> { | |||
36 | /// If a name-binding or reference to a const in a pattern. | 36 | /// If a name-binding or reference to a const in a pattern. |
37 | /// Irrefutable patterns (like let) are excluded. | 37 | /// Irrefutable patterns (like let) are excluded. |
38 | pub(super) is_pat_binding: bool, | 38 | pub(super) is_pat_binding: bool, |
39 | // A bind battern which may also be part of a path. | ||
40 | // if let Some(En<|>) = Some(Enum::A) | ||
41 | pub(super) is_pat_binding_and_path: bool, | ||
39 | /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path. | 42 | /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path. |
40 | pub(super) is_trivial_path: bool, | 43 | pub(super) is_trivial_path: bool, |
41 | /// If not a trivial path, the prefix (qualifier). | 44 | /// If not a trivial path, the prefix (qualifier). |
@@ -95,6 +98,7 @@ impl<'a> CompletionContext<'a> { | |||
95 | impl_def: None, | 98 | impl_def: None, |
96 | is_param: false, | 99 | is_param: false, |
97 | is_pat_binding: false, | 100 | is_pat_binding: false, |
101 | is_pat_binding_and_path: false, | ||
98 | is_trivial_path: false, | 102 | is_trivial_path: false, |
99 | path_prefix: None, | 103 | path_prefix: None, |
100 | after_if: false, | 104 | after_if: false, |
@@ -188,10 +192,17 @@ impl<'a> CompletionContext<'a> { | |||
188 | if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) { | 192 | if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) { |
189 | let parent = bind_pat.syntax().parent(); | 193 | let parent = bind_pat.syntax().parent(); |
190 | if parent.clone().and_then(ast::MatchArm::cast).is_some() | 194 | if parent.clone().and_then(ast::MatchArm::cast).is_some() |
191 | || parent.and_then(ast::Condition::cast).is_some() | 195 | || parent.clone().and_then(ast::Condition::cast).is_some() |
192 | { | 196 | { |
193 | self.is_pat_binding = true; | 197 | self.is_pat_binding = true; |
194 | } | 198 | } |
199 | |||
200 | if parent.and_then(ast::RecordFieldPatList::cast).is_none() | ||
201 | && bind_pat.pat().is_none() | ||
202 | && !bind_pat.is_ref() | ||
203 | { | ||
204 | self.is_pat_binding_and_path = true; | ||
205 | } | ||
195 | } | 206 | } |
196 | if is_node::<ast::Param>(name.syntax()) { | 207 | if is_node::<ast::Param>(name.syntax()) { |
197 | self.is_param = true; | 208 | self.is_param = true; |