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