aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/completion.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-12-21 15:13:21 +0000
committerAleksey Kladov <[email protected]>2018-12-21 15:13:21 +0000
commit45232dfa689bafadf98b92ef30fd32ea9a5e9e7a (patch)
tree4652bd1f393540f2f5abdaaab367cfb0b46a10d6 /crates/ra_analysis/src/completion.rs
parentd4ef07b2355df891d4f9b7641f0246ebe5bd6a6b (diff)
organize completion tests better
Diffstat (limited to 'crates/ra_analysis/src/completion.rs')
-rw-r--r--crates/ra_analysis/src/completion.rs343
1 files changed, 34 insertions, 309 deletions
diff --git a/crates/ra_analysis/src/completion.rs b/crates/ra_analysis/src/completion.rs
index 09894d955..a11e98ac0 100644
--- a/crates/ra_analysis/src/completion.rs
+++ b/crates/ra_analysis/src/completion.rs
@@ -16,7 +16,7 @@ use hir::source_binder;
16use crate::{ 16use crate::{
17 db, 17 db,
18 Cancelable, FilePosition, 18 Cancelable, FilePosition,
19 completion::completion_item::Completions, 19 completion::completion_item::{Completions, CompletionKind},
20}; 20};
21 21
22pub use crate::completion::completion_item::{CompletionItem, InsertText}; 22pub use crate::completion::completion_item::{CompletionItem, InsertText};
@@ -81,7 +81,12 @@ fn param_completions(acc: &mut Completions, ctx: SyntaxNodeRef) {
81 Some((label, lookup)) 81 Some((label, lookup))
82 } 82 }
83 }) 83 })
84 .for_each(|(label, lookup)| CompletionItem::new(label).lookup_by(lookup).add_to(acc)); 84 .for_each(|(label, lookup)| {
85 CompletionItem::new(label)
86 .lookup_by(lookup)
87 .kind(CompletionKind::Magic)
88 .add_to(acc)
89 });
85 90
86 fn process<'a, N: ast::FnDefOwner<'a>>( 91 fn process<'a, N: ast::FnDefOwner<'a>>(
87 node: N, 92 node: N,
@@ -105,341 +110,61 @@ fn is_node<'a, N: AstNode<'a>>(node: SyntaxNodeRef<'a>) -> bool {
105} 110}
106 111
107#[cfg(test)] 112#[cfg(test)]
108mod tests { 113fn check_completion(code: &str, expected_completions: &str, kind: CompletionKind) {
109 use test_utils::assert_eq_dbg; 114 use crate::mock_analysis::{single_file_with_position, analysis_and_position};
110 115 let (analysis, position) = if code.contains("//-") {
111 use crate::mock_analysis::single_file_with_position; 116 analysis_and_position(code)
117 } else {
118 single_file_with_position(code)
119 };
120 let completions = completions(&analysis.imp.db, position).unwrap().unwrap();
121 completions.assert_match(expected_completions, kind);
122}
112 123
124#[cfg(test)]
125mod tests {
113 use super::*; 126 use super::*;
114 127
115 fn is_snippet(completion_item: &CompletionItem) -> bool { 128 fn check_magic_completion(code: &str, expected_completions: &str) {
116 match completion_item.insert_text() { 129 check_completion(code, expected_completions, CompletionKind::Magic);
117 InsertText::Snippet { .. } => true,
118 _ => false,
119 }
120 }
121
122 fn check_scope_completion(code: &str, expected_completions: &str) {
123 let (analysis, position) = single_file_with_position(code);
124 let completions = completions(&analysis.imp.db, position)
125 .unwrap()
126 .unwrap()
127 .into_iter()
128 .filter(|c| !is_snippet(c))
129 .collect::<Vec<_>>();
130 assert_eq_dbg(expected_completions, &completions);
131 }
132
133 fn check_snippet_completion(code: &str, expected_completions: &str) {
134 let (analysis, position) = single_file_with_position(code);
135 let completions = completions(&analysis.imp.db, position)
136 .unwrap()
137 .unwrap()
138 .into_iter()
139 .filter(is_snippet)
140 .collect::<Vec<_>>();
141 assert_eq_dbg(expected_completions, &completions);
142 }
143
144 #[test]
145 fn test_completion_let_scope() {
146 check_scope_completion(
147 r"
148 fn quux(x: i32) {
149 let y = 92;
150 1 + <|>;
151 let z = ();
152 }
153 ",
154 r#"[CompletionItem { label: "y", lookup: None, snippet: None },
155 CompletionItem { label: "x", lookup: None, snippet: None },
156 CompletionItem { label: "quux", lookup: None, snippet: None }]"#,
157 );
158 }
159
160 #[test]
161 fn test_completion_if_let_scope() {
162 check_scope_completion(
163 r"
164 fn quux() {
165 if let Some(x) = foo() {
166 let y = 92;
167 };
168 if let Some(a) = bar() {
169 let b = 62;
170 1 + <|>
171 }
172 }
173 ",
174 r#"[CompletionItem { label: "b", lookup: None, snippet: None },
175 CompletionItem { label: "a", lookup: None, snippet: None },
176 CompletionItem { label: "quux", lookup: None, snippet: None }]"#,
177 );
178 }
179
180 #[test]
181 fn test_completion_for_scope() {
182 check_scope_completion(
183 r"
184 fn quux() {
185 for x in &[1, 2, 3] {
186 <|>
187 }
188 }
189 ",
190 r#"[CompletionItem { label: "x", lookup: None, snippet: None },
191 CompletionItem { label: "quux", lookup: None, snippet: None }]"#,
192 );
193 }
194
195 #[test]
196 fn test_completion_mod_scope() {
197 check_scope_completion(
198 r"
199 struct Foo;
200 enum Baz {}
201 fn quux() {
202 <|>
203 }
204 ",
205 r#"[CompletionItem { label: "quux", lookup: None, snippet: None },
206 CompletionItem { label: "Foo", lookup: None, snippet: None },
207 CompletionItem { label: "Baz", lookup: None, snippet: None }]"#,
208 );
209 }
210
211 #[test]
212 fn test_completion_mod_scope_no_self_use() {
213 check_scope_completion(
214 r"
215 use foo<|>;
216 ",
217 r#"[]"#,
218 );
219 }
220
221 #[test]
222 fn test_completion_self_path() {
223 check_scope_completion(
224 r"
225 use self::m::<|>;
226
227 mod m {
228 struct Bar;
229 }
230 ",
231 r#"[CompletionItem { label: "Bar", lookup: None, snippet: None }]"#,
232 );
233 }
234
235 #[test]
236 fn test_completion_mod_scope_nested() {
237 check_scope_completion(
238 r"
239 struct Foo;
240 mod m {
241 struct Bar;
242 fn quux() { <|> }
243 }
244 ",
245 r#"[CompletionItem { label: "quux", lookup: None, snippet: None },
246 CompletionItem { label: "Bar", lookup: None, snippet: None }]"#,
247 );
248 }
249
250 #[test]
251 fn test_complete_type() {
252 check_scope_completion(
253 r"
254 struct Foo;
255 fn x() -> <|>
256 ",
257 r#"[CompletionItem { label: "Foo", lookup: None, snippet: None },
258 CompletionItem { label: "x", lookup: None, snippet: None }]"#,
259 )
260 }
261
262 #[test]
263 fn test_complete_shadowing() {
264 check_scope_completion(
265 r"
266 fn foo() -> {
267 let bar = 92;
268 {
269 let bar = 62;
270 <|>
271 }
272 }
273 ",
274 r#"[CompletionItem { label: "bar", lookup: None, snippet: None },
275 CompletionItem { label: "foo", lookup: None, snippet: None }]"#,
276 )
277 }
278
279 #[test]
280 fn test_complete_self() {
281 check_scope_completion(
282 r"
283 impl S { fn foo(&self) { <|> } }
284 ",
285 r#"[CompletionItem { label: "self", lookup: None, snippet: None }]"#,
286 )
287 }
288
289 #[test]
290 fn test_completion_kewords() {
291 check_snippet_completion(r"
292 fn quux() {
293 <|>
294 }
295 ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") },
296 CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") },
297 CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") },
298 CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") },
299 CompletionItem { label: "return", lookup: None, snippet: Some("return") },
300 CompletionItem { label: "pd", lookup: None, snippet: Some("eprintln!(\"$0 = {:?}\", $0);") },
301 CompletionItem { label: "ppd", lookup: None, snippet: Some("eprintln!(\"$0 = {:#?}\", $0);") }]"#);
302 }
303
304 #[test]
305 fn test_completion_else() {
306 check_snippet_completion(r"
307 fn quux() {
308 if true {
309 ()
310 } <|>
311 }
312 ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") },
313 CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") },
314 CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") },
315 CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") },
316 CompletionItem { label: "else", lookup: None, snippet: Some("else {$0}") },
317 CompletionItem { label: "else if", lookup: None, snippet: Some("else if $0 {}") },
318 CompletionItem { label: "return", lookup: None, snippet: Some("return") },
319 CompletionItem { label: "pd", lookup: None, snippet: Some("eprintln!(\"$0 = {:?}\", $0);") },
320 CompletionItem { label: "ppd", lookup: None, snippet: Some("eprintln!(\"$0 = {:#?}\", $0);") }]"#);
321 }
322
323 #[test]
324 fn test_completion_return_value() {
325 check_snippet_completion(r"
326 fn quux() -> i32 {
327 <|>
328 92
329 }
330 ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") },
331 CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") },
332 CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") },
333 CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") },
334 CompletionItem { label: "return", lookup: None, snippet: Some("return $0;") },
335 CompletionItem { label: "pd", lookup: None, snippet: Some("eprintln!(\"$0 = {:?}\", $0);") },
336 CompletionItem { label: "ppd", lookup: None, snippet: Some("eprintln!(\"$0 = {:#?}\", $0);") }]"#);
337 check_snippet_completion(r"
338 fn quux() {
339 <|>
340 92
341 }
342 ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") },
343 CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") },
344 CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") },
345 CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") },
346 CompletionItem { label: "return", lookup: None, snippet: Some("return;") },
347 CompletionItem { label: "pd", lookup: None, snippet: Some("eprintln!(\"$0 = {:?}\", $0);") },
348 CompletionItem { label: "ppd", lookup: None, snippet: Some("eprintln!(\"$0 = {:#?}\", $0);") }]"#);
349 }
350
351 #[test]
352 fn test_completion_return_no_stmt() {
353 check_snippet_completion(r"
354 fn quux() -> i32 {
355 match () {
356 () => <|>
357 }
358 }
359 ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") },
360 CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") },
361 CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") },
362 CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") },
363 CompletionItem { label: "return", lookup: None, snippet: Some("return $0") },
364 CompletionItem { label: "pd", lookup: None, snippet: Some("eprintln!(\"$0 = {:?}\", $0);") },
365 CompletionItem { label: "ppd", lookup: None, snippet: Some("eprintln!(\"$0 = {:#?}\", $0);") }]"#);
366 }
367
368 #[test]
369 fn test_continue_break_completion() {
370 check_snippet_completion(r"
371 fn quux() -> i32 {
372 loop { <|> }
373 }
374 ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") },
375 CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") },
376 CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") },
377 CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") },
378 CompletionItem { label: "continue", lookup: None, snippet: Some("continue") },
379 CompletionItem { label: "break", lookup: None, snippet: Some("break") },
380 CompletionItem { label: "return", lookup: None, snippet: Some("return $0") },
381 CompletionItem { label: "pd", lookup: None, snippet: Some("eprintln!(\"$0 = {:?}\", $0);") },
382 CompletionItem { label: "ppd", lookup: None, snippet: Some("eprintln!(\"$0 = {:#?}\", $0);") }]"#);
383 check_snippet_completion(r"
384 fn quux() -> i32 {
385 loop { || { <|> } }
386 }
387 ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") },
388 CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") },
389 CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") },
390 CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") },
391 CompletionItem { label: "return", lookup: None, snippet: Some("return $0") },
392 CompletionItem { label: "pd", lookup: None, snippet: Some("eprintln!(\"$0 = {:?}\", $0);") },
393 CompletionItem { label: "ppd", lookup: None, snippet: Some("eprintln!(\"$0 = {:#?}\", $0);") }]"#);
394 } 130 }
395 131
396 #[test] 132 #[test]
397 fn test_param_completion_last_param() { 133 fn test_param_completion_last_param() {
398 check_scope_completion(r" 134 check_magic_completion(
135 r"
399 fn foo(file_id: FileId) {} 136 fn foo(file_id: FileId) {}
400 fn bar(file_id: FileId) {} 137 fn bar(file_id: FileId) {}
401 fn baz(file<|>) {} 138 fn baz(file<|>) {}
402 ", r#"[CompletionItem { label: "file_id: FileId", lookup: Some("file_id"), snippet: None }]"#); 139 ",
140 r#"file_id "file_id: FileId""#,
141 );
403 } 142 }
404 143
405 #[test] 144 #[test]
406 fn test_param_completion_nth_param() { 145 fn test_param_completion_nth_param() {
407 check_scope_completion(r" 146 check_magic_completion(
147 r"
408 fn foo(file_id: FileId) {} 148 fn foo(file_id: FileId) {}
409 fn bar(file_id: FileId) {} 149 fn bar(file_id: FileId) {}
410 fn baz(file<|>, x: i32) {} 150 fn baz(file<|>, x: i32) {}
411 ", r#"[CompletionItem { label: "file_id: FileId", lookup: Some("file_id"), snippet: None }]"#); 151 ",
152 r#"file_id "file_id: FileId""#,
153 );
412 } 154 }
413 155
414 #[test] 156 #[test]
415 fn test_param_completion_trait_param() { 157 fn test_param_completion_trait_param() {
416 check_scope_completion(r" 158 check_magic_completion(
159 r"
417 pub(crate) trait SourceRoot { 160 pub(crate) trait SourceRoot {
418 pub fn contains(&self, file_id: FileId) -> bool; 161 pub fn contains(&self, file_id: FileId) -> bool;
419 pub fn module_map(&self) -> &ModuleMap; 162 pub fn module_map(&self) -> &ModuleMap;
420 pub fn lines(&self, file_id: FileId) -> &LineIndex; 163 pub fn lines(&self, file_id: FileId) -> &LineIndex;
421 pub fn syntax(&self, file<|>) 164 pub fn syntax(&self, file<|>)
422 } 165 }
423 ", r#"[CompletionItem { label: "self", lookup: None, snippet: None },
424 CompletionItem { label: "SourceRoot", lookup: None, snippet: None },
425 CompletionItem { label: "file_id: FileId", lookup: Some("file_id"), snippet: None }]"#);
426 }
427
428 #[test]
429 fn test_item_snippets() {
430 // check_snippet_completion(r"
431 // <|>
432 // ",
433 // r##"[CompletionItem { label: "Test function", lookup: None, snippet: Some("#[test]\nfn test_${1:feature}() {\n$0\n}"##,
434 // );
435 check_snippet_completion(r"
436 #[cfg(test)]
437 mod tests {
438 <|>
439 }
440 ", 166 ",
441 r##"[CompletionItem { label: "Test function", lookup: Some("tfn"), snippet: Some("#[test]\nfn ${1:feature}() {\n $0\n}") }, 167 r#"file_id "file_id: FileId""#,
442 CompletionItem { label: "pub(crate)", lookup: None, snippet: Some("pub(crate) $0") }]"##,
443 ); 168 );
444 } 169 }
445} 170}