aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r--crates/ra_ide/src/completion/complete_unqualified_path.rs1598
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs19
-rw-r--r--crates/ra_ide/src/completion/completion_item.rs2
-rw-r--r--crates/ra_ide/src/completion/presentation.rs9
4 files changed, 414 insertions, 1214 deletions
diff --git a/crates/ra_ide/src/completion/complete_unqualified_path.rs b/crates/ra_ide/src/completion/complete_unqualified_path.rs
index 790179e5b..72ff82e66 100644
--- a/crates/ra_ide/src/completion/complete_unqualified_path.rs
+++ b/crates/ra_ide/src/completion/complete_unqualified_path.rs
@@ -64,1370 +64,578 @@ fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &T
64 64
65#[cfg(test)] 65#[cfg(test)]
66mod tests { 66mod tests {
67 use insta::assert_debug_snapshot; 67 use expect::{expect, Expect};
68 use test_utils::mark; 68 use test_utils::mark;
69 69
70 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; 70 use crate::completion::{
71 test_utils::{check_edit, completion_list},
72 CompletionKind,
73 };
71 74
72 fn do_reference_completion(ra_fixture: &str) -> Vec<CompletionItem> { 75 fn check(ra_fixture: &str, expect: Expect) {
73 do_completion(ra_fixture, CompletionKind::Reference) 76 let actual = completion_list(ra_fixture, CompletionKind::Reference);
77 expect.assert_eq(&actual)
74 } 78 }
75 79
76 #[test] 80 #[test]
77 fn self_fulfilling_completion() { 81 fn self_fulfilling_completion() {
78 mark::check!(self_fulfilling_completion); 82 mark::check!(self_fulfilling_completion);
79 assert_debug_snapshot!( 83 check(
80 do_reference_completion( 84 r#"
81 r#" 85use foo<|>
82 use foo<|> 86use std::collections;
83 use std::collections; 87"#,
84 "#, 88 expect![[r#"
85 ), 89 ?? collections
86 @r###" 90 "#]],
87 [
88 CompletionItem {
89 label: "collections",
90 source_range: 4..7,
91 delete: 4..7,
92 insert: "collections",
93 },
94 ]
95 "###
96 ); 91 );
97 } 92 }
98 93
99 #[test] 94 #[test]
100 fn bind_pat_and_path_ignore_at() { 95 fn bind_pat_and_path_ignore_at() {
101 assert_debug_snapshot!( 96 check(
102 do_reference_completion( 97 r#"
103 r" 98enum Enum { A, B }
104 enum Enum { 99fn quux(x: Option<Enum>) {
105 A, 100 match x {
106 B, 101 None => (),
107 } 102 Some(en<|> @ Enum::A) => (),
108 fn quux(x: Option<Enum>) { 103 }
109 match x { 104}
110 None => (), 105"#,
111 Some(en<|> @ Enum::A) => (), 106 expect![[""]],
112 }
113 }
114 "
115 ),
116 @"[]"
117 ); 107 );
118 } 108 }
119 109
120 #[test] 110 #[test]
121 fn bind_pat_and_path_ignore_ref() { 111 fn bind_pat_and_path_ignore_ref() {
122 assert_debug_snapshot!( 112 check(
123 do_reference_completion( 113 r#"
124 r" 114enum Enum { A, B }
125 enum Enum { 115fn quux(x: Option<Enum>) {
126 A, 116 match x {
127 B, 117 None => (),
128 } 118 Some(ref en<|>) => (),
129 fn quux(x: Option<Enum>) { 119 }
130 match x { 120}
131 None => (), 121"#,
132 Some(ref en<|>) => (), 122 expect![[""]],
133 }
134 }
135 "
136 ),
137 @r###"[]"###
138 ); 123 );
139 } 124 }
140 125
141 #[test] 126 #[test]
142 fn bind_pat_and_path() { 127 fn bind_pat_and_path() {
143 assert_debug_snapshot!( 128 check(
144 do_reference_completion( 129 r#"
145 r" 130enum Enum { A, B }
146 enum Enum { 131fn quux(x: Option<Enum>) {
147 A, 132 match x {
148 B, 133 None => (),
149 } 134 Some(En<|>) => (),
150 fn quux(x: Option<Enum>) { 135 }
151 match x { 136}
152 None => (), 137"#,
153 Some(En<|>) => (), 138 expect![[r#"
154 } 139 en Enum
155 } 140 "#]],
156 "
157 ),
158 @r###"
159 [
160 CompletionItem {
161 label: "Enum",
162 source_range: 102..104,
163 delete: 102..104,
164 insert: "Enum",
165 kind: Enum,
166 },
167 ]
168 "###
169 ); 141 );
170 } 142 }
171 143
172 #[test] 144 #[test]
173 fn completes_bindings_from_let() { 145 fn completes_bindings_from_let() {
174 assert_debug_snapshot!( 146 check(
175 do_reference_completion( 147 r#"
176 r" 148fn quux(x: i32) {
177 fn quux(x: i32) { 149 let y = 92;
178 let y = 92; 150 1 + <|>;
179 1 + <|>; 151 let z = ();
180 let z = (); 152}
181 } 153"#,
182 " 154 expect![[r#"
183 ), 155 fn quux(…) fn quux(x: i32)
184 @r###" 156 bn x i32
185 [ 157 bn y i32
186 CompletionItem { 158 "#]],
187 label: "quux(…)",
188 source_range: 42..42,
189 delete: 42..42,
190 insert: "quux(${1:x})$0",
191 kind: Function,
192 lookup: "quux",
193 detail: "fn quux(x: i32)",
194 trigger_call_info: true,
195 },
196 CompletionItem {
197 label: "x",
198 source_range: 42..42,
199 delete: 42..42,
200 insert: "x",
201 kind: Binding,
202 detail: "i32",
203 },
204 CompletionItem {
205 label: "y",
206 source_range: 42..42,
207 delete: 42..42,
208 insert: "y",
209 kind: Binding,
210 detail: "i32",
211 },
212 ]
213 "###
214 ); 159 );
215 } 160 }
216 161
217 #[test] 162 #[test]
218 fn completes_bindings_from_if_let() { 163 fn completes_bindings_from_if_let() {
219 assert_debug_snapshot!( 164 check(
220 do_reference_completion( 165 r#"
221 r" 166fn quux() {
222 fn quux() { 167 if let Some(x) = foo() {
223 if let Some(x) = foo() { 168 let y = 92;
224 let y = 92; 169 };
225 }; 170 if let Some(a) = bar() {
226 if let Some(a) = bar() { 171 let b = 62;
227 let b = 62; 172 1 + <|>
228 1 + <|> 173 }
229 } 174}
230 } 175"#,
231 " 176 expect![[r#"
232 ), 177 bn a
233 @r###" 178 bn b i32
234 [ 179 fn quux() fn quux()
235 CompletionItem { 180 "#]],
236 label: "a",
237 source_range: 129..129,
238 delete: 129..129,
239 insert: "a",
240 kind: Binding,
241 },
242 CompletionItem {
243 label: "b",
244 source_range: 129..129,
245 delete: 129..129,
246 insert: "b",
247 kind: Binding,
248 detail: "i32",
249 },
250 CompletionItem {
251 label: "quux()",
252 source_range: 129..129,
253 delete: 129..129,
254 insert: "quux()$0",
255 kind: Function,
256 lookup: "quux",
257 detail: "fn quux()",
258 },
259 ]
260 "###
261 ); 181 );
262 } 182 }
263 183
264 #[test] 184 #[test]
265 fn completes_bindings_from_for() { 185 fn completes_bindings_from_for() {
266 assert_debug_snapshot!( 186 check(
267 do_reference_completion( 187 r#"
268 r" 188fn quux() {
269 fn quux() { 189 for x in &[1, 2, 3] { <|> }
270 for x in &[1, 2, 3] { 190}
271 <|> 191"#,
272 } 192 expect![[r#"
273 } 193 fn quux() fn quux()
274 " 194 bn x
275 ), 195 "#]],
276 @r###"
277 [
278 CompletionItem {
279 label: "quux()",
280 source_range: 46..46,
281 delete: 46..46,
282 insert: "quux()$0",
283 kind: Function,
284 lookup: "quux",
285 detail: "fn quux()",
286 },
287 CompletionItem {
288 label: "x",
289 source_range: 46..46,
290 delete: 46..46,
291 insert: "x",
292 kind: Binding,
293 },
294 ]
295 "###
296 ); 196 );
297 } 197 }
298 198
299 #[test] 199 #[test]
300 fn completes_bindings_from_for_with_in_prefix() { 200 fn completes_if_prefix_is_keyword() {
301 mark::check!(completes_bindings_from_for_with_in_prefix); 201 mark::check!(completes_if_prefix_is_keyword);
302 assert_debug_snapshot!( 202 check_edit(
303 do_reference_completion( 203 "wherewolf",
304 r" 204 r#"
305 fn test() { 205fn main() {
306 for index in &[1, 2, 3] { 206 let wherewolf = 92;
307 let t = in<|> 207 drop(where<|>)
308 } 208}
309 } 209"#,
310 " 210 r#"
311 ), 211fn main() {
312 @r###" 212 let wherewolf = 92;
313 [ 213 drop(wherewolf)
314 CompletionItem { 214}
315 label: "index", 215"#,
316 source_range: 58..58, 216 )
317 delete: 58..58,
318 insert: "index",
319 kind: Binding,
320 },
321 CompletionItem {
322 label: "test()",
323 source_range: 58..58,
324 delete: 58..58,
325 insert: "test()$0",
326 kind: Function,
327 lookup: "test",
328 detail: "fn test()",
329 },
330 ]
331 "###
332 );
333 } 217 }
334 218
335 #[test] 219 #[test]
336 fn completes_generic_params() { 220 fn completes_generic_params() {
337 assert_debug_snapshot!( 221 check(
338 do_reference_completion( 222 r#"fn quux<T>() { <|> }"#,
339 r" 223 expect![[r#"
340 fn quux<T>() { 224 tp T
341 <|> 225 fn quux() fn quux<T>()
342 } 226 "#]],
343 "
344 ),
345 @r###"
346 [
347 CompletionItem {
348 label: "T",
349 source_range: 19..19,
350 delete: 19..19,
351 insert: "T",
352 kind: TypeParam,
353 },
354 CompletionItem {
355 label: "quux()",
356 source_range: 19..19,
357 delete: 19..19,
358 insert: "quux()$0",
359 kind: Function,
360 lookup: "quux",
361 detail: "fn quux<T>()",
362 },
363 ]
364 "###
365 ); 227 );
366 } 228 }
367 229
368 #[test] 230 #[test]
369 fn completes_generic_params_in_struct() { 231 fn completes_generic_params_in_struct() {
370 assert_debug_snapshot!( 232 check(
371 do_reference_completion( 233 r#"struct S<T> { x: <|>}"#,
372 r" 234 expect![[r#"
373 struct X<T> { 235 st S<…>
374 x: <|> 236 tp Self
375 } 237 tp T
376 " 238 "#]],
377 ),
378 @r###"
379 [
380 CompletionItem {
381 label: "Self",
382 source_range: 21..21,
383 delete: 21..21,
384 insert: "Self",
385 kind: TypeParam,
386 },
387 CompletionItem {
388 label: "T",
389 source_range: 21..21,
390 delete: 21..21,
391 insert: "T",
392 kind: TypeParam,
393 },
394 CompletionItem {
395 label: "X<…>",
396 source_range: 21..21,
397 delete: 21..21,
398 insert: "X<$0>",
399 kind: Struct,
400 lookup: "X",
401 },
402 ]
403 "###
404 ); 239 );
405 } 240 }
406 241
407 #[test] 242 #[test]
408 fn completes_self_in_enum() { 243 fn completes_self_in_enum() {
409 assert_debug_snapshot!( 244 check(
410 do_reference_completion( 245 r#"enum X { Y(<|>) }"#,
411 r" 246 expect![[r#"
412 enum X { 247 tp Self
413 Y(<|>) 248 en X
414 } 249 "#]],
415 "
416 ),
417 @r###"
418 [
419 CompletionItem {
420 label: "Self",
421 source_range: 15..15,
422 delete: 15..15,
423 insert: "Self",
424 kind: TypeParam,
425 },
426 CompletionItem {
427 label: "X",
428 source_range: 15..15,
429 delete: 15..15,
430 insert: "X",
431 kind: Enum,
432 },
433 ]
434 "###
435 ); 250 );
436 } 251 }
437 252
438 #[test] 253 #[test]
439 fn completes_module_items() { 254 fn completes_module_items() {
440 assert_debug_snapshot!( 255 check(
441 do_reference_completion( 256 r#"
442 r" 257struct S;
443 struct Foo; 258enum E {}
444 enum Baz {} 259fn quux() { <|> }
445 fn quux() { 260"#,
446 <|> 261 expect![[r#"
447 } 262 en E
448 " 263 st S
449 ), 264 fn quux() fn quux()
450 @r###" 265 "#]],
451 [ 266 );
452 CompletionItem {
453 label: "Baz",
454 source_range: 40..40,
455 delete: 40..40,
456 insert: "Baz",
457 kind: Enum,
458 },
459 CompletionItem {
460 label: "Foo",
461 source_range: 40..40,
462 delete: 40..40,
463 insert: "Foo",
464 kind: Struct,
465 },
466 CompletionItem {
467 label: "quux()",
468 source_range: 40..40,
469 delete: 40..40,
470 insert: "quux()$0",
471 kind: Function,
472 lookup: "quux",
473 detail: "fn quux()",
474 },
475 ]
476 "###
477 );
478 } 267 }
479 268
480 #[test] 269 #[test]
481 fn completes_extern_prelude() { 270 fn completes_extern_prelude() {
482 assert_debug_snapshot!( 271 check(
483 do_reference_completion( 272 r#"
484 r" 273//- /lib.rs
485 //- /lib.rs 274use <|>;
486 use <|>; 275
487 276//- /other_crate/lib.rs
488 //- /other_crate/lib.rs 277// nothing here
489 // nothing here 278"#,
490 " 279 expect![[r#"
491 ), 280 md other_crate
492 @r###" 281 "#]],
493 [
494 CompletionItem {
495 label: "other_crate",
496 source_range: 4..4,
497 delete: 4..4,
498 insert: "other_crate",
499 kind: Module,
500 },
501 ]
502 "###
503 ); 282 );
504 } 283 }
505 284
506 #[test] 285 #[test]
507 fn completes_module_items_in_nested_modules() { 286 fn completes_module_items_in_nested_modules() {
508 assert_debug_snapshot!( 287 check(
509 do_reference_completion( 288 r#"
510 r" 289struct Foo;
511 struct Foo; 290mod m {
512 mod m { 291 struct Bar;
513 struct Bar; 292 fn quux() { <|> }
514 fn quux() { <|> } 293}
515 } 294"#,
516 " 295 expect![[r#"
517 ), 296 st Bar
518 @r###" 297 fn quux() fn quux()
519 [ 298 "#]],
520 CompletionItem {
521 label: "Bar",
522 source_range: 52..52,
523 delete: 52..52,
524 insert: "Bar",
525 kind: Struct,
526 },
527 CompletionItem {
528 label: "quux()",
529 source_range: 52..52,
530 delete: 52..52,
531 insert: "quux()$0",
532 kind: Function,
533 lookup: "quux",
534 detail: "fn quux()",
535 },
536 ]
537 "###
538 ); 299 );
539 } 300 }
540 301
541 #[test] 302 #[test]
542 fn completes_return_type() { 303 fn completes_return_type() {
543 assert_debug_snapshot!( 304 check(
544 do_reference_completion( 305 r#"
545 r" 306struct Foo;
546 struct Foo; 307fn x() -> <|>
547 fn x() -> <|> 308"#,
548 " 309 expect![[r#"
549 ), 310 st Foo
550 @r###" 311 fn x() fn x()
551 [ 312 "#]],
552 CompletionItem {
553 label: "Foo",
554 source_range: 22..22,
555 delete: 22..22,
556 insert: "Foo",
557 kind: Struct,
558 },
559 CompletionItem {
560 label: "x()",
561 source_range: 22..22,
562 delete: 22..22,
563 insert: "x()$0",
564 kind: Function,
565 lookup: "x",
566 detail: "fn x()",
567 },
568 ]
569 "###
570 ); 313 );
571 } 314 }
572 315
573 #[test] 316 #[test]
574 fn dont_show_both_completions_for_shadowing() { 317 fn dont_show_both_completions_for_shadowing() {
575 assert_debug_snapshot!( 318 check(
576 do_reference_completion( 319 r#"
577 r" 320fn foo() {
578 fn foo() { 321 let bar = 92;
579 let bar = 92; 322 {
580 { 323 let bar = 62;
581 let bar = 62; 324 drop(<|>)
582 <|> 325 }
583 } 326}
584 } 327"#,
585 " 328 // FIXME: should be only one bar here
586 ), 329 expect![[r#"
587 @r###" 330 bn bar i32
588 [ 331 bn bar i32
589 CompletionItem { 332 fn foo() fn foo()
590 label: "bar", 333 "#]],
591 source_range: 65..65,
592 delete: 65..65,
593 insert: "bar",
594 kind: Binding,
595 detail: "i32",
596 },
597 CompletionItem {
598 label: "foo()",
599 source_range: 65..65,
600 delete: 65..65,
601 insert: "foo()$0",
602 kind: Function,
603 lookup: "foo",
604 detail: "fn foo()",
605 },
606 ]
607 "###
608 ); 334 );
609 } 335 }
610 336
611 #[test] 337 #[test]
612 fn completes_self_in_methods() { 338 fn completes_self_in_methods() {
613 assert_debug_snapshot!( 339 check(
614 do_reference_completion(r"impl S { fn foo(&self) { <|> } }"), 340 r#"impl S { fn foo(&self) { <|> } }"#,
615 @r###" 341 expect![[r#"
616 [ 342 tp Self
617 CompletionItem { 343 bn self &{unknown}
618 label: "Self", 344 "#]],
619 source_range: 25..25,
620 delete: 25..25,
621 insert: "Self",
622 kind: TypeParam,
623 },
624 CompletionItem {
625 label: "self",
626 source_range: 25..25,
627 delete: 25..25,
628 insert: "self",
629 kind: Binding,
630 detail: "&{unknown}",
631 },
632 ]
633 "###
634 ); 345 );
635 } 346 }
636 347
637 #[test] 348 #[test]
638 fn completes_prelude() { 349 fn completes_prelude() {
639 assert_debug_snapshot!( 350 check(
640 do_reference_completion( 351 r#"
641 " 352//- /main.rs
642 //- /main.rs 353fn foo() { let x: <|> }
643 fn foo() { let x: <|> } 354
644 355//- /std/lib.rs
645 //- /std/lib.rs 356#[prelude_import]
646 #[prelude_import] 357use prelude::*;
647 use prelude::*; 358
648 359mod prelude { struct Option; }
649 mod prelude { 360"#,
650 struct Option; 361 expect![[r#"
651 } 362 st Option
652 " 363 fn foo() fn foo()
653 ), 364 md std
654 @r###" 365 "#]],
655 [
656 CompletionItem {
657 label: "Option",
658 source_range: 18..18,
659 delete: 18..18,
660 insert: "Option",
661 kind: Struct,
662 },
663 CompletionItem {
664 label: "foo()",
665 source_range: 18..18,
666 delete: 18..18,
667 insert: "foo()$0",
668 kind: Function,
669 lookup: "foo",
670 detail: "fn foo()",
671 },
672 CompletionItem {
673 label: "std",
674 source_range: 18..18,
675 delete: 18..18,
676 insert: "std",
677 kind: Module,
678 },
679 ]
680 "###
681 ); 366 );
682 } 367 }
683 368
684 #[test] 369 #[test]
685 fn completes_std_prelude_if_core_is_defined() { 370 fn completes_std_prelude_if_core_is_defined() {
686 assert_debug_snapshot!( 371 check(
687 do_reference_completion( 372 r#"
688 " 373//- /main.rs
689 //- /main.rs 374fn foo() { let x: <|> }
690 fn foo() { let x: <|> } 375
691 376//- /core/lib.rs
692 //- /core/lib.rs 377#[prelude_import]
693 #[prelude_import] 378use prelude::*;
694 use prelude::*; 379
695 380mod prelude { struct Option; }
696 mod prelude { 381
697 struct Option; 382//- /std/lib.rs
698 } 383#[prelude_import]
699 384use prelude::*;
700 //- /std/lib.rs 385
701 #[prelude_import] 386mod prelude { struct String; }
702 use prelude::*; 387"#,
703 388 expect![[r#"
704 mod prelude { 389 st String
705 struct String; 390 md core
706 } 391 fn foo() fn foo()
707 " 392 md std
708 ), 393 "#]],
709 @r###"
710 [
711 CompletionItem {
712 label: "String",
713 source_range: 18..18,
714 delete: 18..18,
715 insert: "String",
716 kind: Struct,
717 },
718 CompletionItem {
719 label: "core",
720 source_range: 18..18,
721 delete: 18..18,
722 insert: "core",
723 kind: Module,
724 },
725 CompletionItem {
726 label: "foo()",
727 source_range: 18..18,
728 delete: 18..18,
729 insert: "foo()$0",
730 kind: Function,
731 lookup: "foo",
732 detail: "fn foo()",
733 },
734 CompletionItem {
735 label: "std",
736 source_range: 18..18,
737 delete: 18..18,
738 insert: "std",
739 kind: Module,
740 },
741 ]
742 "###
743 ); 394 );
744 } 395 }
745 396
746 #[test] 397 #[test]
747 fn completes_macros_as_value() { 398 fn completes_macros_as_value() {
748 assert_debug_snapshot!( 399 check(
749 do_reference_completion( 400 r#"
750 " 401macro_rules! foo { () => {} }
751 //- /main.rs
752 macro_rules! foo {
753 () => {}
754 }
755 402
756 #[macro_use] 403#[macro_use]
757 mod m1 { 404mod m1 {
758 macro_rules! bar { 405 macro_rules! bar { () => {} }
759 () => {} 406}
760 }
761 }
762 407
763 mod m2 { 408mod m2 {
764 macro_rules! nope { 409 macro_rules! nope { () => {} }
765 () => {}
766 }
767 410
768 #[macro_export] 411 #[macro_export]
769 macro_rules! baz { 412 macro_rules! baz { () => {} }
770 () => {} 413}
771 }
772 }
773 414
774 fn main() { 415fn main() { let v = <|> }
775 let v = <|> 416"#,
776 } 417 expect![[r##"
777 " 418 ma bar!(…) macro_rules! bar
778 ), 419 ma baz!(…) #[macro_export]
779 @r###" 420 macro_rules! baz
780 [ 421 ma foo!(…) macro_rules! foo
781 CompletionItem { 422 md m1
782 label: "bar!(…)", 423 md m2
783 source_range: 256..256, 424 fn main() fn main()
784 delete: 256..256, 425 "##]],
785 insert: "bar!($0)",
786 kind: Macro,
787 lookup: "bar!",
788 detail: "macro_rules! bar",
789 },
790 CompletionItem {
791 label: "baz!(…)",
792 source_range: 256..256,
793 delete: 256..256,
794 insert: "baz!($0)",
795 kind: Macro,
796 lookup: "baz!",
797 detail: "#[macro_export]\nmacro_rules! baz",
798 },
799 CompletionItem {
800 label: "foo!(…)",
801 source_range: 256..256,
802 delete: 256..256,
803 insert: "foo!($0)",
804 kind: Macro,
805 lookup: "foo!",
806 detail: "macro_rules! foo",
807 },
808 CompletionItem {
809 label: "m1",
810 source_range: 256..256,
811 delete: 256..256,
812 insert: "m1",
813 kind: Module,
814 },
815 CompletionItem {
816 label: "m2",
817 source_range: 256..256,
818 delete: 256..256,
819 insert: "m2",
820 kind: Module,
821 },
822 CompletionItem {
823 label: "main()",
824 source_range: 256..256,
825 delete: 256..256,
826 insert: "main()$0",
827 kind: Function,
828 lookup: "main",
829 detail: "fn main()",
830 },
831 ]
832 "###
833 ); 426 );
834 } 427 }
835 428
836 #[test] 429 #[test]
837 fn completes_both_macro_and_value() { 430 fn completes_both_macro_and_value() {
838 assert_debug_snapshot!( 431 check(
839 do_reference_completion( 432 r#"
840 " 433macro_rules! foo { () => {} }
841 //- /main.rs 434fn foo() { <|> }
842 macro_rules! foo { 435"#,
843 () => {} 436 expect![[r#"
844 } 437 ma foo!(…) macro_rules! foo
845 438 fn foo() fn foo()
846 fn foo() { 439 "#]],
847 <|>
848 }
849 "
850 ),
851 @r###"
852 [
853 CompletionItem {
854 label: "foo!(…)",
855 source_range: 50..50,
856 delete: 50..50,
857 insert: "foo!($0)",
858 kind: Macro,
859 lookup: "foo!",
860 detail: "macro_rules! foo",
861 },
862 CompletionItem {
863 label: "foo()",
864 source_range: 50..50,
865 delete: 50..50,
866 insert: "foo()$0",
867 kind: Function,
868 lookup: "foo",
869 detail: "fn foo()",
870 },
871 ]
872 "###
873 ); 440 );
874 } 441 }
875 442
876 #[test] 443 #[test]
877 fn completes_macros_as_type() { 444 fn completes_macros_as_type() {
878 assert_debug_snapshot!( 445 check(
879 do_reference_completion( 446 r#"
880 " 447macro_rules! foo { () => {} }
881 //- /main.rs 448fn main() { let x: <|> }
882 macro_rules! foo { 449"#,
883 () => {} 450 expect![[r#"
884 } 451 ma foo!(…) macro_rules! foo
885 452 fn main() fn main()
886 fn main() { 453 "#]],
887 let x: <|>
888 }
889 "
890 ),
891 @r###"
892 [
893 CompletionItem {
894 label: "foo!(…)",
895 source_range: 58..58,
896 delete: 58..58,
897 insert: "foo!($0)",
898 kind: Macro,
899 lookup: "foo!",
900 detail: "macro_rules! foo",
901 },
902 CompletionItem {
903 label: "main()",
904 source_range: 58..58,
905 delete: 58..58,
906 insert: "main()$0",
907 kind: Function,
908 lookup: "main",
909 detail: "fn main()",
910 },
911 ]
912 "###
913 ); 454 );
914 } 455 }
915 456
916 #[test] 457 #[test]
917 fn completes_macros_as_stmt() { 458 fn completes_macros_as_stmt() {
918 assert_debug_snapshot!( 459 check(
919 do_reference_completion( 460 r#"
920 " 461macro_rules! foo { () => {} }
921 //- /main.rs 462fn main() { <|> }
922 macro_rules! foo { 463"#,
923 () => {} 464 expect![[r#"
924 } 465 ma foo!(…) macro_rules! foo
925 466 fn main() fn main()
926 fn main() { 467 "#]],
927 <|>
928 }
929 "
930 ),
931 @r###"
932 [
933 CompletionItem {
934 label: "foo!(…)",
935 source_range: 51..51,
936 delete: 51..51,
937 insert: "foo!($0)",
938 kind: Macro,
939 lookup: "foo!",
940 detail: "macro_rules! foo",
941 },
942 CompletionItem {
943 label: "main()",
944 source_range: 51..51,
945 delete: 51..51,
946 insert: "main()$0",
947 kind: Function,
948 lookup: "main",
949 detail: "fn main()",
950 },
951 ]
952 "###
953 ); 468 );
954 } 469 }
955 470
956 #[test] 471 #[test]
957 fn completes_local_item() { 472 fn completes_local_item() {
958 assert_debug_snapshot!( 473 check(
959 do_reference_completion( 474 r#"
960 " 475fn main() {
961 //- /main.rs 476 return f<|>;
962 fn main() { 477 fn frobnicate() {}
963 return f<|>; 478}
964 fn frobnicate() {} 479"#,
965 } 480 expect![[r#"
966 " 481 fn frobnicate() fn frobnicate()
967 ), 482 fn main() fn main()
968 @r###" 483 "#]],
969 [ 484 );
970 CompletionItem {
971 label: "frobnicate()",
972 source_range: 23..24,
973 delete: 23..24,
974 insert: "frobnicate()$0",
975 kind: Function,
976 lookup: "frobnicate",
977 detail: "fn frobnicate()",
978 },
979 CompletionItem {
980 label: "main()",
981 source_range: 23..24,
982 delete: 23..24,
983 insert: "main()$0",
984 kind: Function,
985 lookup: "main",
986 detail: "fn main()",
987 },
988 ]
989 "###
990 )
991 } 485 }
992 486
993 #[test] 487 #[test]
994 fn completes_in_simple_macro_1() { 488 fn completes_in_simple_macro_1() {
995 assert_debug_snapshot!( 489 check(
996 do_reference_completion( 490 r#"
997 r" 491macro_rules! m { ($e:expr) => { $e } }
998 macro_rules! m { ($e:expr) => { $e } } 492fn quux(x: i32) {
999 fn quux(x: i32) { 493 let y = 92;
1000 let y = 92; 494 m!(<|>);
1001 m!(<|>); 495}
1002 } 496"#,
1003 " 497 expect![[r#"
1004 ), 498 ma m!(…) macro_rules! m
1005 @r###" 499 fn quux(…) fn quux(x: i32)
1006 [ 500 bn x i32
1007 CompletionItem { 501 bn y i32
1008 label: "m!(…)", 502 "#]],
1009 source_range: 80..80,
1010 delete: 80..80,
1011 insert: "m!($0)",
1012 kind: Macro,
1013 lookup: "m!",
1014 detail: "macro_rules! m",
1015 },
1016 CompletionItem {
1017 label: "quux(…)",
1018 source_range: 80..80,
1019 delete: 80..80,
1020 insert: "quux(${1:x})$0",
1021 kind: Function,
1022 lookup: "quux",
1023 detail: "fn quux(x: i32)",
1024 trigger_call_info: true,
1025 },
1026 CompletionItem {
1027 label: "x",
1028 source_range: 80..80,
1029 delete: 80..80,
1030 insert: "x",
1031 kind: Binding,
1032 detail: "i32",
1033 },
1034 CompletionItem {
1035 label: "y",
1036 source_range: 80..80,
1037 delete: 80..80,
1038 insert: "y",
1039 kind: Binding,
1040 detail: "i32",
1041 },
1042 ]
1043 "###
1044 ); 503 );
1045 } 504 }
1046 505
1047 #[test] 506 #[test]
1048 fn completes_in_simple_macro_2() { 507 fn completes_in_simple_macro_2() {
1049 assert_debug_snapshot!( 508 check(
1050 do_reference_completion( 509 r"
1051 r" 510macro_rules! m { ($e:expr) => { $e } }
1052 macro_rules! m { ($e:expr) => { $e } } 511fn quux(x: i32) {
1053 fn quux(x: i32) { 512 let y = 92;
1054 let y = 92; 513 m!(x<|>);
1055 m!(x<|>); 514}
1056 } 515",
1057 " 516 expect![[r#"
1058 ), 517 ma m!(…) macro_rules! m
1059 @r###" 518 fn quux(…) fn quux(x: i32)
1060 [ 519 bn x i32
1061 CompletionItem { 520 bn y i32
1062 label: "m!(…)", 521 "#]],
1063 source_range: 80..81,
1064 delete: 80..81,
1065 insert: "m!($0)",
1066 kind: Macro,
1067 lookup: "m!",
1068 detail: "macro_rules! m",
1069 },
1070 CompletionItem {
1071 label: "quux(…)",
1072 source_range: 80..81,
1073 delete: 80..81,
1074 insert: "quux(${1:x})$0",
1075 kind: Function,
1076 lookup: "quux",
1077 detail: "fn quux(x: i32)",
1078 trigger_call_info: true,
1079 },
1080 CompletionItem {
1081 label: "x",
1082 source_range: 80..81,
1083 delete: 80..81,
1084 insert: "x",
1085 kind: Binding,
1086 detail: "i32",
1087 },
1088 CompletionItem {
1089 label: "y",
1090 source_range: 80..81,
1091 delete: 80..81,
1092 insert: "y",
1093 kind: Binding,
1094 detail: "i32",
1095 },
1096 ]
1097 "###
1098 ); 522 );
1099 } 523 }
1100 524
1101 #[test] 525 #[test]
1102 fn completes_in_simple_macro_without_closing_parens() { 526 fn completes_in_simple_macro_without_closing_parens() {
1103 assert_debug_snapshot!( 527 check(
1104 do_reference_completion( 528 r#"
1105 r" 529macro_rules! m { ($e:expr) => { $e } }
1106 macro_rules! m { ($e:expr) => { $e } } 530fn quux(x: i32) {
1107 fn quux(x: i32) { 531 let y = 92;
1108 let y = 92; 532 m!(x<|>
1109 m!(x<|> 533}
1110 } 534"#,
1111 " 535 expect![[r#"
1112 ), 536 ma m!(…) macro_rules! m
1113 @r###" 537 fn quux(…) fn quux(x: i32)
1114 [ 538 bn x i32
1115 CompletionItem { 539 bn y i32
1116 label: "m!(…)", 540 "#]],
1117 source_range: 80..81,
1118 delete: 80..81,
1119 insert: "m!($0)",
1120 kind: Macro,
1121 lookup: "m!",
1122 detail: "macro_rules! m",
1123 },
1124 CompletionItem {
1125 label: "quux(…)",
1126 source_range: 80..81,
1127 delete: 80..81,
1128 insert: "quux(${1:x})$0",
1129 kind: Function,
1130 lookup: "quux",
1131 detail: "fn quux(x: i32)",
1132 trigger_call_info: true,
1133 },
1134 CompletionItem {
1135 label: "x",
1136 source_range: 80..81,
1137 delete: 80..81,
1138 insert: "x",
1139 kind: Binding,
1140 detail: "i32",
1141 },
1142 CompletionItem {
1143 label: "y",
1144 source_range: 80..81,
1145 delete: 80..81,
1146 insert: "y",
1147 kind: Binding,
1148 detail: "i32",
1149 },
1150 ]
1151 "###
1152 ); 541 );
1153 } 542 }
1154 543
1155 #[test] 544 #[test]
1156 fn completes_unresolved_uses() { 545 fn completes_unresolved_uses() {
1157 assert_debug_snapshot!( 546 check(
1158 do_reference_completion( 547 r#"
1159 r" 548use spam::Quux;
1160 use spam::Quux; 549
1161 550fn main() { <|> }
1162 fn main() { 551"#,
1163 <|> 552 expect![[r#"
1164 } 553 ?? Quux
1165 " 554 fn main() fn main()
1166 ), 555 "#]],
1167 @r###"
1168 [
1169 CompletionItem {
1170 label: "Quux",
1171 source_range: 33..33,
1172 delete: 33..33,
1173 insert: "Quux",
1174 },
1175 CompletionItem {
1176 label: "main()",
1177 source_range: 33..33,
1178 delete: 33..33,
1179 insert: "main()$0",
1180 kind: Function,
1181 lookup: "main",
1182 detail: "fn main()",
1183 },
1184 ]
1185 "###
1186 ); 556 );
1187 } 557 }
1188 #[test] 558 #[test]
1189 fn completes_enum_variant_matcharm() { 559 fn completes_enum_variant_matcharm() {
1190 assert_debug_snapshot!( 560 check(
1191 do_reference_completion( 561 r#"
1192 r" 562enum Foo { Bar, Baz, Quux }
1193 enum Foo {
1194 Bar,
1195 Baz,
1196 Quux
1197 }
1198 563
1199 fn main() { 564fn main() {
1200 let foo = Foo::Quux; 565 let foo = Foo::Quux;
1201 566 match foo { Qu<|> }
1202 match foo { 567}
1203 Qu<|> 568"#,
1204 } 569 expect![[r#"
1205 } 570 en Foo
1206 " 571 ev Foo::Bar ()
1207 ), 572 ev Foo::Baz ()
1208 @r###" 573 ev Foo::Quux ()
1209 [ 574 "#]],
1210 CompletionItem {
1211 label: "Foo",
1212 source_range: 103..105,
1213 delete: 103..105,
1214 insert: "Foo",
1215 kind: Enum,
1216 },
1217 CompletionItem {
1218 label: "Foo::Bar",
1219 source_range: 103..105,
1220 delete: 103..105,
1221 insert: "Foo::Bar",
1222 kind: EnumVariant,
1223 lookup: "Bar",
1224 detail: "()",
1225 },
1226 CompletionItem {
1227 label: "Foo::Baz",
1228 source_range: 103..105,
1229 delete: 103..105,
1230 insert: "Foo::Baz",
1231 kind: EnumVariant,
1232 lookup: "Baz",
1233 detail: "()",
1234 },
1235 CompletionItem {
1236 label: "Foo::Quux",
1237 source_range: 103..105,
1238 delete: 103..105,
1239 insert: "Foo::Quux",
1240 kind: EnumVariant,
1241 lookup: "Quux",
1242 detail: "()",
1243 },
1244 ]
1245 "###
1246 ) 575 )
1247 } 576 }
1248 577
1249 #[test] 578 #[test]
1250 fn completes_enum_variant_iflet() { 579 fn completes_enum_variant_iflet() {
1251 assert_debug_snapshot!( 580 check(
1252 do_reference_completion( 581 r#"
1253 r" 582enum Foo { Bar, Baz, Quux }
1254 enum Foo {
1255 Bar,
1256 Baz,
1257 Quux
1258 }
1259
1260 fn main() {
1261 let foo = Foo::Quux;
1262 583
1263 if let Qu<|> = foo { 584fn main() {
1264 585 let foo = Foo::Quux;
1265 } 586 if let Qu<|> = foo { }
1266 } 587}
1267 " 588"#,
1268 ), 589 expect![[r#"
1269 @r###" 590 en Foo
1270 [ 591 ev Foo::Bar ()
1271 CompletionItem { 592 ev Foo::Baz ()
1272 label: "Foo", 593 ev Foo::Quux ()
1273 source_range: 90..92, 594 "#]],
1274 delete: 90..92,
1275 insert: "Foo",
1276 kind: Enum,
1277 },
1278 CompletionItem {
1279 label: "Foo::Bar",
1280 source_range: 90..92,
1281 delete: 90..92,
1282 insert: "Foo::Bar",
1283 kind: EnumVariant,
1284 lookup: "Bar",
1285 detail: "()",
1286 },
1287 CompletionItem {
1288 label: "Foo::Baz",
1289 source_range: 90..92,
1290 delete: 90..92,
1291 insert: "Foo::Baz",
1292 kind: EnumVariant,
1293 lookup: "Baz",
1294 detail: "()",
1295 },
1296 CompletionItem {
1297 label: "Foo::Quux",
1298 source_range: 90..92,
1299 delete: 90..92,
1300 insert: "Foo::Quux",
1301 kind: EnumVariant,
1302 lookup: "Quux",
1303 detail: "()",
1304 },
1305 ]
1306 "###
1307 ) 595 )
1308 } 596 }
1309 597
1310 #[test] 598 #[test]
1311 fn completes_enum_variant_basic_expr() { 599 fn completes_enum_variant_basic_expr() {
1312 assert_debug_snapshot!( 600 check(
1313 do_reference_completion( 601 r#"
1314 r" 602enum Foo { Bar, Baz, Quux }
1315 enum Foo { 603fn main() { let foo: Foo = Q<|> }
1316 Bar, 604"#,
1317 Baz, 605 expect![[r#"
1318 Quux 606 en Foo
1319 } 607 ev Foo::Bar ()
1320 608 ev Foo::Baz ()
1321 fn main() { 609 ev Foo::Quux ()
1322 let foo: Foo = Q<|> 610 fn main() fn main()
1323 } 611 "#]],
1324 "
1325 ),
1326 @r###"
1327 [
1328 CompletionItem {
1329 label: "Foo",
1330 source_range: 72..73,
1331 delete: 72..73,
1332 insert: "Foo",
1333 kind: Enum,
1334 },
1335 CompletionItem {
1336 label: "Foo::Bar",
1337 source_range: 72..73,
1338 delete: 72..73,
1339 insert: "Foo::Bar",
1340 kind: EnumVariant,
1341 lookup: "Bar",
1342 detail: "()",
1343 },
1344 CompletionItem {
1345 label: "Foo::Baz",
1346 source_range: 72..73,
1347 delete: 72..73,
1348 insert: "Foo::Baz",
1349 kind: EnumVariant,
1350 lookup: "Baz",
1351 detail: "()",
1352 },
1353 CompletionItem {
1354 label: "Foo::Quux",
1355 source_range: 72..73,
1356 delete: 72..73,
1357 insert: "Foo::Quux",
1358 kind: EnumVariant,
1359 lookup: "Quux",
1360 detail: "()",
1361 },
1362 CompletionItem {
1363 label: "main()",
1364 source_range: 72..73,
1365 delete: 72..73,
1366 insert: "main()$0",
1367 kind: Function,
1368 lookup: "main",
1369 detail: "fn main()",
1370 },
1371 ]
1372 "###
1373 ) 612 )
1374 } 613 }
1375 614
1376 #[test] 615 #[test]
1377 fn completes_enum_variant_from_module() { 616 fn completes_enum_variant_from_module() {
1378 assert_debug_snapshot!( 617 check(
1379 do_reference_completion( 618 r#"
1380 r" 619mod m { pub enum E { V } }
1381 mod m { pub enum E { V } } 620fn f() -> m::E { V<|> }
1382 621"#,
1383 fn f() -> m::E { 622 expect![[r#"
1384 V<|> 623 fn f() fn f() -> m::E
1385 } 624 md m
1386 " 625 ev m::E::V ()
1387 ), 626 "#]],
1388 @r###"
1389 [
1390 CompletionItem {
1391 label: "f()",
1392 source_range: 49..50,
1393 delete: 49..50,
1394 insert: "f()$0",
1395 kind: Function,
1396 lookup: "f",
1397 detail: "fn f() -> m::E",
1398 },
1399 CompletionItem {
1400 label: "m",
1401 source_range: 49..50,
1402 delete: 49..50,
1403 insert: "m",
1404 kind: Module,
1405 },
1406 CompletionItem {
1407 label: "m::E::V",
1408 source_range: 49..50,
1409 delete: 49..50,
1410 insert: "m::E::V",
1411 kind: EnumVariant,
1412 lookup: "V",
1413 detail: "()",
1414 },
1415 ]
1416 "###
1417 ) 627 )
1418 } 628 }
1419 629
1420 #[test] 630 #[test]
1421 fn dont_complete_attr() { 631 fn dont_complete_attr() {
1422 assert_debug_snapshot!( 632 check(
1423 do_reference_completion( 633 r#"
1424 r" 634struct Foo;
1425 struct Foo; 635#[<|>]
1426 #[<|>] 636fn f() {}
1427 fn f() {} 637"#,
1428 " 638 expect![[""]],
1429 ),
1430 @r###"[]"###
1431 ) 639 )
1432 } 640 }
1433} 641}
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index ef22ea54d..7688a1483 100644
--- a/crates/ra_ide/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
@@ -196,20 +196,11 @@ impl<'a> CompletionContext<'a> {
196 // The range of the identifier that is being completed. 196 // The range of the identifier that is being completed.
197 pub(crate) fn source_range(&self) -> TextRange { 197 pub(crate) fn source_range(&self) -> TextRange {
198 // check kind of macro-expanded token, but use range of original token 198 // check kind of macro-expanded token, but use range of original token
199 match self.token.kind() { 199 if self.token.kind() == IDENT || self.token.kind().is_keyword() {
200 // workaroud when completion is triggered by trigger characters. 200 mark::hit!(completes_if_prefix_is_keyword);
201 IDENT => self.original_token.text_range(), 201 self.original_token.text_range()
202 _ => { 202 } else {
203 // If we haven't characters between keyword and our cursor we take the keyword start range to edit 203 TextRange::empty(self.offset)
204 if self.token.kind().is_keyword()
205 && self.offset == self.original_token.text_range().end()
206 {
207 mark::hit!(completes_bindings_from_for_with_in_prefix);
208 TextRange::empty(self.original_token.text_range().start())
209 } else {
210 TextRange::empty(self.offset)
211 }
212 }
213 } 204 }
214 } 205 }
215 206
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs
index 477d6f6f6..d7011c9cf 100644
--- a/crates/ra_ide/src/completion/completion_item.rs
+++ b/crates/ra_ide/src/completion/completion_item.rs
@@ -123,6 +123,7 @@ pub enum CompletionItemKind {
123 TypeParam, 123 TypeParam,
124 Macro, 124 Macro,
125 Attribute, 125 Attribute,
126 UnresolvedReference,
126} 127}
127 128
128impl CompletionItemKind { 129impl CompletionItemKind {
@@ -147,6 +148,7 @@ impl CompletionItemKind {
147 CompletionItemKind::Trait => "tt", 148 CompletionItemKind::Trait => "tt",
148 CompletionItemKind::TypeAlias => "ta", 149 CompletionItemKind::TypeAlias => "ta",
149 CompletionItemKind::TypeParam => "tp", 150 CompletionItemKind::TypeParam => "tp",
151 CompletionItemKind::UnresolvedReference => "??",
150 } 152 }
151 } 153 }
152} 154}
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index bfa7e08be..e4c57e41a 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -79,11 +79,10 @@ impl Completions {
79 return self.add_macro(ctx, Some(local_name), *mac); 79 return self.add_macro(ctx, Some(local_name), *mac);
80 } 80 }
81 ScopeDef::Unknown => { 81 ScopeDef::Unknown => {
82 return self.add(CompletionItem::new( 82 return self.add(
83 CompletionKind::Reference, 83 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), local_name)
84 ctx.source_range(), 84 .kind(CompletionItemKind::UnresolvedReference),
85 local_name, 85 );
86 ));
87 } 86 }
88 }; 87 };
89 88