diff options
Diffstat (limited to 'crates/ra_ide')
-rw-r--r-- | crates/ra_ide/src/completion/complete_keyword.rs | 183 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/completion_item.rs | 26 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/patterns.rs | 84 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/test_utils.rs | 52 |
4 files changed, 100 insertions, 245 deletions
diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 8ea51c7aa..432793de2 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs | |||
@@ -61,7 +61,6 @@ fn add_keyword( | |||
61 | 61 | ||
62 | pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { | 62 | pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { |
63 | add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); | 63 | add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); |
64 | add_keyword(ctx, acc, "type", "type ", ctx.is_new_item || ctx.block_expr_parent); | ||
65 | add_keyword(ctx, acc, "use", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); | 64 | add_keyword(ctx, acc, "use", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); |
66 | add_keyword(ctx, acc, "impl", "impl $0 {}", ctx.is_new_item); | 65 | add_keyword(ctx, acc, "impl", "impl $0 {}", ctx.is_new_item); |
67 | add_keyword(ctx, acc, "trait", "impl $0 {}", ctx.is_new_item); | 66 | add_keyword(ctx, acc, "trait", "impl $0 {}", ctx.is_new_item); |
@@ -111,12 +110,9 @@ fn complete_return( | |||
111 | 110 | ||
112 | #[cfg(test)] | 111 | #[cfg(test)] |
113 | mod tests { | 112 | mod tests { |
114 | use crate::{ | 113 | use crate::completion::{ |
115 | completion::{ | 114 | test_utils::{do_completion, get_completions}, |
116 | test_utils::{do_completion, do_completion_with_position}, | 115 | CompletionItem, CompletionKind, |
117 | CompletionItem, CompletionKind, | ||
118 | }, | ||
119 | CompletionItemKind, | ||
120 | }; | 116 | }; |
121 | use insta::assert_debug_snapshot; | 117 | use insta::assert_debug_snapshot; |
122 | 118 | ||
@@ -124,132 +120,39 @@ mod tests { | |||
124 | do_completion(code, CompletionKind::Keyword) | 120 | do_completion(code, CompletionKind::Keyword) |
125 | } | 121 | } |
126 | 122 | ||
127 | fn get_completion_text_and_assert_positions(code: &str) -> Vec<(String, String)> { | 123 | fn get_keyword_completions(code: &str) -> Vec<String> { |
128 | let (position, completion_items) = | 124 | get_completions(code, CompletionKind::Keyword) |
129 | do_completion_with_position(code, CompletionKind::Keyword); | ||
130 | let mut returned_keywords = Vec::<(String, String)>::new(); | ||
131 | |||
132 | for item in completion_items { | ||
133 | assert!(item.text_edit().len() == 1); | ||
134 | assert!(item.kind() == Some(CompletionItemKind::Keyword)); | ||
135 | let atom = item.text_edit().iter().next().unwrap().clone(); | ||
136 | assert!(atom.delete.start() == position.offset); | ||
137 | assert!(atom.delete.end() == position.offset); | ||
138 | let pair = (item.label().to_string(), atom.insert); | ||
139 | returned_keywords.push(pair); | ||
140 | } | ||
141 | returned_keywords.sort(); | ||
142 | returned_keywords | ||
143 | } | ||
144 | |||
145 | #[test] | ||
146 | fn completes_keywords_in_use_stmt_new_approach() { | ||
147 | assert_debug_snapshot!( | ||
148 | get_completion_text_and_assert_positions(r" | ||
149 | use <|> | ||
150 | "), | ||
151 | @r###" | ||
152 | [ | ||
153 | ( | ||
154 | "crate", | ||
155 | "crate::", | ||
156 | ), | ||
157 | ( | ||
158 | "self", | ||
159 | "self", | ||
160 | ), | ||
161 | ( | ||
162 | "super", | ||
163 | "super::", | ||
164 | ), | ||
165 | ] | ||
166 | "### | ||
167 | ); | ||
168 | } | 125 | } |
169 | 126 | ||
170 | #[test] | 127 | #[test] |
171 | fn completes_keywords_in_use_stmt() { | 128 | fn completes_keywords_in_use_stmt() { |
172 | assert_debug_snapshot!( | 129 | assert_debug_snapshot!( |
173 | do_keyword_completion( | 130 | get_keyword_completions(r"use <|>"), |
174 | r" | ||
175 | use <|> | ||
176 | ", | ||
177 | ), | ||
178 | @r###" | 131 | @r###" |
179 | [ | 132 | [ |
180 | CompletionItem { | 133 | "kw crate", |
181 | label: "crate", | 134 | "kw self", |
182 | source_range: 21..21, | 135 | "kw super", |
183 | delete: 21..21, | ||
184 | insert: "crate::", | ||
185 | kind: Keyword, | ||
186 | }, | ||
187 | CompletionItem { | ||
188 | label: "self", | ||
189 | source_range: 21..21, | ||
190 | delete: 21..21, | ||
191 | insert: "self", | ||
192 | kind: Keyword, | ||
193 | }, | ||
194 | CompletionItem { | ||
195 | label: "super", | ||
196 | source_range: 21..21, | ||
197 | delete: 21..21, | ||
198 | insert: "super::", | ||
199 | kind: Keyword, | ||
200 | }, | ||
201 | ] | 136 | ] |
202 | "### | 137 | "### |
203 | ); | 138 | ); |
204 | 139 | ||
205 | assert_debug_snapshot!( | 140 | assert_debug_snapshot!( |
206 | do_keyword_completion( | 141 | get_keyword_completions(r"use a::<|>"), |
207 | r" | ||
208 | use a::<|> | ||
209 | ", | ||
210 | ), | ||
211 | @r###" | 142 | @r###" |
212 | [ | 143 | [ |
213 | CompletionItem { | 144 | "kw self", |
214 | label: "self", | 145 | "kw super", |
215 | source_range: 24..24, | ||
216 | delete: 24..24, | ||
217 | insert: "self", | ||
218 | kind: Keyword, | ||
219 | }, | ||
220 | CompletionItem { | ||
221 | label: "super", | ||
222 | source_range: 24..24, | ||
223 | delete: 24..24, | ||
224 | insert: "super::", | ||
225 | kind: Keyword, | ||
226 | }, | ||
227 | ] | 146 | ] |
228 | "### | 147 | "### |
229 | ); | 148 | ); |
230 | 149 | ||
231 | assert_debug_snapshot!( | 150 | assert_debug_snapshot!( |
232 | do_keyword_completion( | 151 | get_keyword_completions(r"use a::{b, <|>}"), |
233 | r" | ||
234 | use a::{b, <|>} | ||
235 | ", | ||
236 | ), | ||
237 | @r###" | 152 | @r###" |
238 | [ | 153 | [ |
239 | CompletionItem { | 154 | "kw self", |
240 | label: "self", | 155 | "kw super", |
241 | source_range: 28..28, | ||
242 | delete: 28..28, | ||
243 | insert: "self", | ||
244 | kind: Keyword, | ||
245 | }, | ||
246 | CompletionItem { | ||
247 | label: "super", | ||
248 | source_range: 28..28, | ||
249 | delete: 28..28, | ||
250 | insert: "super::", | ||
251 | kind: Keyword, | ||
252 | }, | ||
253 | ] | 156 | ] |
254 | "### | 157 | "### |
255 | ); | 158 | ); |
@@ -258,50 +161,22 @@ mod tests { | |||
258 | #[test] | 161 | #[test] |
259 | fn completes_various_keywords_in_function() { | 162 | fn completes_various_keywords_in_function() { |
260 | assert_debug_snapshot!( | 163 | assert_debug_snapshot!( |
261 | do_keyword_completion( | 164 | get_keyword_completions(r"fn quux() { <|> }"), |
262 | r" | ||
263 | fn quux() { | ||
264 | <|> | ||
265 | } | ||
266 | ", | ||
267 | ), | ||
268 | @r###" | 165 | @r###" |
269 | [ | 166 | [ |
270 | CompletionItem { | 167 | "kw const", |
271 | label: "if", | 168 | "kw extern", |
272 | source_range: 49..49, | 169 | "kw fn", |
273 | delete: 49..49, | 170 | "kw let", |
274 | insert: "if $0 {}", | 171 | "kw loop", |
275 | kind: Keyword, | 172 | "kw match", |
276 | }, | 173 | "kw mod", |
277 | CompletionItem { | 174 | "kw return", |
278 | label: "loop", | 175 | "kw static", |
279 | source_range: 49..49, | 176 | "kw type", |
280 | delete: 49..49, | 177 | "kw unsafe", |
281 | insert: "loop {$0}", | 178 | "kw use", |
282 | kind: Keyword, | 179 | "kw while", |
283 | }, | ||
284 | CompletionItem { | ||
285 | label: "match", | ||
286 | source_range: 49..49, | ||
287 | delete: 49..49, | ||
288 | insert: "match $0 {}", | ||
289 | kind: Keyword, | ||
290 | }, | ||
291 | CompletionItem { | ||
292 | label: "return", | ||
293 | source_range: 49..49, | ||
294 | delete: 49..49, | ||
295 | insert: "return;", | ||
296 | kind: Keyword, | ||
297 | }, | ||
298 | CompletionItem { | ||
299 | label: "while", | ||
300 | source_range: 49..49, | ||
301 | delete: 49..49, | ||
302 | insert: "while $0 {}", | ||
303 | kind: Keyword, | ||
304 | }, | ||
305 | ] | 180 | ] |
306 | "### | 181 | "### |
307 | ); | 182 | ); |
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs index cfb7c1e38..d1a4dd881 100644 --- a/crates/ra_ide/src/completion/completion_item.rs +++ b/crates/ra_ide/src/completion/completion_item.rs | |||
@@ -125,6 +125,32 @@ pub enum CompletionItemKind { | |||
125 | Attribute, | 125 | Attribute, |
126 | } | 126 | } |
127 | 127 | ||
128 | impl CompletionItemKind { | ||
129 | pub fn tag(&self) -> String { | ||
130 | let tag = match self { | ||
131 | CompletionItemKind::Snippet => "sn", | ||
132 | CompletionItemKind::Keyword => "kw", | ||
133 | CompletionItemKind::Module => "md", | ||
134 | CompletionItemKind::Function => "fn", | ||
135 | CompletionItemKind::BuiltinType => "bt", | ||
136 | CompletionItemKind::Struct => "st", | ||
137 | CompletionItemKind::Enum => "en", | ||
138 | CompletionItemKind::EnumVariant => "ev", | ||
139 | CompletionItemKind::Binding => "bn", | ||
140 | CompletionItemKind::Field => "fd", | ||
141 | CompletionItemKind::Static => "sc", | ||
142 | CompletionItemKind::Const => "ct", | ||
143 | CompletionItemKind::Trait => "tt", | ||
144 | CompletionItemKind::TypeAlias => "ta", | ||
145 | CompletionItemKind::Method => "me", | ||
146 | CompletionItemKind::TypeParam => "tp", | ||
147 | CompletionItemKind::Macro => "ma", | ||
148 | CompletionItemKind::Attribute => "at", | ||
149 | }; | ||
150 | tag.to_owned() | ||
151 | } | ||
152 | } | ||
153 | |||
128 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] | 154 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] |
129 | pub(crate) enum CompletionKind { | 155 | pub(crate) enum CompletionKind { |
130 | /// Parser-based keyword completion. | 156 | /// Parser-based keyword completion. |
diff --git a/crates/ra_ide/src/completion/patterns.rs b/crates/ra_ide/src/completion/patterns.rs index 25be0c307..bc39689ab 100644 --- a/crates/ra_ide/src/completion/patterns.rs +++ b/crates/ra_ide/src/completion/patterns.rs | |||
@@ -121,115 +121,51 @@ mod tests { | |||
121 | 121 | ||
122 | #[test] | 122 | #[test] |
123 | fn test_unsafe_is_prev() { | 123 | fn test_unsafe_is_prev() { |
124 | check_pattern_is_applicable( | 124 | check_pattern_is_applicable(r"unsafe i<|>", unsafe_is_prev); |
125 | r" | ||
126 | unsafe i<|> | ||
127 | ", | ||
128 | unsafe_is_prev, | ||
129 | ); | ||
130 | } | 125 | } |
131 | 126 | ||
132 | #[test] | 127 | #[test] |
133 | fn test_if_is_prev() { | 128 | fn test_if_is_prev() { |
134 | check_pattern_is_applicable( | 129 | check_pattern_is_applicable(r"if l<|>", if_is_prev); |
135 | r" | ||
136 | if l<|> | ||
137 | ", | ||
138 | if_is_prev, | ||
139 | ); | ||
140 | } | 130 | } |
141 | 131 | ||
142 | #[test] | 132 | #[test] |
143 | fn test_inside_trait() { | 133 | fn test_inside_trait() { |
144 | check_pattern_is_applicable( | 134 | check_pattern_is_applicable(r"trait A { fn<|> }", inside_trait); |
145 | r" | ||
146 | trait A { | ||
147 | fn<|> | ||
148 | } | ||
149 | ", | ||
150 | inside_trait, | ||
151 | ); | ||
152 | } | 135 | } |
153 | 136 | ||
154 | #[test] | 137 | #[test] |
155 | fn test_has_trait_as_prev_sibling() { | 138 | fn test_has_trait_as_prev_sibling() { |
156 | check_pattern_is_applicable( | 139 | check_pattern_is_applicable(r"trait A w<|> {}", has_trait_as_prev_sibling); |
157 | r" | ||
158 | trait A w<|> { | ||
159 | } | ||
160 | ", | ||
161 | has_trait_as_prev_sibling, | ||
162 | ); | ||
163 | } | 140 | } |
164 | 141 | ||
165 | #[test] | 142 | #[test] |
166 | fn test_has_impl_as_prev_sibling() { | 143 | fn test_has_impl_as_prev_sibling() { |
167 | check_pattern_is_applicable( | 144 | check_pattern_is_applicable(r"impl A w<|> {}", has_impl_as_prev_sibling); |
168 | r" | ||
169 | impl A w<|> { | ||
170 | } | ||
171 | ", | ||
172 | has_impl_as_prev_sibling, | ||
173 | ); | ||
174 | } | 145 | } |
175 | 146 | ||
176 | #[test] | 147 | #[test] |
177 | fn test_parent_block_expr() { | 148 | fn test_parent_block_expr() { |
178 | check_pattern_is_applicable( | 149 | check_pattern_is_applicable(r"fn my_fn() { let a = 2; f<|> }", has_block_expr_parent); |
179 | r" | ||
180 | fn my_fn() { | ||
181 | let a = 2; | ||
182 | f<|> | ||
183 | } | ||
184 | ", | ||
185 | has_block_expr_parent, | ||
186 | ); | ||
187 | } | 150 | } |
188 | 151 | ||
189 | #[test] | 152 | #[test] |
190 | fn test_has_ref_pat_parent_in_func_parameters() { | 153 | fn test_has_ref_pat_parent_in_func_parameters() { |
191 | check_pattern_is_applicable( | 154 | check_pattern_is_applicable(r"fn my_fn(&<|>) {}", has_ref_pat_parent); |
192 | r" | ||
193 | fn my_fn(&<|>) { | ||
194 | let a = 2; | ||
195 | } | ||
196 | ", | ||
197 | has_ref_pat_parent, | ||
198 | ); | ||
199 | } | 155 | } |
200 | 156 | ||
201 | #[test] | 157 | #[test] |
202 | fn test_has_ref_pat_parent_in_let_statement() { | 158 | fn test_has_ref_pat_parent_in_let_statement() { |
203 | check_pattern_is_applicable( | 159 | check_pattern_is_applicable(r"fn my_fn() { let &<|> }", has_ref_pat_parent); |
204 | r" | ||
205 | fn my_fn() { | ||
206 | let &<|> | ||
207 | } | ||
208 | ", | ||
209 | has_ref_pat_parent, | ||
210 | ); | ||
211 | } | 160 | } |
212 | 161 | ||
213 | #[test] | 162 | #[test] |
214 | fn test_has_bind_pat_parent_in_func_parameters() { | 163 | fn test_has_bind_pat_parent_in_func_parameters() { |
215 | check_pattern_is_applicable( | 164 | check_pattern_is_applicable(r"fn my_fn(m<|>) {}", has_bind_pat_parent); |
216 | r" | ||
217 | fn my_fn(m<|>) { | ||
218 | } | ||
219 | ", | ||
220 | has_bind_pat_parent, | ||
221 | ); | ||
222 | } | 165 | } |
223 | 166 | ||
224 | #[test] | 167 | #[test] |
225 | fn test_has_bind_pat_parent_in_let_statement() { | 168 | fn test_has_bind_pat_parent_in_let_statement() { |
226 | check_pattern_is_applicable( | 169 | check_pattern_is_applicable(r"fn my_fn() { let m<|> }", has_bind_pat_parent); |
227 | r" | ||
228 | fn my_fn() { | ||
229 | let m<|> | ||
230 | } | ||
231 | ", | ||
232 | has_bind_pat_parent, | ||
233 | ); | ||
234 | } | 170 | } |
235 | } | 171 | } |
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs index f439f974d..c660de7b1 100644 --- a/crates/ra_ide/src/completion/test_utils.rs +++ b/crates/ra_ide/src/completion/test_utils.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use crate::{ | 3 | use crate::{ |
4 | completion::{completion_item::CompletionKind, CompletionConfig}, | 4 | completion::{completion_item::CompletionKind, CompletionConfig}, |
5 | mock_analysis::{analysis_and_position, single_file_with_position}, | 5 | mock_analysis::{analysis_and_position, single_file_with_position}, |
6 | CompletionItem, FilePosition, | 6 | CompletionItem, |
7 | }; | 7 | }; |
8 | use hir::Semantics; | 8 | use hir::Semantics; |
9 | use ra_syntax::{AstNode, NodeOrToken, SyntaxElement}; | 9 | use ra_syntax::{AstNode, NodeOrToken, SyntaxElement}; |
@@ -12,11 +12,8 @@ pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionI | |||
12 | do_completion_with_options(code, kind, &CompletionConfig::default()) | 12 | do_completion_with_options(code, kind, &CompletionConfig::default()) |
13 | } | 13 | } |
14 | 14 | ||
15 | pub(crate) fn do_completion_with_position( | 15 | pub(crate) fn get_completions(code: &str, kind: CompletionKind) -> Vec<String> { |
16 | code: &str, | 16 | get_completions_with_options(code, kind, &CompletionConfig::default()) |
17 | kind: CompletionKind, | ||
18 | ) -> (FilePosition, Vec<CompletionItem>) { | ||
19 | do_completion_with_options_and_position(code, kind, &CompletionConfig::default()) | ||
20 | } | 17 | } |
21 | 18 | ||
22 | pub(crate) fn do_completion_with_options( | 19 | pub(crate) fn do_completion_with_options( |
@@ -24,25 +21,46 @@ pub(crate) fn do_completion_with_options( | |||
24 | kind: CompletionKind, | 21 | kind: CompletionKind, |
25 | options: &CompletionConfig, | 22 | options: &CompletionConfig, |
26 | ) -> Vec<CompletionItem> { | 23 | ) -> Vec<CompletionItem> { |
27 | do_completion_with_options_and_position(code, kind, options).1 | 24 | let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(code, options) |
25 | .into_iter() | ||
26 | .filter(|c| c.completion_kind == kind) | ||
27 | .collect(); | ||
28 | kind_completions.sort_by_key(|c| c.label().to_owned()); | ||
29 | kind_completions | ||
28 | } | 30 | } |
29 | 31 | ||
30 | pub(crate) fn do_completion_with_options_and_position( | 32 | fn get_all_completion_items(code: &str, options: &CompletionConfig) -> Vec<CompletionItem> { |
31 | code: &str, | ||
32 | kind: CompletionKind, | ||
33 | options: &CompletionConfig, | ||
34 | ) -> (FilePosition, Vec<CompletionItem>) { | ||
35 | let (analysis, position) = if code.contains("//-") { | 33 | let (analysis, position) = if code.contains("//-") { |
36 | analysis_and_position(code) | 34 | analysis_and_position(code) |
37 | } else { | 35 | } else { |
38 | single_file_with_position(code) | 36 | single_file_with_position(code) |
39 | }; | 37 | }; |
40 | let completions = analysis.completions(options, position).unwrap().unwrap(); | 38 | analysis.completions(options, position).unwrap().unwrap().into() |
41 | let completion_items: Vec<CompletionItem> = completions.into(); | 39 | } |
42 | let mut kind_completions: Vec<CompletionItem> = | 40 | |
43 | completion_items.into_iter().filter(|c| c.completion_kind == kind).collect(); | 41 | pub(crate) fn get_all_completions(code: &str, options: &CompletionConfig) -> Vec<String> { |
42 | let mut kind_completions = get_all_completion_items(code, options); | ||
43 | kind_completions.sort_by_key(|c| c.label().to_owned()); | ||
44 | kind_completions | ||
45 | .into_iter() | ||
46 | .map(|it| format!("{} {}", it.kind().unwrap().tag(), it.label())) | ||
47 | .collect() | ||
48 | } | ||
49 | |||
50 | pub(crate) fn get_completions_with_options( | ||
51 | code: &str, | ||
52 | kind: CompletionKind, | ||
53 | options: &CompletionConfig, | ||
54 | ) -> Vec<String> { | ||
55 | let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(code, options) | ||
56 | .into_iter() | ||
57 | .filter(|c| c.completion_kind == kind) | ||
58 | .collect(); | ||
44 | kind_completions.sort_by_key(|c| c.label().to_owned()); | 59 | kind_completions.sort_by_key(|c| c.label().to_owned()); |
45 | (position, kind_completions) | 60 | kind_completions |
61 | .into_iter() | ||
62 | .map(|it| format!("{} {}", it.kind().unwrap().tag(), it.label())) | ||
63 | .collect() | ||
46 | } | 64 | } |
47 | 65 | ||
48 | pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -> bool) { | 66 | pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -> bool) { |