diff options
Diffstat (limited to 'crates/completion/src/completions/unqualified_path.rs')
-rw-r--r-- | crates/completion/src/completions/unqualified_path.rs | 737 |
1 files changed, 0 insertions, 737 deletions
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs deleted file mode 100644 index ac5596ca4..000000000 --- a/crates/completion/src/completions/unqualified_path.rs +++ /dev/null | |||
@@ -1,737 +0,0 @@ | |||
1 | //! Completion of names from the current scope, e.g. locals and imported items. | ||
2 | |||
3 | use std::iter; | ||
4 | |||
5 | use hir::{Adt, ModuleDef, ScopeDef, Type}; | ||
6 | use syntax::AstNode; | ||
7 | use test_utils::mark; | ||
8 | |||
9 | use crate::{CompletionContext, Completions}; | ||
10 | |||
11 | pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { | ||
12 | if !(ctx.is_trivial_path || ctx.is_pat_binding_or_const) { | ||
13 | return; | ||
14 | } | ||
15 | if ctx.record_lit_syntax.is_some() | ||
16 | || ctx.record_pat_syntax.is_some() | ||
17 | || ctx.attribute_under_caret.is_some() | ||
18 | || ctx.mod_declaration_under_caret.is_some() | ||
19 | { | ||
20 | return; | ||
21 | } | ||
22 | |||
23 | if let Some(ty) = &ctx.expected_type { | ||
24 | complete_enum_variants(acc, ctx, ty); | ||
25 | } | ||
26 | |||
27 | if ctx.is_pat_binding_or_const { | ||
28 | return; | ||
29 | } | ||
30 | |||
31 | ctx.scope.process_all_names(&mut |name, res| { | ||
32 | if ctx.use_item_syntax.is_some() { | ||
33 | if let (ScopeDef::Unknown, Some(name_ref)) = (&res, &ctx.name_ref_syntax) { | ||
34 | if name_ref.syntax().text() == name.to_string().as_str() { | ||
35 | mark::hit!(self_fulfilling_completion); | ||
36 | return; | ||
37 | } | ||
38 | } | ||
39 | } | ||
40 | acc.add_resolution(ctx, name.to_string(), &res) | ||
41 | }); | ||
42 | } | ||
43 | |||
44 | fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) { | ||
45 | if let Some(Adt::Enum(enum_data)) = | ||
46 | iter::successors(Some(ty.clone()), |ty| ty.remove_ref()).last().and_then(|ty| ty.as_adt()) | ||
47 | { | ||
48 | let variants = enum_data.variants(ctx.db); | ||
49 | |||
50 | let module = if let Some(module) = ctx.scope.module() { | ||
51 | // Compute path from the completion site if available. | ||
52 | module | ||
53 | } else { | ||
54 | // Otherwise fall back to the enum's definition site. | ||
55 | enum_data.module(ctx.db) | ||
56 | }; | ||
57 | |||
58 | for variant in variants { | ||
59 | if let Some(path) = module.find_use_path(ctx.db, ModuleDef::from(variant)) { | ||
60 | // Variants with trivial paths are already added by the existing completion logic, | ||
61 | // so we should avoid adding these twice | ||
62 | if path.segments.len() > 1 { | ||
63 | acc.add_qualified_enum_variant(ctx, variant, path); | ||
64 | } | ||
65 | } | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | |||
70 | #[cfg(test)] | ||
71 | mod tests { | ||
72 | use expect_test::{expect, Expect}; | ||
73 | use test_utils::mark; | ||
74 | |||
75 | use crate::{ | ||
76 | test_utils::{check_edit, completion_list_with_config, TEST_CONFIG}, | ||
77 | CompletionConfig, CompletionKind, | ||
78 | }; | ||
79 | |||
80 | fn check(ra_fixture: &str, expect: Expect) { | ||
81 | check_with_config(TEST_CONFIG, ra_fixture, expect); | ||
82 | } | ||
83 | |||
84 | fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) { | ||
85 | let actual = completion_list_with_config(config, ra_fixture, CompletionKind::Reference); | ||
86 | expect.assert_eq(&actual) | ||
87 | } | ||
88 | |||
89 | #[test] | ||
90 | fn self_fulfilling_completion() { | ||
91 | mark::check!(self_fulfilling_completion); | ||
92 | check( | ||
93 | r#" | ||
94 | use foo$0 | ||
95 | use std::collections; | ||
96 | "#, | ||
97 | expect![[r#" | ||
98 | ?? collections | ||
99 | "#]], | ||
100 | ); | ||
101 | } | ||
102 | |||
103 | #[test] | ||
104 | fn bind_pat_and_path_ignore_at() { | ||
105 | check( | ||
106 | r#" | ||
107 | enum Enum { A, B } | ||
108 | fn quux(x: Option<Enum>) { | ||
109 | match x { | ||
110 | None => (), | ||
111 | Some(en$0 @ Enum::A) => (), | ||
112 | } | ||
113 | } | ||
114 | "#, | ||
115 | expect![[""]], | ||
116 | ); | ||
117 | } | ||
118 | |||
119 | #[test] | ||
120 | fn bind_pat_and_path_ignore_ref() { | ||
121 | check( | ||
122 | r#" | ||
123 | enum Enum { A, B } | ||
124 | fn quux(x: Option<Enum>) { | ||
125 | match x { | ||
126 | None => (), | ||
127 | Some(ref en$0) => (), | ||
128 | } | ||
129 | } | ||
130 | "#, | ||
131 | expect![[""]], | ||
132 | ); | ||
133 | } | ||
134 | |||
135 | #[test] | ||
136 | fn bind_pat_and_path() { | ||
137 | check( | ||
138 | r#" | ||
139 | enum Enum { A, B } | ||
140 | fn quux(x: Option<Enum>) { | ||
141 | match x { | ||
142 | None => (), | ||
143 | Some(En$0) => (), | ||
144 | } | ||
145 | } | ||
146 | "#, | ||
147 | expect![[r#" | ||
148 | en Enum | ||
149 | "#]], | ||
150 | ); | ||
151 | } | ||
152 | |||
153 | #[test] | ||
154 | fn completes_bindings_from_let() { | ||
155 | check( | ||
156 | r#" | ||
157 | fn quux(x: i32) { | ||
158 | let y = 92; | ||
159 | 1 + $0; | ||
160 | let z = (); | ||
161 | } | ||
162 | "#, | ||
163 | expect![[r#" | ||
164 | bn y i32 | ||
165 | bn x i32 | ||
166 | fn quux(…) fn quux(x: i32) | ||
167 | "#]], | ||
168 | ); | ||
169 | } | ||
170 | |||
171 | #[test] | ||
172 | fn completes_bindings_from_if_let() { | ||
173 | check( | ||
174 | r#" | ||
175 | fn quux() { | ||
176 | if let Some(x) = foo() { | ||
177 | let y = 92; | ||
178 | }; | ||
179 | if let Some(a) = bar() { | ||
180 | let b = 62; | ||
181 | 1 + $0 | ||
182 | } | ||
183 | } | ||
184 | "#, | ||
185 | expect![[r#" | ||
186 | bn b i32 | ||
187 | bn a | ||
188 | fn quux() fn quux() | ||
189 | "#]], | ||
190 | ); | ||
191 | } | ||
192 | |||
193 | #[test] | ||
194 | fn completes_bindings_from_for() { | ||
195 | check( | ||
196 | r#" | ||
197 | fn quux() { | ||
198 | for x in &[1, 2, 3] { $0 } | ||
199 | } | ||
200 | "#, | ||
201 | expect![[r#" | ||
202 | bn x | ||
203 | fn quux() fn quux() | ||
204 | "#]], | ||
205 | ); | ||
206 | } | ||
207 | |||
208 | #[test] | ||
209 | fn completes_if_prefix_is_keyword() { | ||
210 | mark::check!(completes_if_prefix_is_keyword); | ||
211 | check_edit( | ||
212 | "wherewolf", | ||
213 | r#" | ||
214 | fn main() { | ||
215 | let wherewolf = 92; | ||
216 | drop(where$0) | ||
217 | } | ||
218 | "#, | ||
219 | r#" | ||
220 | fn main() { | ||
221 | let wherewolf = 92; | ||
222 | drop(wherewolf) | ||
223 | } | ||
224 | "#, | ||
225 | ) | ||
226 | } | ||
227 | |||
228 | #[test] | ||
229 | fn completes_generic_params() { | ||
230 | check( | ||
231 | r#"fn quux<T>() { $0 }"#, | ||
232 | expect![[r#" | ||
233 | tp T | ||
234 | fn quux() fn quux<T>() | ||
235 | "#]], | ||
236 | ); | ||
237 | } | ||
238 | |||
239 | #[test] | ||
240 | fn completes_generic_params_in_struct() { | ||
241 | check( | ||
242 | r#"struct S<T> { x: $0}"#, | ||
243 | expect![[r#" | ||
244 | tp Self | ||
245 | tp T | ||
246 | st S<…> | ||
247 | "#]], | ||
248 | ); | ||
249 | } | ||
250 | |||
251 | #[test] | ||
252 | fn completes_self_in_enum() { | ||
253 | check( | ||
254 | r#"enum X { Y($0) }"#, | ||
255 | expect![[r#" | ||
256 | tp Self | ||
257 | en X | ||
258 | "#]], | ||
259 | ); | ||
260 | } | ||
261 | |||
262 | #[test] | ||
263 | fn completes_module_items() { | ||
264 | check( | ||
265 | r#" | ||
266 | struct S; | ||
267 | enum E {} | ||
268 | fn quux() { $0 } | ||
269 | "#, | ||
270 | expect![[r#" | ||
271 | st S | ||
272 | fn quux() fn quux() | ||
273 | en E | ||
274 | "#]], | ||
275 | ); | ||
276 | } | ||
277 | |||
278 | /// Regression test for issue #6091. | ||
279 | #[test] | ||
280 | fn correctly_completes_module_items_prefixed_with_underscore() { | ||
281 | check_edit( | ||
282 | "_alpha", | ||
283 | r#" | ||
284 | fn main() { | ||
285 | _$0 | ||
286 | } | ||
287 | fn _alpha() {} | ||
288 | "#, | ||
289 | r#" | ||
290 | fn main() { | ||
291 | _alpha()$0 | ||
292 | } | ||
293 | fn _alpha() {} | ||
294 | "#, | ||
295 | ) | ||
296 | } | ||
297 | |||
298 | #[test] | ||
299 | fn completes_extern_prelude() { | ||
300 | check( | ||
301 | r#" | ||
302 | //- /lib.rs crate:main deps:other_crate | ||
303 | use $0; | ||
304 | |||
305 | //- /other_crate/lib.rs crate:other_crate | ||
306 | // nothing here | ||
307 | "#, | ||
308 | expect![[r#" | ||
309 | md other_crate | ||
310 | "#]], | ||
311 | ); | ||
312 | } | ||
313 | |||
314 | #[test] | ||
315 | fn completes_module_items_in_nested_modules() { | ||
316 | check( | ||
317 | r#" | ||
318 | struct Foo; | ||
319 | mod m { | ||
320 | struct Bar; | ||
321 | fn quux() { $0 } | ||
322 | } | ||
323 | "#, | ||
324 | expect![[r#" | ||
325 | fn quux() fn quux() | ||
326 | st Bar | ||
327 | "#]], | ||
328 | ); | ||
329 | } | ||
330 | |||
331 | #[test] | ||
332 | fn completes_return_type() { | ||
333 | check( | ||
334 | r#" | ||
335 | struct Foo; | ||
336 | fn x() -> $0 | ||
337 | "#, | ||
338 | expect![[r#" | ||
339 | st Foo | ||
340 | fn x() fn x() | ||
341 | "#]], | ||
342 | ); | ||
343 | } | ||
344 | |||
345 | #[test] | ||
346 | fn dont_show_both_completions_for_shadowing() { | ||
347 | check( | ||
348 | r#" | ||
349 | fn foo() { | ||
350 | let bar = 92; | ||
351 | { | ||
352 | let bar = 62; | ||
353 | drop($0) | ||
354 | } | ||
355 | } | ||
356 | "#, | ||
357 | // FIXME: should be only one bar here | ||
358 | expect![[r#" | ||
359 | bn bar i32 | ||
360 | bn bar i32 | ||
361 | fn foo() fn foo() | ||
362 | "#]], | ||
363 | ); | ||
364 | } | ||
365 | |||
366 | #[test] | ||
367 | fn completes_self_in_methods() { | ||
368 | check( | ||
369 | r#"impl S { fn foo(&self) { $0 } }"#, | ||
370 | expect![[r#" | ||
371 | bn self &{unknown} | ||
372 | tp Self | ||
373 | "#]], | ||
374 | ); | ||
375 | } | ||
376 | |||
377 | #[test] | ||
378 | fn completes_prelude() { | ||
379 | check( | ||
380 | r#" | ||
381 | //- /main.rs crate:main deps:std | ||
382 | fn foo() { let x: $0 } | ||
383 | |||
384 | //- /std/lib.rs crate:std | ||
385 | #[prelude_import] | ||
386 | use prelude::*; | ||
387 | |||
388 | mod prelude { struct Option; } | ||
389 | "#, | ||
390 | expect![[r#" | ||
391 | fn foo() fn foo() | ||
392 | md std | ||
393 | st Option | ||
394 | "#]], | ||
395 | ); | ||
396 | } | ||
397 | |||
398 | #[test] | ||
399 | fn completes_prelude_macros() { | ||
400 | check( | ||
401 | r#" | ||
402 | //- /main.rs crate:main deps:std | ||
403 | fn f() {$0} | ||
404 | |||
405 | //- /std/lib.rs crate:std | ||
406 | #[prelude_import] | ||
407 | pub use prelude::*; | ||
408 | |||
409 | #[macro_use] | ||
410 | mod prelude { | ||
411 | pub use crate::concat; | ||
412 | } | ||
413 | |||
414 | mod macros { | ||
415 | #[rustc_builtin_macro] | ||
416 | #[macro_export] | ||
417 | macro_rules! concat { } | ||
418 | } | ||
419 | "#, | ||
420 | expect![[r##" | ||
421 | fn f() fn f() | ||
422 | ma concat!(…) #[macro_export] macro_rules! concat | ||
423 | md std | ||
424 | "##]], | ||
425 | ); | ||
426 | } | ||
427 | |||
428 | #[test] | ||
429 | fn completes_std_prelude_if_core_is_defined() { | ||
430 | check( | ||
431 | r#" | ||
432 | //- /main.rs crate:main deps:core,std | ||
433 | fn foo() { let x: $0 } | ||
434 | |||
435 | //- /core/lib.rs crate:core | ||
436 | #[prelude_import] | ||
437 | use prelude::*; | ||
438 | |||
439 | mod prelude { struct Option; } | ||
440 | |||
441 | //- /std/lib.rs crate:std deps:core | ||
442 | #[prelude_import] | ||
443 | use prelude::*; | ||
444 | |||
445 | mod prelude { struct String; } | ||
446 | "#, | ||
447 | expect![[r#" | ||
448 | fn foo() fn foo() | ||
449 | md std | ||
450 | md core | ||
451 | st String | ||
452 | "#]], | ||
453 | ); | ||
454 | } | ||
455 | |||
456 | #[test] | ||
457 | fn completes_macros_as_value() { | ||
458 | check( | ||
459 | r#" | ||
460 | macro_rules! foo { () => {} } | ||
461 | |||
462 | #[macro_use] | ||
463 | mod m1 { | ||
464 | macro_rules! bar { () => {} } | ||
465 | } | ||
466 | |||
467 | mod m2 { | ||
468 | macro_rules! nope { () => {} } | ||
469 | |||
470 | #[macro_export] | ||
471 | macro_rules! baz { () => {} } | ||
472 | } | ||
473 | |||
474 | fn main() { let v = $0 } | ||
475 | "#, | ||
476 | expect![[r##" | ||
477 | md m1 | ||
478 | ma baz!(…) #[macro_export] macro_rules! baz | ||
479 | fn main() fn main() | ||
480 | md m2 | ||
481 | ma bar!(…) macro_rules! bar | ||
482 | ma foo!(…) macro_rules! foo | ||
483 | "##]], | ||
484 | ); | ||
485 | } | ||
486 | |||
487 | #[test] | ||
488 | fn completes_both_macro_and_value() { | ||
489 | check( | ||
490 | r#" | ||
491 | macro_rules! foo { () => {} } | ||
492 | fn foo() { $0 } | ||
493 | "#, | ||
494 | expect![[r#" | ||
495 | fn foo() fn foo() | ||
496 | ma foo!(…) macro_rules! foo | ||
497 | "#]], | ||
498 | ); | ||
499 | } | ||
500 | |||
501 | #[test] | ||
502 | fn completes_macros_as_type() { | ||
503 | check( | ||
504 | r#" | ||
505 | macro_rules! foo { () => {} } | ||
506 | fn main() { let x: $0 } | ||
507 | "#, | ||
508 | expect![[r#" | ||
509 | fn main() fn main() | ||
510 | ma foo!(…) macro_rules! foo | ||
511 | "#]], | ||
512 | ); | ||
513 | } | ||
514 | |||
515 | #[test] | ||
516 | fn completes_macros_as_stmt() { | ||
517 | check( | ||
518 | r#" | ||
519 | macro_rules! foo { () => {} } | ||
520 | fn main() { $0 } | ||
521 | "#, | ||
522 | expect![[r#" | ||
523 | fn main() fn main() | ||
524 | ma foo!(…) macro_rules! foo | ||
525 | "#]], | ||
526 | ); | ||
527 | } | ||
528 | |||
529 | #[test] | ||
530 | fn completes_local_item() { | ||
531 | check( | ||
532 | r#" | ||
533 | fn main() { | ||
534 | return f$0; | ||
535 | fn frobnicate() {} | ||
536 | } | ||
537 | "#, | ||
538 | expect![[r#" | ||
539 | fn frobnicate() fn frobnicate() | ||
540 | fn main() fn main() | ||
541 | "#]], | ||
542 | ); | ||
543 | } | ||
544 | |||
545 | #[test] | ||
546 | fn completes_in_simple_macro_1() { | ||
547 | check( | ||
548 | r#" | ||
549 | macro_rules! m { ($e:expr) => { $e } } | ||
550 | fn quux(x: i32) { | ||
551 | let y = 92; | ||
552 | m!($0); | ||
553 | } | ||
554 | "#, | ||
555 | expect![[r#" | ||
556 | bn y i32 | ||
557 | bn x i32 | ||
558 | fn quux(…) fn quux(x: i32) | ||
559 | ma m!(…) macro_rules! m | ||
560 | "#]], | ||
561 | ); | ||
562 | } | ||
563 | |||
564 | #[test] | ||
565 | fn completes_in_simple_macro_2() { | ||
566 | check( | ||
567 | r" | ||
568 | macro_rules! m { ($e:expr) => { $e } } | ||
569 | fn quux(x: i32) { | ||
570 | let y = 92; | ||
571 | m!(x$0); | ||
572 | } | ||
573 | ", | ||
574 | expect![[r#" | ||
575 | bn y i32 | ||
576 | bn x i32 | ||
577 | fn quux(…) fn quux(x: i32) | ||
578 | ma m!(…) macro_rules! m | ||
579 | "#]], | ||
580 | ); | ||
581 | } | ||
582 | |||
583 | #[test] | ||
584 | fn completes_in_simple_macro_without_closing_parens() { | ||
585 | check( | ||
586 | r#" | ||
587 | macro_rules! m { ($e:expr) => { $e } } | ||
588 | fn quux(x: i32) { | ||
589 | let y = 92; | ||
590 | m!(x$0 | ||
591 | } | ||
592 | "#, | ||
593 | expect![[r#" | ||
594 | bn y i32 | ||
595 | bn x i32 | ||
596 | fn quux(…) fn quux(x: i32) | ||
597 | ma m!(…) macro_rules! m | ||
598 | "#]], | ||
599 | ); | ||
600 | } | ||
601 | |||
602 | #[test] | ||
603 | fn completes_unresolved_uses() { | ||
604 | check( | ||
605 | r#" | ||
606 | use spam::Quux; | ||
607 | |||
608 | fn main() { $0 } | ||
609 | "#, | ||
610 | expect![[r#" | ||
611 | fn main() fn main() | ||
612 | ?? Quux | ||
613 | "#]], | ||
614 | ); | ||
615 | } | ||
616 | |||
617 | #[test] | ||
618 | fn completes_enum_variant_matcharm() { | ||
619 | check( | ||
620 | r#" | ||
621 | enum Foo { Bar, Baz, Quux } | ||
622 | |||
623 | fn main() { | ||
624 | let foo = Foo::Quux; | ||
625 | match foo { Qu$0 } | ||
626 | } | ||
627 | "#, | ||
628 | expect![[r#" | ||
629 | ev Foo::Bar () | ||
630 | ev Foo::Baz () | ||
631 | ev Foo::Quux () | ||
632 | en Foo | ||
633 | "#]], | ||
634 | ) | ||
635 | } | ||
636 | |||
637 | #[test] | ||
638 | fn completes_enum_variant_matcharm_ref() { | ||
639 | check( | ||
640 | r#" | ||
641 | enum Foo { Bar, Baz, Quux } | ||
642 | |||
643 | fn main() { | ||
644 | let foo = Foo::Quux; | ||
645 | match &foo { Qu$0 } | ||
646 | } | ||
647 | "#, | ||
648 | expect![[r#" | ||
649 | ev Foo::Bar () | ||
650 | ev Foo::Baz () | ||
651 | ev Foo::Quux () | ||
652 | en Foo | ||
653 | "#]], | ||
654 | ) | ||
655 | } | ||
656 | |||
657 | #[test] | ||
658 | fn completes_enum_variant_iflet() { | ||
659 | check( | ||
660 | r#" | ||
661 | enum Foo { Bar, Baz, Quux } | ||
662 | |||
663 | fn main() { | ||
664 | let foo = Foo::Quux; | ||
665 | if let Qu$0 = foo { } | ||
666 | } | ||
667 | "#, | ||
668 | expect![[r#" | ||
669 | ev Foo::Bar () | ||
670 | ev Foo::Baz () | ||
671 | ev Foo::Quux () | ||
672 | en Foo | ||
673 | "#]], | ||
674 | ) | ||
675 | } | ||
676 | |||
677 | #[test] | ||
678 | fn completes_enum_variant_basic_expr() { | ||
679 | check( | ||
680 | r#" | ||
681 | enum Foo { Bar, Baz, Quux } | ||
682 | fn main() { let foo: Foo = Q$0 } | ||
683 | "#, | ||
684 | expect![[r#" | ||
685 | ev Foo::Bar () | ||
686 | ev Foo::Baz () | ||
687 | ev Foo::Quux () | ||
688 | en Foo | ||
689 | fn main() fn main() | ||
690 | "#]], | ||
691 | ) | ||
692 | } | ||
693 | |||
694 | #[test] | ||
695 | fn completes_enum_variant_from_module() { | ||
696 | check( | ||
697 | r#" | ||
698 | mod m { pub enum E { V } } | ||
699 | fn f() -> m::E { V$0 } | ||
700 | "#, | ||
701 | expect![[r#" | ||
702 | ev m::E::V () | ||
703 | md m | ||
704 | fn f() fn f() -> m::E | ||
705 | "#]], | ||
706 | ) | ||
707 | } | ||
708 | |||
709 | #[test] | ||
710 | fn dont_complete_attr() { | ||
711 | check( | ||
712 | r#" | ||
713 | struct Foo; | ||
714 | #[$0] | ||
715 | fn f() {} | ||
716 | "#, | ||
717 | expect![[""]], | ||
718 | ) | ||
719 | } | ||
720 | |||
721 | #[test] | ||
722 | fn completes_type_or_trait_in_impl_block() { | ||
723 | check( | ||
724 | r#" | ||
725 | trait MyTrait {} | ||
726 | struct MyStruct {} | ||
727 | |||
728 | impl My$0 | ||
729 | "#, | ||
730 | expect![[r#" | ||
731 | tp Self | ||
732 | tt MyTrait | ||
733 | st MyStruct | ||
734 | "#]], | ||
735 | ) | ||
736 | } | ||
737 | } | ||