aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/completion
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/completion')
-rw-r--r--crates/ra_ide/src/completion/complete_dot.rs8
-rw-r--r--crates/ra_ide/src/completion/complete_keyword.rs12
-rw-r--r--crates/ra_ide/src/completion/complete_pattern.rs2
-rw-r--r--crates/ra_ide/src/completion/complete_postfix.rs24
-rw-r--r--crates/ra_ide/src/completion/complete_qualified_path.rs1523
-rw-r--r--crates/ra_ide/src/completion/complete_snippet.rs106
-rw-r--r--crates/ra_ide/src/completion/presentation.rs51
-rw-r--r--crates/ra_ide/src/completion/test_utils.rs17
8 files changed, 539 insertions, 1204 deletions
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs
index 667a8b949..3c6c8c81a 100644
--- a/crates/ra_ide/src/completion/complete_dot.rs
+++ b/crates/ra_ide/src/completion/complete_dot.rs
@@ -83,7 +83,7 @@ fn foo(s: S) { s.<|> }
83"#, 83"#,
84 expect![[r#" 84 expect![[r#"
85 me bar() fn bar(&self) 85 me bar() fn bar(&self)
86 fd foo u32 86 fd foo u32
87 "#]], 87 "#]],
88 ); 88 );
89 } 89 }
@@ -98,7 +98,7 @@ impl S {
98} 98}
99"#, 99"#,
100 expect![[r#" 100 expect![[r#"
101 me foo() fn foo(self) 101 me foo() fn foo(self)
102 fd the_field (u32,) 102 fd the_field (u32,)
103 "#]], 103 "#]],
104 ) 104 )
@@ -114,7 +114,7 @@ impl A {
114} 114}
115"#, 115"#,
116 expect![[r#" 116 expect![[r#"
117 me foo() fn foo(&self) 117 me foo() fn foo(&self)
118 fd the_field (u32, i32) 118 fd the_field (u32, i32)
119 "#]], 119 "#]],
120 ) 120 )
@@ -148,7 +148,7 @@ fn foo(a: inner::A) { a.<|> }
148"#, 148"#,
149 expect![[r#" 149 expect![[r#"
150 fd crate_field u32 150 fd crate_field u32
151 fd pub_field u32 151 fd pub_field u32
152 fd super_field u32 152 fd super_field u32
153 "#]], 153 "#]],
154 ); 154 );
diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs
index 340d57a49..2dc401f57 100644
--- a/crates/ra_ide/src/completion/complete_keyword.rs
+++ b/crates/ra_ide/src/completion/complete_keyword.rs
@@ -216,17 +216,17 @@ mod tests {
216 check( 216 check(
217 r"use a::<|>", 217 r"use a::<|>",
218 expect![[r#" 218 expect![[r#"
219 kw self 219 kw self
220 kw super:: 220 kw super::
221 "#]], 221 "#]],
222 ); 222 );
223 223
224 check( 224 check(
225 r"use a::{b, <|>}", 225 r"use a::{b, <|>}",
226 expect![[r#" 226 expect![[r#"
227 kw self 227 kw self
228 kw super:: 228 kw super::
229 "#]], 229 "#]],
230 ); 230 );
231 } 231 }
232 232
diff --git a/crates/ra_ide/src/completion/complete_pattern.rs b/crates/ra_ide/src/completion/complete_pattern.rs
index 41c16df7b..13fa7548d 100644
--- a/crates/ra_ide/src/completion/complete_pattern.rs
+++ b/crates/ra_ide/src/completion/complete_pattern.rs
@@ -61,7 +61,7 @@ fn foo() {
61 expect![[r#" 61 expect![[r#"
62 st Bar 62 st Bar
63 en E 63 en E
64 ev X () 64 ev X ()
65 ct Z 65 ct Z
66 md m 66 md m
67 "#]], 67 "#]],
diff --git a/crates/ra_ide/src/completion/complete_postfix.rs b/crates/ra_ide/src/completion/complete_postfix.rs
index 14013dc2f..8735b9010 100644
--- a/crates/ra_ide/src/completion/complete_postfix.rs
+++ b/crates/ra_ide/src/completion/complete_postfix.rs
@@ -260,14 +260,14 @@ fn main() {
260} 260}
261"#, 261"#,
262 expect![[r#" 262 expect![[r#"
263 sn box Box::new(expr) 263 sn box Box::new(expr)
264 sn call function(expr) 264 sn call function(expr)
265 sn dbg dbg!(expr) 265 sn dbg dbg!(expr)
266 sn if if expr {} 266 sn if if expr {}
267 sn match match expr {} 267 sn match match expr {}
268 sn not !expr 268 sn not !expr
269 sn ref &expr 269 sn ref &expr
270 sn refm &mut expr 270 sn refm &mut expr
271 sn while while expr {} 271 sn while while expr {}
272 "#]], 272 "#]],
273 ); 273 );
@@ -283,12 +283,12 @@ fn main() {
283} 283}
284"#, 284"#,
285 expect![[r#" 285 expect![[r#"
286 sn box Box::new(expr) 286 sn box Box::new(expr)
287 sn call function(expr) 287 sn call function(expr)
288 sn dbg dbg!(expr) 288 sn dbg dbg!(expr)
289 sn match match expr {} 289 sn match match expr {}
290 sn ref &expr 290 sn ref &expr
291 sn refm &mut expr 291 sn refm &mut expr
292 "#]], 292 "#]],
293 ) 293 )
294 } 294 }
diff --git a/crates/ra_ide/src/completion/complete_qualified_path.rs b/crates/ra_ide/src/completion/complete_qualified_path.rs
index 5175c8afe..e5553e28f 100644
--- a/crates/ra_ide/src/completion/complete_qualified_path.rs
+++ b/crates/ra_ide/src/completion/complete_qualified_path.rs
@@ -147,1269 +147,588 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
147 147
148#[cfg(test)] 148#[cfg(test)]
149mod tests { 149mod tests {
150 use expect::{expect, Expect};
150 use test_utils::mark; 151 use test_utils::mark;
151 152
152 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; 153 use crate::completion::{
153 use insta::assert_debug_snapshot; 154 test_utils::{check_edit, completion_list},
155 CompletionKind,
156 };
157
158 fn check(ra_fixture: &str, expect: Expect) {
159 let actual = completion_list(ra_fixture, CompletionKind::Reference);
160 expect.assert_eq(&actual);
161 }
154 162
155 fn do_reference_completion(code: &str) -> Vec<CompletionItem> { 163 fn check_builtin(ra_fixture: &str, expect: Expect) {
156 do_completion(code, CompletionKind::Reference) 164 let actual = completion_list(ra_fixture, CompletionKind::BuiltinType);
165 expect.assert_eq(&actual);
157 } 166 }
158 167
159 #[test] 168 #[test]
160 fn dont_complete_current_use() { 169 fn dont_complete_current_use() {
161 mark::check!(dont_complete_current_use); 170 mark::check!(dont_complete_current_use);
162 let completions = do_completion(r"use self::foo<|>;", CompletionKind::Reference); 171 check(r#"use self::foo<|>;"#, expect![[""]]);
163 assert!(completions.is_empty());
164 } 172 }
165 173
166 #[test] 174 #[test]
167 fn dont_complete_current_use_in_braces_with_glob() { 175 fn dont_complete_current_use_in_braces_with_glob() {
168 let completions = do_completion( 176 check(
169 r" 177 r#"
170 mod foo { pub struct S; } 178mod foo { pub struct S; }
171 use self::{foo::*, bar<|>}; 179use self::{foo::*, bar<|>};
172 ", 180"#,
173 CompletionKind::Reference, 181 expect![[r#"
182 st S
183 md foo
184 "#]],
174 ); 185 );
175 assert_eq!(completions.len(), 2);
176 } 186 }
177 187
178 #[test] 188 #[test]
179 fn dont_complete_primitive_in_use() { 189 fn dont_complete_primitive_in_use() {
180 let completions = do_completion(r"use self::<|>;", CompletionKind::BuiltinType); 190 check_builtin(r#"use self::<|>;"#, expect![[""]]);
181 assert!(completions.is_empty());
182 } 191 }
183 192
184 #[test] 193 #[test]
185 fn dont_complete_primitive_in_module_scope() { 194 fn dont_complete_primitive_in_module_scope() {
186 let completions = do_completion(r"fn foo() { self::<|> }", CompletionKind::BuiltinType); 195 check_builtin(r#"fn foo() { self::<|> }"#, expect![[""]]);
187 assert!(completions.is_empty());
188 } 196 }
189 197
190 #[test] 198 #[test]
191 fn completes_primitives() { 199 fn completes_primitives() {
192 let completions = 200 check_builtin(
193 do_completion(r"fn main() { let _: <|> = 92; }", CompletionKind::BuiltinType); 201 r#"fn main() { let _: <|> = 92; }"#,
194 assert_eq!(completions.len(), 17); 202 expect![[r#"
195 } 203 bt bool
196 204 bt char
197 #[test] 205 bt f32
198 fn completes_mod_with_docs() { 206 bt f64
199 assert_debug_snapshot!( 207 bt i128
200 do_reference_completion( 208 bt i16
201 r" 209 bt i32
202 use self::my<|>; 210 bt i64
203 211 bt i8
204 /// Some simple 212 bt isize
205 /// docs describing `mod my`. 213 bt str
206 mod my { 214 bt u128
207 struct Bar; 215 bt u16
208 } 216 bt u32
209 " 217 bt u64
210 ), 218 bt u8
211 @r###" 219 bt usize
212 [ 220 "#]],
213 CompletionItem {
214 label: "my",
215 source_range: 10..12,
216 delete: 10..12,
217 insert: "my",
218 kind: Module,
219 documentation: Documentation(
220 "Some simple\ndocs describing `mod my`.",
221 ),
222 },
223 ]
224 "###
225 ); 221 );
226 } 222 }
227 223
228 #[test] 224 #[test]
229 fn completes_mod_with_same_name_as_function() { 225 fn completes_mod_with_same_name_as_function() {
230 assert_debug_snapshot!( 226 check(
231 do_reference_completion( 227 r#"
232 r" 228use self::my::<|>;
233 use self::my::<|>; 229
234 230mod my { pub struct Bar; }
235 mod my { 231fn my() {}
236 pub struct Bar; 232"#,
237 } 233 expect![[r#"
238 234 st Bar
239 fn my() {} 235 "#]],
240 "
241 ),
242 @r###"
243 [
244 CompletionItem {
245 label: "Bar",
246 source_range: 14..14,
247 delete: 14..14,
248 insert: "Bar",
249 kind: Struct,
250 },
251 ]
252 "###
253 ); 236 );
254 } 237 }
255 238
256 #[test] 239 #[test]
257 fn path_visibility() { 240 fn filters_visibility() {
258 assert_debug_snapshot!( 241 check(
259 do_reference_completion( 242 r#"
260 r" 243use self::my::<|>;
261 use self::my::<|>; 244
262 245mod my {
263 mod my { 246 struct Bar;
264 struct Bar; 247 pub struct Foo;
265 pub struct Foo; 248 pub use Bar as PublicBar;
266 pub use Bar as PublicBar; 249}
267 } 250"#,
268 " 251 expect![[r#"
269 ), 252 st Foo
270 @r###" 253 st PublicBar
271 [ 254 "#]],
272 CompletionItem {
273 label: "Foo",
274 source_range: 14..14,
275 delete: 14..14,
276 insert: "Foo",
277 kind: Struct,
278 },
279 CompletionItem {
280 label: "PublicBar",
281 source_range: 14..14,
282 delete: 14..14,
283 insert: "PublicBar",
284 kind: Struct,
285 },
286 ]
287 "###
288 ); 255 );
289 } 256 }
290 257
291 #[test] 258 #[test]
292 fn completes_use_item_starting_with_self() { 259 fn completes_use_item_starting_with_self() {
293 assert_debug_snapshot!( 260 check(
294 do_reference_completion( 261 r#"
295 r" 262use self::m::<|>;
296 use self::m::<|>;
297 263
298 mod m { 264mod m { pub struct Bar; }
299 pub struct Bar; 265"#,
300 } 266 expect![[r#"
301 " 267 st Bar
302 ), 268 "#]],
303 @r###"
304 [
305 CompletionItem {
306 label: "Bar",
307 source_range: 13..13,
308 delete: 13..13,
309 insert: "Bar",
310 kind: Struct,
311 },
312 ]
313 "###
314 ); 269 );
315 } 270 }
316 271
317 #[test] 272 #[test]
318 fn completes_use_item_starting_with_crate() { 273 fn completes_use_item_starting_with_crate() {
319 assert_debug_snapshot!( 274 check(
320 do_reference_completion( 275 r#"
321 " 276//- /lib.rs
322 //- /lib.rs 277mod foo;
323 mod foo; 278struct Spam;
324 struct Spam; 279//- /foo.rs
325 //- /foo.rs 280use crate::Sp<|>
326 use crate::Sp<|> 281"#,
327 " 282 expect![[r#"
328 ), 283 st Spam
329 @r###" 284 md foo
330 [ 285 "#]],
331 CompletionItem {
332 label: "Spam",
333 source_range: 11..13,
334 delete: 11..13,
335 insert: "Spam",
336 kind: Struct,
337 },
338 CompletionItem {
339 label: "foo",
340 source_range: 11..13,
341 delete: 11..13,
342 insert: "foo",
343 kind: Module,
344 },
345 ]
346 "###
347 ); 286 );
348 } 287 }
349 288
350 #[test] 289 #[test]
351 fn completes_nested_use_tree() { 290 fn completes_nested_use_tree() {
352 assert_debug_snapshot!( 291 check(
353 do_reference_completion( 292 r#"
354 " 293//- /lib.rs
355 //- /lib.rs 294mod foo;
356 mod foo; 295struct Spam;
357 struct Spam; 296//- /foo.rs
358 //- /foo.rs 297use crate::{Sp<|>};
359 use crate::{Sp<|>}; 298"#,
360 " 299 expect![[r#"
361 ), 300 st Spam
362 @r###" 301 md foo
363 [ 302 "#]],
364 CompletionItem {
365 label: "Spam",
366 source_range: 12..14,
367 delete: 12..14,
368 insert: "Spam",
369 kind: Struct,
370 },
371 CompletionItem {
372 label: "foo",
373 source_range: 12..14,
374 delete: 12..14,
375 insert: "foo",
376 kind: Module,
377 },
378 ]
379 "###
380 ); 303 );
381 } 304 }
382 305
383 #[test] 306 #[test]
384 fn completes_deeply_nested_use_tree() { 307 fn completes_deeply_nested_use_tree() {
385 assert_debug_snapshot!( 308 check(
386 do_reference_completion( 309 r#"
387 " 310//- /lib.rs
388 //- /lib.rs 311mod foo;
389 mod foo; 312pub mod bar {
390 pub mod bar { 313 pub mod baz {
391 pub mod baz { 314 pub struct Spam;
392 pub struct Spam;
393 }
394 }
395 //- /foo.rs
396 use crate::{bar::{baz::Sp<|>}};
397 "
398 ),
399 @r###"
400 [
401 CompletionItem {
402 label: "Spam",
403 source_range: 23..25,
404 delete: 23..25,
405 insert: "Spam",
406 kind: Struct,
407 },
408 ]
409 "###
410 );
411 }
412
413 #[test]
414 fn completes_enum_variant() {
415 assert_debug_snapshot!(
416 do_reference_completion(
417 "
418 //- /lib.rs
419 /// An enum
420 enum E {
421 /// Foo Variant
422 Foo,
423 /// Bar Variant with i32
424 Bar(i32)
425 }
426 fn foo() { let _ = E::<|> }
427 "
428 ),
429 @r###"
430 [
431 CompletionItem {
432 label: "Bar(…)",
433 source_range: 116..116,
434 delete: 116..116,
435 insert: "Bar($0)",
436 kind: EnumVariant,
437 lookup: "Bar",
438 detail: "(i32)",
439 documentation: Documentation(
440 "Bar Variant with i32",
441 ),
442 trigger_call_info: true,
443 },
444 CompletionItem {
445 label: "Foo",
446 source_range: 116..116,
447 delete: 116..116,
448 insert: "Foo",
449 kind: EnumVariant,
450 detail: "()",
451 documentation: Documentation(
452 "Foo Variant",
453 ),
454 },
455 ]
456 "###
457 );
458 }
459
460 #[test]
461 fn completes_enum_variant_with_details() {
462 assert_debug_snapshot!(
463 do_reference_completion(
464 "
465 //- /lib.rs
466 struct S { field: u32 }
467 /// An enum
468 enum E {
469 /// Foo Variant (empty)
470 Foo,
471 /// Bar Variant with i32 and u32
472 Bar(i32, u32),
473 ///
474 S(S),
475 }
476 fn foo() { let _ = E::<|> }
477 "
478 ),
479 @r###"
480 [
481 CompletionItem {
482 label: "Bar(…)",
483 source_range: 180..180,
484 delete: 180..180,
485 insert: "Bar($0)",
486 kind: EnumVariant,
487 lookup: "Bar",
488 detail: "(i32, u32)",
489 documentation: Documentation(
490 "Bar Variant with i32 and u32",
491 ),
492 trigger_call_info: true,
493 },
494 CompletionItem {
495 label: "Foo",
496 source_range: 180..180,
497 delete: 180..180,
498 insert: "Foo",
499 kind: EnumVariant,
500 detail: "()",
501 documentation: Documentation(
502 "Foo Variant (empty)",
503 ),
504 },
505 CompletionItem {
506 label: "S(…)",
507 source_range: 180..180,
508 delete: 180..180,
509 insert: "S($0)",
510 kind: EnumVariant,
511 lookup: "S",
512 detail: "(S)",
513 documentation: Documentation(
514 "",
515 ),
516 trigger_call_info: true,
517 },
518 ]
519 "###
520 );
521 } 315 }
522 316}
523 #[test] 317//- /foo.rs
524 fn completes_struct_associated_method() { 318use crate::{bar::{baz::Sp<|>}};
525 assert_debug_snapshot!( 319"#,
526 do_reference_completion( 320 expect![[r#"
527 " 321 st Spam
528 //- /lib.rs 322 "#]],
529 /// A Struct
530 struct S;
531
532 impl S {
533 /// An associated method
534 fn m() { }
535 }
536
537 fn foo() { let _ = S::<|> }
538 "
539 ),
540 @r###"
541 [
542 CompletionItem {
543 label: "m()",
544 source_range: 102..102,
545 delete: 102..102,
546 insert: "m()$0",
547 kind: Function,
548 lookup: "m",
549 detail: "fn m()",
550 documentation: Documentation(
551 "An associated method",
552 ),
553 },
554 ]
555 "###
556 ); 323 );
557 } 324 }
558 325
559 #[test] 326 #[test]
560 fn completes_struct_associated_method_with_self() { 327 fn completes_enum_variant() {
561 assert_debug_snapshot!( 328 check(
562 do_reference_completion( 329 r#"
563 " 330enum E { Foo, Bar(i32) }
564 //- /lib.rs 331fn foo() { let _ = E::<|> }
565 /// A Struct 332"#,
566 struct S; 333 expect![[r#"
567 334 ev Bar(…) (i32)
568 impl S { 335 ev Foo ()
569 /// An associated method 336 "#]],
570 fn m(&self) { }
571 }
572
573 fn foo() { let _ = S::<|> }
574 "
575 ),
576 @r###"
577 [
578 CompletionItem {
579 label: "m()",
580 source_range: 107..107,
581 delete: 107..107,
582 insert: "m()$0",
583 kind: Method,
584 lookup: "m",
585 detail: "fn m(&self)",
586 documentation: Documentation(
587 "An associated method",
588 ),
589 },
590 ]
591 "###
592 ); 337 );
593 } 338 }
594 339
595 #[test] 340 #[test]
596 fn completes_struct_associated_const() { 341 fn completes_struct_associated_items() {
597 assert_debug_snapshot!( 342 check(
598 do_reference_completion( 343 r#"
599 " 344//- /lib.rs
600 //- /lib.rs 345struct S;
601 /// A Struct 346
602 struct S; 347impl S {
603 348 fn a() {}
604 impl S { 349 fn b(&self) {}
605 /// An associated const 350 const C: i32 = 42;
606 const C: i32 = 42; 351 type T = i32;
607 } 352}
608 353
609 fn foo() { let _ = S::<|> } 354fn foo() { let _ = S::<|> }
610 " 355"#,
611 ), 356 expect![[r#"
612 @r###" 357 ct C const C: i32 = 42;
613 [ 358 ta T type T = i32;
614 CompletionItem { 359 fn a() fn a()
615 label: "C", 360 me b() fn b(&self)
616 source_range: 109..109, 361 "#]],
617 delete: 109..109,
618 insert: "C",
619 kind: Const,
620 detail: "const C: i32 = 42;",
621 documentation: Documentation(
622 "An associated const",
623 ),
624 },
625 ]
626 "###
627 ); 362 );
628 } 363 }
629 364
630 #[test] 365 #[test]
631 fn completes_struct_associated_type() { 366 fn associated_item_visibility() {
632 assert_debug_snapshot!( 367 check(
633 do_reference_completion( 368 r#"
634 " 369struct S;
635 //- /lib.rs
636 /// A Struct
637 struct S;
638
639 impl S {
640 /// An associated type
641 type T = i32;
642 }
643 370
644 fn foo() { let _ = S::<|> } 371mod m {
645 " 372 impl super::S {
646 ), 373 pub(super) fn public_method() { }
647 @r###" 374 fn private_method() { }
648 [ 375 pub(super) type PublicType = u32;
649 CompletionItem { 376 type PrivateType = u32;
650 label: "T", 377 pub(super) const PUBLIC_CONST: u32 = 1;
651 source_range: 103..103, 378 const PRIVATE_CONST: u32 = 1;
652 delete: 103..103,
653 insert: "T",
654 kind: TypeAlias,
655 detail: "type T = i32;",
656 documentation: Documentation(
657 "An associated type",
658 ),
659 },
660 ]
661 "###
662 );
663 } 379 }
380}
664 381
665 #[test] 382fn foo() { let _ = S::<|> }
666 fn associated_item_visibility() { 383"#,
667 assert_debug_snapshot!( 384 expect![[r#"
668 do_reference_completion( 385 ct PUBLIC_CONST pub(super) const PUBLIC_CONST: u32 = 1;
669 " 386 ta PublicType pub(super) type PublicType = u32;
670 //- /lib.rs 387 fn public_method() pub(super) fn public_method()
671 struct S; 388 "#]],
672
673 mod m {
674 impl super::S {
675 pub(super) fn public_method() { }
676 fn private_method() { }
677 pub(super) type PublicType = u32;
678 type PrivateType = u32;
679 pub(super) const PUBLIC_CONST: u32 = 1;
680 const PRIVATE_CONST: u32 = 1;
681 }
682 }
683
684 fn foo() { let _ = S::<|> }
685 "
686 ),
687 @r###"
688 [
689 CompletionItem {
690 label: "PUBLIC_CONST",
691 source_range: 304..304,
692 delete: 304..304,
693 insert: "PUBLIC_CONST",
694 kind: Const,
695 detail: "pub(super) const PUBLIC_CONST: u32 = 1;",
696 },
697 CompletionItem {
698 label: "PublicType",
699 source_range: 304..304,
700 delete: 304..304,
701 insert: "PublicType",
702 kind: TypeAlias,
703 detail: "pub(super) type PublicType = u32;",
704 },
705 CompletionItem {
706 label: "public_method()",
707 source_range: 304..304,
708 delete: 304..304,
709 insert: "public_method()$0",
710 kind: Function,
711 lookup: "public_method",
712 detail: "pub(super) fn public_method()",
713 },
714 ]
715 "###
716 ); 389 );
717 } 390 }
718 391
719 #[test] 392 #[test]
720 fn completes_enum_associated_method() { 393 fn completes_enum_associated_method() {
721 assert_debug_snapshot!( 394 check(
722 do_reference_completion( 395 r#"
723 " 396enum E {};
724 //- /lib.rs 397impl E { fn m() { } }
725 /// An enum 398
726 enum S {}; 399fn foo() { let _ = E::<|> }
727 400 "#,
728 impl S { 401 expect![[r#"
729 /// An associated method 402 fn m() fn m()
730 fn m() { } 403 "#]],
731 }
732
733 fn foo() { let _ = S::<|> }
734 "
735 ),
736 @r###"
737 [
738 CompletionItem {
739 label: "m()",
740 source_range: 102..102,
741 delete: 102..102,
742 insert: "m()$0",
743 kind: Function,
744 lookup: "m",
745 detail: "fn m()",
746 documentation: Documentation(
747 "An associated method",
748 ),
749 },
750 ]
751 "###
752 ); 404 );
753 } 405 }
754 406
755 #[test] 407 #[test]
756 fn completes_union_associated_method() { 408 fn completes_union_associated_method() {
757 assert_debug_snapshot!( 409 check(
758 do_reference_completion( 410 r#"
759 " 411union U {};
760 //- /lib.rs 412impl U { fn m() { } }
761 /// A union 413
762 union U {}; 414fn foo() { let _ = U::<|> }
763 415"#,
764 impl U { 416 expect![[r#"
765 /// An associated method 417 fn m() fn m()
766 fn m() { } 418 "#]],
767 }
768
769 fn foo() { let _ = U::<|> }
770 "
771 ),
772 @r###"
773 [
774 CompletionItem {
775 label: "m()",
776 source_range: 103..103,
777 delete: 103..103,
778 insert: "m()$0",
779 kind: Function,
780 lookup: "m",
781 detail: "fn m()",
782 documentation: Documentation(
783 "An associated method",
784 ),
785 },
786 ]
787 "###
788 ); 419 );
789 } 420 }
790 421
791 #[test] 422 #[test]
792 fn completes_use_paths_across_crates() { 423 fn completes_use_paths_across_crates() {
793 assert_debug_snapshot!( 424 check(
794 do_reference_completion( 425 r#"
795 " 426//- /main.rs
796 //- /main.rs 427use foo::<|>;
797 use foo::<|>; 428
798 429//- /foo/lib.rs
799 //- /foo/lib.rs 430pub mod bar { pub struct S; }
800 pub mod bar { 431"#,
801 pub struct S; 432 expect![[r#"
802 } 433 md bar
803 " 434 "#]],
804 ),
805 @r###"
806 [
807 CompletionItem {
808 label: "bar",
809 source_range: 9..9,
810 delete: 9..9,
811 insert: "bar",
812 kind: Module,
813 },
814 ]
815 "###
816 ); 435 );
817 } 436 }
818 437
819 #[test] 438 #[test]
820 fn completes_trait_associated_method_1() { 439 fn completes_trait_associated_method_1() {
821 assert_debug_snapshot!( 440 check(
822 do_reference_completion( 441 r#"
823 " 442trait Trait { fn m(); }
824 //- /lib.rs
825 trait Trait {
826 /// A trait method
827 fn m();
828 }
829 443
830 fn foo() { let _ = Trait::<|> } 444fn foo() { let _ = Trait::<|> }
831 " 445"#,
832 ), 446 expect![[r#"
833 @r###" 447 fn m() fn m()
834 [ 448 "#]],
835 CompletionItem {
836 label: "m()",
837 source_range: 74..74,
838 delete: 74..74,
839 insert: "m()$0",
840 kind: Function,
841 lookup: "m",
842 detail: "fn m()",
843 documentation: Documentation(
844 "A trait method",
845 ),
846 },
847 ]
848 "###
849 ); 449 );
850 } 450 }
851 451
852 #[test] 452 #[test]
853 fn completes_trait_associated_method_2() { 453 fn completes_trait_associated_method_2() {
854 assert_debug_snapshot!( 454 check(
855 do_reference_completion( 455 r#"
856 " 456trait Trait { fn m(); }
857 //- /lib.rs 457
858 trait Trait { 458struct S;
859 /// A trait method 459impl Trait for S {}
860 fn m();
861 }
862 460
863 struct S; 461fn foo() { let _ = S::<|> }
864 impl Trait for S {} 462"#,
865 463 expect![[r#"
866 fn foo() { let _ = S::<|> } 464 fn m() fn m()
867 " 465 "#]],
868 ),
869 @r###"
870 [
871 CompletionItem {
872 label: "m()",
873 source_range: 101..101,
874 delete: 101..101,
875 insert: "m()$0",
876 kind: Function,
877 lookup: "m",
878 detail: "fn m()",
879 documentation: Documentation(
880 "A trait method",
881 ),
882 },
883 ]
884 "###
885 ); 466 );
886 } 467 }
887 468
888 #[test] 469 #[test]
889 fn completes_trait_associated_method_3() { 470 fn completes_trait_associated_method_3() {
890 assert_debug_snapshot!( 471 check(
891 do_reference_completion( 472 r#"
892 " 473trait Trait { fn m(); }
893 //- /lib.rs
894 trait Trait {
895 /// A trait method
896 fn m();
897 }
898 474
899 struct S; 475struct S;
900 impl Trait for S {} 476impl Trait for S {}
901 477
902 fn foo() { let _ = <S as Trait>::<|> } 478fn foo() { let _ = <S as Trait>::<|> }
903 " 479"#,
904 ), 480 expect![[r#"
905 @r###" 481 fn m() fn m()
906 [ 482 "#]],
907 CompletionItem {
908 label: "m()",
909 source_range: 112..112,
910 delete: 112..112,
911 insert: "m()$0",
912 kind: Function,
913 lookup: "m",
914 detail: "fn m()",
915 documentation: Documentation(
916 "A trait method",
917 ),
918 },
919 ]
920 "###
921 ); 483 );
922 } 484 }
923 485
924 #[test] 486 #[test]
925 fn completes_ty_param_assoc_ty() { 487 fn completes_ty_param_assoc_ty() {
926 assert_debug_snapshot!( 488 check(
927 do_reference_completion( 489 r#"
928 " 490trait Super {
929 //- /lib.rs 491 type Ty;
930 trait Super { 492 const CONST: u8;
931 type Ty; 493 fn func() {}
932 const CONST: u8; 494 fn method(&self) {}
933 fn func() {} 495}
934 fn method(&self) {}
935 }
936 496
937 trait Sub: Super { 497trait Sub: Super {
938 type SubTy; 498 type SubTy;
939 const C2: (); 499 const C2: ();
940 fn subfunc() {} 500 fn subfunc() {}
941 fn submethod(&self) {} 501 fn submethod(&self) {}
942 } 502}
943 503
944 fn foo<T: Sub>() { 504fn foo<T: Sub>() { T::<|> }
945 T::<|> 505"#,
946 } 506 expect![[r#"
947 " 507 ct C2 const C2: ();
948 ), 508 ct CONST const CONST: u8;
949 @r###" 509 ta SubTy type SubTy;
950 [ 510 ta Ty type Ty;
951 CompletionItem { 511 fn func() fn func()
952 label: "C2", 512 me method() fn method(&self)
953 source_range: 221..221, 513 fn subfunc() fn subfunc()
954 delete: 221..221, 514 me submethod() fn submethod(&self)
955 insert: "C2", 515 "#]],
956 kind: Const,
957 detail: "const C2: ();",
958 },
959 CompletionItem {
960 label: "CONST",
961 source_range: 221..221,
962 delete: 221..221,
963 insert: "CONST",
964 kind: Const,
965 detail: "const CONST: u8;",
966 },
967 CompletionItem {
968 label: "SubTy",
969 source_range: 221..221,
970 delete: 221..221,
971 insert: "SubTy",
972 kind: TypeAlias,
973 detail: "type SubTy;",
974 },
975 CompletionItem {
976 label: "Ty",
977 source_range: 221..221,
978 delete: 221..221,
979 insert: "Ty",
980 kind: TypeAlias,
981 detail: "type Ty;",
982 },
983 CompletionItem {
984 label: "func()",
985 source_range: 221..221,
986 delete: 221..221,
987 insert: "func()$0",
988 kind: Function,
989 lookup: "func",
990 detail: "fn func()",
991 },
992 CompletionItem {
993 label: "method()",
994 source_range: 221..221,
995 delete: 221..221,
996 insert: "method()$0",
997 kind: Method,
998 lookup: "method",
999 detail: "fn method(&self)",
1000 },
1001 CompletionItem {
1002 label: "subfunc()",
1003 source_range: 221..221,
1004 delete: 221..221,
1005 insert: "subfunc()$0",
1006 kind: Function,
1007 lookup: "subfunc",
1008 detail: "fn subfunc()",
1009 },
1010 CompletionItem {
1011 label: "submethod()",
1012 source_range: 221..221,
1013 delete: 221..221,
1014 insert: "submethod()$0",
1015 kind: Method,
1016 lookup: "submethod",
1017 detail: "fn submethod(&self)",
1018 },
1019 ]
1020 "###
1021 ); 516 );
1022 } 517 }
1023 518
1024 #[test] 519 #[test]
1025 fn completes_self_param_assoc_ty() { 520 fn completes_self_param_assoc_ty() {
1026 assert_debug_snapshot!( 521 check(
1027 do_reference_completion( 522 r#"
1028 " 523trait Super {
1029 //- /lib.rs 524 type Ty;
1030 trait Super { 525 const CONST: u8 = 0;
1031 type Ty; 526 fn func() {}
1032 const CONST: u8 = 0; 527 fn method(&self) {}
1033 fn func() {} 528}
1034 fn method(&self) {}
1035 }
1036 529
1037 trait Sub: Super { 530trait Sub: Super {
1038 type SubTy; 531 type SubTy;
1039 const C2: () = (); 532 const C2: () = ();
1040 fn subfunc() {} 533 fn subfunc() {}
1041 fn submethod(&self) {} 534 fn submethod(&self) {}
1042 } 535}
1043 536
1044 struct Wrap<T>(T); 537struct Wrap<T>(T);
1045 impl<T> Super for Wrap<T> {} 538impl<T> Super for Wrap<T> {}
1046 impl<T> Sub for Wrap<T> { 539impl<T> Sub for Wrap<T> {
1047 fn subfunc() { 540 fn subfunc() {
1048 // Should be able to assume `Self: Sub + Super` 541 // Should be able to assume `Self: Sub + Super`
1049 Self::<|> 542 Self::<|>
1050 } 543 }
1051 } 544}
1052 " 545"#,
1053 ), 546 expect![[r#"
1054 @r###" 547 ct C2 const C2: () = ();
1055 [ 548 ct CONST const CONST: u8 = 0;
1056 CompletionItem { 549 ta SubTy type SubTy;
1057 label: "C2", 550 ta Ty type Ty;
1058 source_range: 367..367, 551 fn func() fn func()
1059 delete: 367..367, 552 me method() fn method(&self)
1060 insert: "C2", 553 fn subfunc() fn subfunc()
1061 kind: Const, 554 me submethod() fn submethod(&self)
1062 detail: "const C2: () = ();", 555 "#]],
1063 },
1064 CompletionItem {
1065 label: "CONST",
1066 source_range: 367..367,
1067 delete: 367..367,
1068 insert: "CONST",
1069 kind: Const,
1070 detail: "const CONST: u8 = 0;",
1071 },
1072 CompletionItem {
1073 label: "SubTy",
1074 source_range: 367..367,
1075 delete: 367..367,
1076 insert: "SubTy",
1077 kind: TypeAlias,
1078 detail: "type SubTy;",
1079 },
1080 CompletionItem {
1081 label: "Ty",
1082 source_range: 367..367,
1083 delete: 367..367,
1084 insert: "Ty",
1085 kind: TypeAlias,
1086 detail: "type Ty;",
1087 },
1088 CompletionItem {
1089 label: "func()",
1090 source_range: 367..367,
1091 delete: 367..367,
1092 insert: "func()$0",
1093 kind: Function,
1094 lookup: "func",
1095 detail: "fn func()",
1096 },
1097 CompletionItem {
1098 label: "method()",
1099 source_range: 367..367,
1100 delete: 367..367,
1101 insert: "method()$0",
1102 kind: Method,
1103 lookup: "method",
1104 detail: "fn method(&self)",
1105 },
1106 CompletionItem {
1107 label: "subfunc()",
1108 source_range: 367..367,
1109 delete: 367..367,
1110 insert: "subfunc()$0",
1111 kind: Function,
1112 lookup: "subfunc",
1113 detail: "fn subfunc()",
1114 },
1115 CompletionItem {
1116 label: "submethod()",
1117 source_range: 367..367,
1118 delete: 367..367,
1119 insert: "submethod()$0",
1120 kind: Method,
1121 lookup: "submethod",
1122 detail: "fn submethod(&self)",
1123 },
1124 ]
1125 "###
1126 ); 556 );
1127 } 557 }
1128 558
1129 #[test] 559 #[test]
1130 fn completes_type_alias() { 560 fn completes_type_alias() {
1131 assert_debug_snapshot!( 561 check(
1132 do_reference_completion( 562 r#"
1133 " 563struct S;
1134 struct S; 564impl S { fn foo() {} }
1135 impl S { fn foo() {} } 565type T = S;
1136 type T = S; 566impl T { fn bar() {} }
1137 impl T { fn bar() {} } 567
1138 568fn main() { T::<|>; }
1139 fn main() { 569"#,
1140 T::<|>; 570 expect![[r#"
1141 } 571 fn bar() fn bar()
1142 " 572 fn foo() fn foo()
1143 ), 573 "#]],
1144 @r###"
1145 [
1146 CompletionItem {
1147 label: "bar()",
1148 source_range: 88..88,
1149 delete: 88..88,
1150 insert: "bar()$0",
1151 kind: Function,
1152 lookup: "bar",
1153 detail: "fn bar()",
1154 },
1155 CompletionItem {
1156 label: "foo()",
1157 source_range: 88..88,
1158 delete: 88..88,
1159 insert: "foo()$0",
1160 kind: Function,
1161 lookup: "foo",
1162 detail: "fn foo()",
1163 },
1164 ]
1165 "###
1166 ); 574 );
1167 } 575 }
1168 576
1169 #[test] 577 #[test]
1170 fn completes_qualified_macros() { 578 fn completes_qualified_macros() {
1171 assert_debug_snapshot!( 579 check(
1172 do_reference_completion( 580 r#"
1173 " 581#[macro_export]
1174 #[macro_export] 582macro_rules! foo { () => {} }
1175 macro_rules! foo { 583
1176 () => {} 584fn main() { let _ = crate::<|> }
1177 } 585 "#,
1178 586 expect![[r##"
1179 fn main() { 587 ma foo!(…) #[macro_export]
1180 let _ = crate::<|> 588 macro_rules! foo
1181 } 589 fn main() fn main()
1182 " 590 "##]],
1183 ),
1184 @r###"
1185 [
1186 CompletionItem {
1187 label: "foo!(…)",
1188 source_range: 82..82,
1189 delete: 82..82,
1190 insert: "foo!($0)",
1191 kind: Macro,
1192 lookup: "foo!",
1193 detail: "#[macro_export]\nmacro_rules! foo",
1194 },
1195 CompletionItem {
1196 label: "main()",
1197 source_range: 82..82,
1198 delete: 82..82,
1199 insert: "main()$0",
1200 kind: Function,
1201 lookup: "main",
1202 detail: "fn main()",
1203 },
1204 ]
1205 "###
1206 ); 591 );
1207 } 592 }
1208 593
1209 #[test] 594 #[test]
1210 fn test_super_super_completion() { 595 fn test_super_super_completion() {
1211 assert_debug_snapshot!( 596 check(
1212 do_reference_completion( 597 r#"
1213 r" 598mod a {
1214 mod a { 599 const A: usize = 0;
1215 const A: usize = 0; 600 mod b {
1216 601 const B: usize = 0;
1217 mod b { 602 mod c { use super::super::<|> }
1218 const B: usize = 0; 603 }
1219 604}
1220 mod c { 605"#,
1221 use super::super::<|> 606 expect![[r#"
1222 } 607 ct A
1223 } 608 md b
1224 } 609 "#]],
1225 ",
1226 ),
1227 @r###"
1228 [
1229 CompletionItem {
1230 label: "A",
1231 source_range: 120..120,
1232 delete: 120..120,
1233 insert: "A",
1234 kind: Const,
1235 },
1236 CompletionItem {
1237 label: "b",
1238 source_range: 120..120,
1239 delete: 120..120,
1240 insert: "b",
1241 kind: Module,
1242 },
1243 ]
1244 "###
1245 ); 610 );
1246 } 611 }
1247 612
1248 #[test] 613 #[test]
1249 fn completes_reexported_items_under_correct_name() { 614 fn completes_reexported_items_under_correct_name() {
1250 assert_debug_snapshot!( 615 check(
1251 do_reference_completion( 616 r#"
1252 r" 617fn foo() { self::m::<|> }
1253 fn foo() {
1254 self::m::<|>
1255 }
1256 618
1257 mod m { 619mod m {
1258 pub use super::p::wrong_fn as right_fn; 620 pub use super::p::wrong_fn as right_fn;
1259 pub use super::p::WRONG_CONST as RIGHT_CONST; 621 pub use super::p::WRONG_CONST as RIGHT_CONST;
1260 pub use super::p::WrongType as RightType; 622 pub use super::p::WrongType as RightType;
1261 } 623}
1262 mod p { 624mod p {
1263 fn wrong_fn() {} 625 fn wrong_fn() {}
1264 const WRONG_CONST: u32 = 1; 626 const WRONG_CONST: u32 = 1;
1265 struct WrongType {}; 627 struct WrongType {};
1266 } 628}
1267 " 629"#,
1268 ), 630 expect![[r#"
1269 @r###" 631 ct RIGHT_CONST
1270 [ 632 st RightType
1271 CompletionItem { 633 fn right_fn() fn wrong_fn()
1272 label: "RIGHT_CONST", 634 "#]],
1273 source_range: 24..24, 635 );
1274 delete: 24..24, 636
1275 insert: "RIGHT_CONST", 637 check_edit(
1276 kind: Const, 638 "RightType",
1277 }, 639 r#"
1278 CompletionItem { 640fn foo() { self::m::<|> }
1279 label: "RightType", 641
1280 source_range: 24..24, 642mod m {
1281 delete: 24..24, 643 pub use super::p::wrong_fn as right_fn;
1282 insert: "RightType", 644 pub use super::p::WRONG_CONST as RIGHT_CONST;
1283 kind: Struct, 645 pub use super::p::WrongType as RightType;
1284 }, 646}
1285 CompletionItem { 647mod p {
1286 label: "right_fn()", 648 fn wrong_fn() {}
1287 source_range: 24..24, 649 const WRONG_CONST: u32 = 1;
1288 delete: 24..24, 650 struct WrongType {};
1289 insert: "right_fn()$0", 651}
1290 kind: Function, 652"#,
1291 lookup: "right_fn", 653 r#"
1292 detail: "fn wrong_fn()", 654fn foo() { self::m::RightType }
1293 }, 655
1294 ] 656mod m {
1295 "### 657 pub use super::p::wrong_fn as right_fn;
658 pub use super::p::WRONG_CONST as RIGHT_CONST;
659 pub use super::p::WrongType as RightType;
660}
661mod p {
662 fn wrong_fn() {}
663 const WRONG_CONST: u32 = 1;
664 struct WrongType {};
665}
666"#,
1296 ); 667 );
1297 } 668 }
1298 669
1299 #[test] 670 #[test]
1300 fn completes_in_simple_macro_call() { 671 fn completes_in_simple_macro_call() {
1301 let completions = do_reference_completion( 672 check(
1302 r#" 673 r#"
1303 macro_rules! m { ($e:expr) => { $e } } 674macro_rules! m { ($e:expr) => { $e } }
1304 fn main() { m!(self::f<|>); } 675fn main() { m!(self::f<|>); }
1305 fn foo() {} 676fn foo() {}
1306 "#, 677"#,
678 expect![[r#"
679 fn foo() fn foo()
680 fn main() fn main()
681 "#]],
1307 ); 682 );
1308 assert_debug_snapshot!(completions, @r###"
1309 [
1310 CompletionItem {
1311 label: "foo()",
1312 source_range: 60..61,
1313 delete: 60..61,
1314 insert: "foo()$0",
1315 kind: Function,
1316 lookup: "foo",
1317 detail: "fn foo()",
1318 },
1319 CompletionItem {
1320 label: "main()",
1321 source_range: 60..61,
1322 delete: 60..61,
1323 insert: "main()$0",
1324 kind: Function,
1325 lookup: "main",
1326 detail: "fn main()",
1327 },
1328 ]
1329 "###);
1330 } 683 }
1331 684
1332 #[test] 685 #[test]
1333 fn function_mod_share_name() { 686 fn function_mod_share_name() {
1334 assert_debug_snapshot!( 687 check(
1335 do_reference_completion( 688 r#"
1336 r" 689fn foo() { self::m::<|> }
1337 fn foo() {
1338 self::m::<|>
1339 }
1340 690
1341 mod m { 691mod m {
1342 pub mod z {} 692 pub mod z {}
1343 pub fn z() {} 693 pub fn z() {}
1344 } 694}
1345 ", 695"#,
1346 ), 696 expect![[r#"
1347 @r###" 697 md z
1348 [ 698 fn z() pub fn z()
1349 CompletionItem { 699 "#]],
1350 label: "z",
1351 source_range: 24..24,
1352 delete: 24..24,
1353 insert: "z",
1354 kind: Module,
1355 },
1356 CompletionItem {
1357 label: "z()",
1358 source_range: 24..24,
1359 delete: 24..24,
1360 insert: "z()$0",
1361 kind: Function,
1362 lookup: "z",
1363 detail: "pub fn z()",
1364 },
1365 ]
1366 "###
1367 ); 700 );
1368 } 701 }
1369 702
1370 #[test] 703 #[test]
1371 fn completes_hashmap_new() { 704 fn completes_hashmap_new() {
1372 assert_debug_snapshot!( 705 check(
1373 do_reference_completion( 706 r#"
1374 r" 707struct RandomState;
1375 struct RandomState; 708struct HashMap<K, V, S = RandomState> {}
1376 struct HashMap<K, V, S = RandomState> {} 709
1377 710impl<K, V> HashMap<K, V, RandomState> {
1378 impl<K, V> HashMap<K, V, RandomState> { 711 pub fn new() -> HashMap<K, V, RandomState> { }
1379 pub fn new() -> HashMap<K, V, RandomState> { } 712}
1380 } 713fn foo() {
1381 fn foo() { 714 HashMap::<|>
1382 HashMap::<|> 715}
1383 } 716"#,
1384 " 717 expect![[r#"
1385 ), 718 fn new() pub fn new() -> HashMap<K, V, RandomState>
1386 @r###" 719 "#]],
1387 [
1388 CompletionItem {
1389 label: "new()",
1390 source_range: 179..179,
1391 delete: 179..179,
1392 insert: "new()$0",
1393 kind: Function,
1394 lookup: "new",
1395 detail: "pub fn new() -> HashMap<K, V, RandomState>",
1396 },
1397 ]
1398 "###
1399 ); 720 );
1400 } 721 }
1401 722
1402 #[test] 723 #[test]
1403 fn dont_complete_attr() { 724 fn dont_complete_attr() {
1404 assert_debug_snapshot!( 725 check(
1405 do_reference_completion( 726 r#"
1406 r" 727mod foo { pub struct Foo; }
1407 mod foo { pub struct Foo; } 728#[foo::<|>]
1408 #[foo::<|>] 729fn f() {}
1409 fn f() {} 730"#,
1410 " 731 expect![[""]],
1411 ), 732 );
1412 @r###"[]"###
1413 )
1414 } 733 }
1415} 734}
diff --git a/crates/ra_ide/src/completion/complete_snippet.rs b/crates/ra_ide/src/completion/complete_snippet.rs
index 52aaa70f0..28d8f7876 100644
--- a/crates/ra_ide/src/completion/complete_snippet.rs
+++ b/crates/ra_ide/src/completion/complete_snippet.rs
@@ -70,95 +70,47 @@ fn ${1:feature}() {
70 70
71#[cfg(test)] 71#[cfg(test)]
72mod tests { 72mod tests {
73 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; 73 use expect::{expect, Expect};
74 use insta::assert_debug_snapshot;
75 74
76 fn do_snippet_completion(code: &str) -> Vec<CompletionItem> { 75 use crate::completion::{test_utils::completion_list, CompletionKind};
77 do_completion(code, CompletionKind::Snippet) 76
77 fn check(ra_fixture: &str, expect: Expect) {
78 let actual = completion_list(ra_fixture, CompletionKind::Snippet);
79 expect.assert_eq(&actual)
78 } 80 }
79 81
80 #[test] 82 #[test]
81 fn completes_snippets_in_expressions() { 83 fn completes_snippets_in_expressions() {
82 assert_debug_snapshot!( 84 check(
83 do_snippet_completion(r"fn foo(x: i32) { <|> }"), 85 r#"fn foo(x: i32) { <|> }"#,
84 @r###" 86 expect![[r#"
85 [ 87 sn pd
86 CompletionItem { 88 sn ppd
87 label: "pd", 89 "#]],
88 source_range: 17..17, 90 );
89 delete: 17..17,
90 insert: "eprintln!(\"$0 = {:?}\", $0);",
91 kind: Snippet,
92 },
93 CompletionItem {
94 label: "ppd",
95 source_range: 17..17,
96 delete: 17..17,
97 insert: "eprintln!(\"$0 = {:#?}\", $0);",
98 kind: Snippet,
99 },
100 ]
101 "###
102 );
103 } 91 }
104 92
105 #[test] 93 #[test]
106 fn should_not_complete_snippets_in_path() { 94 fn should_not_complete_snippets_in_path() {
107 assert_debug_snapshot!( 95 check(r#"fn foo(x: i32) { ::foo<|> }"#, expect![[""]]);
108 do_snippet_completion(r"fn foo(x: i32) { ::foo<|> }"), 96 check(r#"fn foo(x: i32) { ::<|> }"#, expect![[""]]);
109 @"[]"
110 );
111 assert_debug_snapshot!(
112 do_snippet_completion(r"fn foo(x: i32) { ::<|> }"),
113 @"[]"
114 );
115 } 97 }
116 98
117 #[test] 99 #[test]
118 fn completes_snippets_in_items() { 100 fn completes_snippets_in_items() {
119 assert_debug_snapshot!( 101 check(
120 do_snippet_completion( 102 r#"
121 r" 103#[cfg(test)]
122 #[cfg(test)] 104mod tests {
123 mod tests { 105 <|>
124 <|> 106}
125 } 107"#,
126 " 108 expect![[r#"
127 ), 109 sn Test function
128 @r###" 110 sn Test module
129 [ 111 sn macro_rules
130 CompletionItem { 112 sn pub(crate)
131 label: "Test function", 113 "#]],
132 source_range: 29..29, 114 )
133 delete: 29..29,
134 insert: "#[test]\nfn ${1:feature}() {\n $0\n}",
135 kind: Snippet,
136 lookup: "tfn",
137 },
138 CompletionItem {
139 label: "Test module",
140 source_range: 29..29,
141 delete: 29..29,
142 insert: "#[cfg(test)]\nmod tests {\n use super::*;\n\n #[test]\n fn ${1:test_name}() {\n $0\n }\n}",
143 kind: Snippet,
144 lookup: "tmod",
145 },
146 CompletionItem {
147 label: "macro_rules",
148 source_range: 29..29,
149 delete: 29..29,
150 insert: "macro_rules! $1 {\n\t($2) => {\n\t\t$0\n\t};\n}",
151 kind: Snippet,
152 },
153 CompletionItem {
154 label: "pub(crate)",
155 source_range: 29..29,
156 delete: 29..29,
157 insert: "pub(crate) $0",
158 kind: Snippet,
159 },
160 ]
161 "###
162 );
163 } 115 }
164} 116}
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 946bbef7c..bfa7e08be 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -683,6 +683,57 @@ impl S {
683 }, 683 },
684 ] 684 ]
685 "#]], 685 "#]],
686 );
687
688 check(
689 r#"
690use self::my<|>;
691
692/// mod docs
693mod my { }
694
695/// enum docs
696enum E {
697 /// variant docs
698 V
699}
700use self::E::*;
701"#,
702 expect![[r#"
703 [
704 CompletionItem {
705 label: "E",
706 source_range: 10..12,
707 delete: 10..12,
708 insert: "E",
709 kind: Enum,
710 documentation: Documentation(
711 "enum docs",
712 ),
713 },
714 CompletionItem {
715 label: "V",
716 source_range: 10..12,
717 delete: 10..12,
718 insert: "V",
719 kind: EnumVariant,
720 detail: "()",
721 documentation: Documentation(
722 "variant docs",
723 ),
724 },
725 CompletionItem {
726 label: "my",
727 source_range: 10..12,
728 delete: 10..12,
729 insert: "my",
730 kind: Module,
731 documentation: Documentation(
732 "mod docs",
733 ),
734 },
735 ]
736 "#]],
686 ) 737 )
687 } 738 }
688 739
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs
index cbae1da85..c2be23697 100644
--- a/crates/ra_ide/src/completion/test_utils.rs
+++ b/crates/ra_ide/src/completion/test_utils.rs
@@ -43,12 +43,21 @@ pub(crate) fn completion_list_with_config(
43 .filter(|c| c.completion_kind == kind) 43 .filter(|c| c.completion_kind == kind)
44 .collect(); 44 .collect();
45 kind_completions.sort_by_key(|c| c.label().to_owned()); 45 kind_completions.sort_by_key(|c| c.label().to_owned());
46 let label_width = kind_completions
47 .iter()
48 .map(|it| monospace_width(it.label()))
49 .max()
50 .unwrap_or_default()
51 .min(16);
46 kind_completions 52 kind_completions
47 .into_iter() 53 .into_iter()
48 .map(|it| { 54 .map(|it| {
49 let mut buf = format!("{} {}", it.kind().unwrap().tag(), it.label()); 55 let tag = it.kind().unwrap().tag();
56 let var_name = format!("{} {}", tag, it.label());
57 let mut buf = var_name;
50 if let Some(detail) = it.detail() { 58 if let Some(detail) = it.detail() {
51 format_to!(buf, " {}", detail); 59 let width = label_width.saturating_sub(monospace_width(it.label()));
60 format_to!(buf, "{:width$} {}", "", detail, width = width);
52 } 61 }
53 format_to!(buf, "\n"); 62 format_to!(buf, "\n");
54 buf 63 buf
@@ -56,6 +65,10 @@ pub(crate) fn completion_list_with_config(
56 .collect() 65 .collect()
57} 66}
58 67
68fn monospace_width(s: &str) -> usize {
69 s.chars().count()
70}
71
59pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) { 72pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
60 check_edit_with_config(what, ra_fixture_before, ra_fixture_after, &CompletionConfig::default()) 73 check_edit_with_config(what, ra_fixture_before, ra_fixture_after, &CompletionConfig::default())
61} 74}