diff options
author | Benjamin Coenen <[email protected]> | 2020-04-07 16:59:09 +0100 |
---|---|---|
committer | Benjamin Coenen <[email protected]> | 2020-04-07 16:59:09 +0100 |
commit | 18a5e164838e1dc2abcc6b79d4fc2f96ffd2507c (patch) | |
tree | bc80b5c49c3b7ba31c7fe967bb34fe14bac9d5ed /crates/ra_ide/src/completion/complete_qualified_path.rs | |
parent | ab864ed259c10ff51f7c9c3421d098eeea7b0245 (diff) | |
parent | 33c364b545350134b945fbca834194fd1a28fe08 (diff) |
Merge branch 'master' of github.com:rust-analyzer/rust-analyzer
Diffstat (limited to 'crates/ra_ide/src/completion/complete_qualified_path.rs')
-rw-r--r-- | crates/ra_ide/src/completion/complete_qualified_path.rs | 1046 |
1 files changed, 1046 insertions, 0 deletions
diff --git a/crates/ra_ide/src/completion/complete_qualified_path.rs b/crates/ra_ide/src/completion/complete_qualified_path.rs new file mode 100644 index 000000000..d98523406 --- /dev/null +++ b/crates/ra_ide/src/completion/complete_qualified_path.rs | |||
@@ -0,0 +1,1046 @@ | |||
1 | //! Completion of paths, i.e. `some::prefix::<|>`. | ||
2 | |||
3 | use hir::{Adt, HasVisibility, PathResolution, ScopeDef}; | ||
4 | use ra_syntax::AstNode; | ||
5 | use test_utils::tested_by; | ||
6 | |||
7 | use crate::completion::{CompletionContext, Completions}; | ||
8 | |||
9 | pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) { | ||
10 | let path = match &ctx.path_prefix { | ||
11 | Some(path) => path.clone(), | ||
12 | _ => return, | ||
13 | }; | ||
14 | let def = match ctx.scope().resolve_hir_path(&path) { | ||
15 | Some(PathResolution::Def(def)) => def, | ||
16 | _ => return, | ||
17 | }; | ||
18 | let context_module = ctx.scope().module(); | ||
19 | match def { | ||
20 | hir::ModuleDef::Module(module) => { | ||
21 | let module_scope = module.scope(ctx.db, context_module); | ||
22 | for (name, def) in module_scope { | ||
23 | if ctx.use_item_syntax.is_some() { | ||
24 | if let ScopeDef::Unknown = def { | ||
25 | if let Some(name_ref) = ctx.name_ref_syntax.as_ref() { | ||
26 | if name_ref.syntax().text() == name.to_string().as_str() { | ||
27 | // for `use self::foo<|>`, don't suggest `foo` as a completion | ||
28 | tested_by!(dont_complete_current_use); | ||
29 | continue; | ||
30 | } | ||
31 | } | ||
32 | } | ||
33 | } | ||
34 | |||
35 | acc.add_resolution(ctx, name.to_string(), &def); | ||
36 | } | ||
37 | } | ||
38 | hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => { | ||
39 | if let hir::ModuleDef::Adt(Adt::Enum(e)) = def { | ||
40 | for variant in e.variants(ctx.db) { | ||
41 | acc.add_enum_variant(ctx, variant, None); | ||
42 | } | ||
43 | } | ||
44 | let ty = match def { | ||
45 | hir::ModuleDef::Adt(adt) => adt.ty(ctx.db), | ||
46 | hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), | ||
47 | _ => unreachable!(), | ||
48 | }; | ||
49 | // Iterate assoc types separately | ||
50 | // FIXME: complete T::AssocType | ||
51 | let krate = ctx.krate; | ||
52 | if let Some(krate) = krate { | ||
53 | let traits_in_scope = ctx.scope().traits_in_scope(); | ||
54 | ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| { | ||
55 | if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { | ||
56 | return None; | ||
57 | } | ||
58 | match item { | ||
59 | hir::AssocItem::Function(func) => { | ||
60 | if !func.has_self_param(ctx.db) { | ||
61 | acc.add_function(ctx, func, None); | ||
62 | } | ||
63 | } | ||
64 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), | ||
65 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), | ||
66 | } | ||
67 | None::<()> | ||
68 | }); | ||
69 | |||
70 | ty.iterate_impl_items(ctx.db, krate, |item| { | ||
71 | if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { | ||
72 | return None; | ||
73 | } | ||
74 | match item { | ||
75 | hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {} | ||
76 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), | ||
77 | } | ||
78 | None::<()> | ||
79 | }); | ||
80 | } | ||
81 | } | ||
82 | hir::ModuleDef::Trait(t) => { | ||
83 | for item in t.items(ctx.db) { | ||
84 | if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { | ||
85 | continue; | ||
86 | } | ||
87 | match item { | ||
88 | hir::AssocItem::Function(func) => { | ||
89 | if !func.has_self_param(ctx.db) { | ||
90 | acc.add_function(ctx, func, None); | ||
91 | } | ||
92 | } | ||
93 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), | ||
94 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), | ||
95 | } | ||
96 | } | ||
97 | } | ||
98 | _ => {} | ||
99 | }; | ||
100 | } | ||
101 | |||
102 | #[cfg(test)] | ||
103 | mod tests { | ||
104 | use test_utils::covers; | ||
105 | |||
106 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; | ||
107 | use insta::assert_debug_snapshot; | ||
108 | |||
109 | fn do_reference_completion(code: &str) -> Vec<CompletionItem> { | ||
110 | do_completion(code, CompletionKind::Reference) | ||
111 | } | ||
112 | |||
113 | #[test] | ||
114 | fn dont_complete_current_use() { | ||
115 | covers!(dont_complete_current_use); | ||
116 | let completions = do_completion(r"use self::foo<|>;", CompletionKind::Reference); | ||
117 | assert!(completions.is_empty()); | ||
118 | } | ||
119 | |||
120 | #[test] | ||
121 | fn dont_complete_current_use_in_braces_with_glob() { | ||
122 | let completions = do_completion( | ||
123 | r" | ||
124 | mod foo { pub struct S; } | ||
125 | use self::{foo::*, bar<|>}; | ||
126 | ", | ||
127 | CompletionKind::Reference, | ||
128 | ); | ||
129 | assert_eq!(completions.len(), 2); | ||
130 | } | ||
131 | |||
132 | #[test] | ||
133 | fn dont_complete_primitive_in_use() { | ||
134 | let completions = do_completion(r"use self::<|>;", CompletionKind::BuiltinType); | ||
135 | assert!(completions.is_empty()); | ||
136 | } | ||
137 | |||
138 | #[test] | ||
139 | fn dont_complete_primitive_in_module_scope() { | ||
140 | let completions = do_completion(r"fn foo() { self::<|> }", CompletionKind::BuiltinType); | ||
141 | assert!(completions.is_empty()); | ||
142 | } | ||
143 | |||
144 | #[test] | ||
145 | fn completes_primitives() { | ||
146 | let completions = | ||
147 | do_completion(r"fn main() { let _: <|> = 92; }", CompletionKind::BuiltinType); | ||
148 | assert_eq!(completions.len(), 17); | ||
149 | } | ||
150 | |||
151 | #[test] | ||
152 | fn completes_mod_with_docs() { | ||
153 | assert_debug_snapshot!( | ||
154 | do_reference_completion( | ||
155 | r" | ||
156 | use self::my<|>; | ||
157 | |||
158 | /// Some simple | ||
159 | /// docs describing `mod my`. | ||
160 | mod my { | ||
161 | struct Bar; | ||
162 | } | ||
163 | " | ||
164 | ), | ||
165 | @r###" | ||
166 | [ | ||
167 | CompletionItem { | ||
168 | label: "my", | ||
169 | source_range: [27; 29), | ||
170 | delete: [27; 29), | ||
171 | insert: "my", | ||
172 | kind: Module, | ||
173 | documentation: Documentation( | ||
174 | "Some simple\ndocs describing `mod my`.", | ||
175 | ), | ||
176 | }, | ||
177 | ] | ||
178 | "### | ||
179 | ); | ||
180 | } | ||
181 | |||
182 | #[test] | ||
183 | fn path_visibility() { | ||
184 | assert_debug_snapshot!( | ||
185 | do_reference_completion( | ||
186 | r" | ||
187 | use self::my::<|>; | ||
188 | |||
189 | mod my { | ||
190 | struct Bar; | ||
191 | pub struct Foo; | ||
192 | pub use Bar as PublicBar; | ||
193 | } | ||
194 | " | ||
195 | ), | ||
196 | @r###" | ||
197 | [ | ||
198 | CompletionItem { | ||
199 | label: "Foo", | ||
200 | source_range: [31; 31), | ||
201 | delete: [31; 31), | ||
202 | insert: "Foo", | ||
203 | kind: Struct, | ||
204 | }, | ||
205 | CompletionItem { | ||
206 | label: "PublicBar", | ||
207 | source_range: [31; 31), | ||
208 | delete: [31; 31), | ||
209 | insert: "PublicBar", | ||
210 | kind: Struct, | ||
211 | }, | ||
212 | ] | ||
213 | "### | ||
214 | ); | ||
215 | } | ||
216 | |||
217 | #[test] | ||
218 | fn completes_use_item_starting_with_self() { | ||
219 | assert_debug_snapshot!( | ||
220 | do_reference_completion( | ||
221 | r" | ||
222 | use self::m::<|>; | ||
223 | |||
224 | mod m { | ||
225 | pub struct Bar; | ||
226 | } | ||
227 | " | ||
228 | ), | ||
229 | @r###" | ||
230 | [ | ||
231 | CompletionItem { | ||
232 | label: "Bar", | ||
233 | source_range: [30; 30), | ||
234 | delete: [30; 30), | ||
235 | insert: "Bar", | ||
236 | kind: Struct, | ||
237 | }, | ||
238 | ] | ||
239 | "### | ||
240 | ); | ||
241 | } | ||
242 | |||
243 | #[test] | ||
244 | fn completes_use_item_starting_with_crate() { | ||
245 | assert_debug_snapshot!( | ||
246 | do_reference_completion( | ||
247 | " | ||
248 | //- /lib.rs | ||
249 | mod foo; | ||
250 | struct Spam; | ||
251 | //- /foo.rs | ||
252 | use crate::Sp<|> | ||
253 | " | ||
254 | ), | ||
255 | @r###" | ||
256 | [ | ||
257 | CompletionItem { | ||
258 | label: "Spam", | ||
259 | source_range: [11; 13), | ||
260 | delete: [11; 13), | ||
261 | insert: "Spam", | ||
262 | kind: Struct, | ||
263 | }, | ||
264 | CompletionItem { | ||
265 | label: "foo", | ||
266 | source_range: [11; 13), | ||
267 | delete: [11; 13), | ||
268 | insert: "foo", | ||
269 | kind: Module, | ||
270 | }, | ||
271 | ] | ||
272 | "### | ||
273 | ); | ||
274 | } | ||
275 | |||
276 | #[test] | ||
277 | fn completes_nested_use_tree() { | ||
278 | assert_debug_snapshot!( | ||
279 | do_reference_completion( | ||
280 | " | ||
281 | //- /lib.rs | ||
282 | mod foo; | ||
283 | struct Spam; | ||
284 | //- /foo.rs | ||
285 | use crate::{Sp<|>}; | ||
286 | " | ||
287 | ), | ||
288 | @r###" | ||
289 | [ | ||
290 | CompletionItem { | ||
291 | label: "Spam", | ||
292 | source_range: [12; 14), | ||
293 | delete: [12; 14), | ||
294 | insert: "Spam", | ||
295 | kind: Struct, | ||
296 | }, | ||
297 | CompletionItem { | ||
298 | label: "foo", | ||
299 | source_range: [12; 14), | ||
300 | delete: [12; 14), | ||
301 | insert: "foo", | ||
302 | kind: Module, | ||
303 | }, | ||
304 | ] | ||
305 | "### | ||
306 | ); | ||
307 | } | ||
308 | |||
309 | #[test] | ||
310 | fn completes_deeply_nested_use_tree() { | ||
311 | assert_debug_snapshot!( | ||
312 | do_reference_completion( | ||
313 | " | ||
314 | //- /lib.rs | ||
315 | mod foo; | ||
316 | pub mod bar { | ||
317 | pub mod baz { | ||
318 | pub struct Spam; | ||
319 | } | ||
320 | } | ||
321 | //- /foo.rs | ||
322 | use crate::{bar::{baz::Sp<|>}}; | ||
323 | " | ||
324 | ), | ||
325 | @r###" | ||
326 | [ | ||
327 | CompletionItem { | ||
328 | label: "Spam", | ||
329 | source_range: [23; 25), | ||
330 | delete: [23; 25), | ||
331 | insert: "Spam", | ||
332 | kind: Struct, | ||
333 | }, | ||
334 | ] | ||
335 | "### | ||
336 | ); | ||
337 | } | ||
338 | |||
339 | #[test] | ||
340 | fn completes_enum_variant() { | ||
341 | assert_debug_snapshot!( | ||
342 | do_reference_completion( | ||
343 | " | ||
344 | //- /lib.rs | ||
345 | /// An enum | ||
346 | enum E { | ||
347 | /// Foo Variant | ||
348 | Foo, | ||
349 | /// Bar Variant with i32 | ||
350 | Bar(i32) | ||
351 | } | ||
352 | fn foo() { let _ = E::<|> } | ||
353 | " | ||
354 | ), | ||
355 | @r###" | ||
356 | [ | ||
357 | CompletionItem { | ||
358 | label: "Bar(…)", | ||
359 | source_range: [116; 116), | ||
360 | delete: [116; 116), | ||
361 | insert: "Bar($0)", | ||
362 | kind: EnumVariant, | ||
363 | lookup: "Bar", | ||
364 | detail: "(i32)", | ||
365 | documentation: Documentation( | ||
366 | "Bar Variant with i32", | ||
367 | ), | ||
368 | trigger_call_info: true, | ||
369 | }, | ||
370 | CompletionItem { | ||
371 | label: "Foo", | ||
372 | source_range: [116; 116), | ||
373 | delete: [116; 116), | ||
374 | insert: "Foo", | ||
375 | kind: EnumVariant, | ||
376 | detail: "()", | ||
377 | documentation: Documentation( | ||
378 | "Foo Variant", | ||
379 | ), | ||
380 | }, | ||
381 | ] | ||
382 | "### | ||
383 | ); | ||
384 | } | ||
385 | |||
386 | #[test] | ||
387 | fn completes_enum_variant_with_details() { | ||
388 | assert_debug_snapshot!( | ||
389 | do_reference_completion( | ||
390 | " | ||
391 | //- /lib.rs | ||
392 | struct S { field: u32 } | ||
393 | /// An enum | ||
394 | enum E { | ||
395 | /// Foo Variant (empty) | ||
396 | Foo, | ||
397 | /// Bar Variant with i32 and u32 | ||
398 | Bar(i32, u32), | ||
399 | /// | ||
400 | S(S), | ||
401 | } | ||
402 | fn foo() { let _ = E::<|> } | ||
403 | " | ||
404 | ), | ||
405 | @r###" | ||
406 | [ | ||
407 | CompletionItem { | ||
408 | label: "Bar(…)", | ||
409 | source_range: [180; 180), | ||
410 | delete: [180; 180), | ||
411 | insert: "Bar($0)", | ||
412 | kind: EnumVariant, | ||
413 | lookup: "Bar", | ||
414 | detail: "(i32, u32)", | ||
415 | documentation: Documentation( | ||
416 | "Bar Variant with i32 and u32", | ||
417 | ), | ||
418 | trigger_call_info: true, | ||
419 | }, | ||
420 | CompletionItem { | ||
421 | label: "Foo", | ||
422 | source_range: [180; 180), | ||
423 | delete: [180; 180), | ||
424 | insert: "Foo", | ||
425 | kind: EnumVariant, | ||
426 | detail: "()", | ||
427 | documentation: Documentation( | ||
428 | "Foo Variant (empty)", | ||
429 | ), | ||
430 | }, | ||
431 | CompletionItem { | ||
432 | label: "S(…)", | ||
433 | source_range: [180; 180), | ||
434 | delete: [180; 180), | ||
435 | insert: "S($0)", | ||
436 | kind: EnumVariant, | ||
437 | lookup: "S", | ||
438 | detail: "(S)", | ||
439 | documentation: Documentation( | ||
440 | "", | ||
441 | ), | ||
442 | trigger_call_info: true, | ||
443 | }, | ||
444 | ] | ||
445 | "### | ||
446 | ); | ||
447 | } | ||
448 | |||
449 | #[test] | ||
450 | fn completes_struct_associated_method() { | ||
451 | assert_debug_snapshot!( | ||
452 | do_reference_completion( | ||
453 | " | ||
454 | //- /lib.rs | ||
455 | /// A Struct | ||
456 | struct S; | ||
457 | |||
458 | impl S { | ||
459 | /// An associated method | ||
460 | fn m() { } | ||
461 | } | ||
462 | |||
463 | fn foo() { let _ = S::<|> } | ||
464 | " | ||
465 | ), | ||
466 | @r###" | ||
467 | [ | ||
468 | CompletionItem { | ||
469 | label: "m()", | ||
470 | source_range: [100; 100), | ||
471 | delete: [100; 100), | ||
472 | insert: "m()$0", | ||
473 | kind: Function, | ||
474 | lookup: "m", | ||
475 | detail: "fn m()", | ||
476 | documentation: Documentation( | ||
477 | "An associated method", | ||
478 | ), | ||
479 | }, | ||
480 | ] | ||
481 | "### | ||
482 | ); | ||
483 | } | ||
484 | |||
485 | #[test] | ||
486 | fn completes_struct_associated_const() { | ||
487 | assert_debug_snapshot!( | ||
488 | do_reference_completion( | ||
489 | " | ||
490 | //- /lib.rs | ||
491 | /// A Struct | ||
492 | struct S; | ||
493 | |||
494 | impl S { | ||
495 | /// An associated const | ||
496 | const C: i32 = 42; | ||
497 | } | ||
498 | |||
499 | fn foo() { let _ = S::<|> } | ||
500 | " | ||
501 | ), | ||
502 | @r###" | ||
503 | [ | ||
504 | CompletionItem { | ||
505 | label: "C", | ||
506 | source_range: [107; 107), | ||
507 | delete: [107; 107), | ||
508 | insert: "C", | ||
509 | kind: Const, | ||
510 | detail: "const C: i32 = 42;", | ||
511 | documentation: Documentation( | ||
512 | "An associated const", | ||
513 | ), | ||
514 | }, | ||
515 | ] | ||
516 | "### | ||
517 | ); | ||
518 | } | ||
519 | |||
520 | #[test] | ||
521 | fn completes_struct_associated_type() { | ||
522 | assert_debug_snapshot!( | ||
523 | do_reference_completion( | ||
524 | " | ||
525 | //- /lib.rs | ||
526 | /// A Struct | ||
527 | struct S; | ||
528 | |||
529 | impl S { | ||
530 | /// An associated type | ||
531 | type T = i32; | ||
532 | } | ||
533 | |||
534 | fn foo() { let _ = S::<|> } | ||
535 | " | ||
536 | ), | ||
537 | @r###" | ||
538 | [ | ||
539 | CompletionItem { | ||
540 | label: "T", | ||
541 | source_range: [101; 101), | ||
542 | delete: [101; 101), | ||
543 | insert: "T", | ||
544 | kind: TypeAlias, | ||
545 | detail: "type T = i32;", | ||
546 | documentation: Documentation( | ||
547 | "An associated type", | ||
548 | ), | ||
549 | }, | ||
550 | ] | ||
551 | "### | ||
552 | ); | ||
553 | } | ||
554 | |||
555 | #[test] | ||
556 | fn associated_item_visibility() { | ||
557 | assert_debug_snapshot!( | ||
558 | do_reference_completion( | ||
559 | " | ||
560 | //- /lib.rs | ||
561 | struct S; | ||
562 | |||
563 | mod m { | ||
564 | impl super::S { | ||
565 | pub(super) fn public_method() { } | ||
566 | fn private_method() { } | ||
567 | pub(super) type PublicType = u32; | ||
568 | type PrivateType = u32; | ||
569 | pub(super) const PUBLIC_CONST: u32 = 1; | ||
570 | const PRIVATE_CONST: u32 = 1; | ||
571 | } | ||
572 | } | ||
573 | |||
574 | fn foo() { let _ = S::<|> } | ||
575 | " | ||
576 | ), | ||
577 | @r###" | ||
578 | [ | ||
579 | CompletionItem { | ||
580 | label: "PUBLIC_CONST", | ||
581 | source_range: [302; 302), | ||
582 | delete: [302; 302), | ||
583 | insert: "PUBLIC_CONST", | ||
584 | kind: Const, | ||
585 | detail: "pub(super) const PUBLIC_CONST: u32 = 1;", | ||
586 | }, | ||
587 | CompletionItem { | ||
588 | label: "PublicType", | ||
589 | source_range: [302; 302), | ||
590 | delete: [302; 302), | ||
591 | insert: "PublicType", | ||
592 | kind: TypeAlias, | ||
593 | detail: "pub(super) type PublicType = u32;", | ||
594 | }, | ||
595 | CompletionItem { | ||
596 | label: "public_method()", | ||
597 | source_range: [302; 302), | ||
598 | delete: [302; 302), | ||
599 | insert: "public_method()$0", | ||
600 | kind: Function, | ||
601 | lookup: "public_method", | ||
602 | detail: "pub(super) fn public_method()", | ||
603 | }, | ||
604 | ] | ||
605 | "### | ||
606 | ); | ||
607 | } | ||
608 | |||
609 | #[test] | ||
610 | fn completes_enum_associated_method() { | ||
611 | assert_debug_snapshot!( | ||
612 | do_reference_completion( | ||
613 | " | ||
614 | //- /lib.rs | ||
615 | /// An enum | ||
616 | enum S {}; | ||
617 | |||
618 | impl S { | ||
619 | /// An associated method | ||
620 | fn m() { } | ||
621 | } | ||
622 | |||
623 | fn foo() { let _ = S::<|> } | ||
624 | " | ||
625 | ), | ||
626 | @r###" | ||
627 | [ | ||
628 | CompletionItem { | ||
629 | label: "m()", | ||
630 | source_range: [100; 100), | ||
631 | delete: [100; 100), | ||
632 | insert: "m()$0", | ||
633 | kind: Function, | ||
634 | lookup: "m", | ||
635 | detail: "fn m()", | ||
636 | documentation: Documentation( | ||
637 | "An associated method", | ||
638 | ), | ||
639 | }, | ||
640 | ] | ||
641 | "### | ||
642 | ); | ||
643 | } | ||
644 | |||
645 | #[test] | ||
646 | fn completes_union_associated_method() { | ||
647 | assert_debug_snapshot!( | ||
648 | do_reference_completion( | ||
649 | " | ||
650 | //- /lib.rs | ||
651 | /// A union | ||
652 | union U {}; | ||
653 | |||
654 | impl U { | ||
655 | /// An associated method | ||
656 | fn m() { } | ||
657 | } | ||
658 | |||
659 | fn foo() { let _ = U::<|> } | ||
660 | " | ||
661 | ), | ||
662 | @r###" | ||
663 | [ | ||
664 | CompletionItem { | ||
665 | label: "m()", | ||
666 | source_range: [101; 101), | ||
667 | delete: [101; 101), | ||
668 | insert: "m()$0", | ||
669 | kind: Function, | ||
670 | lookup: "m", | ||
671 | detail: "fn m()", | ||
672 | documentation: Documentation( | ||
673 | "An associated method", | ||
674 | ), | ||
675 | }, | ||
676 | ] | ||
677 | "### | ||
678 | ); | ||
679 | } | ||
680 | |||
681 | #[test] | ||
682 | fn completes_use_paths_across_crates() { | ||
683 | assert_debug_snapshot!( | ||
684 | do_reference_completion( | ||
685 | " | ||
686 | //- /main.rs | ||
687 | use foo::<|>; | ||
688 | |||
689 | //- /foo/lib.rs | ||
690 | pub mod bar { | ||
691 | pub struct S; | ||
692 | } | ||
693 | " | ||
694 | ), | ||
695 | @r###" | ||
696 | [ | ||
697 | CompletionItem { | ||
698 | label: "bar", | ||
699 | source_range: [9; 9), | ||
700 | delete: [9; 9), | ||
701 | insert: "bar", | ||
702 | kind: Module, | ||
703 | }, | ||
704 | ] | ||
705 | "### | ||
706 | ); | ||
707 | } | ||
708 | |||
709 | #[test] | ||
710 | fn completes_trait_associated_method_1() { | ||
711 | assert_debug_snapshot!( | ||
712 | do_reference_completion( | ||
713 | " | ||
714 | //- /lib.rs | ||
715 | trait Trait { | ||
716 | /// A trait method | ||
717 | fn m(); | ||
718 | } | ||
719 | |||
720 | fn foo() { let _ = Trait::<|> } | ||
721 | " | ||
722 | ), | ||
723 | @r###" | ||
724 | [ | ||
725 | CompletionItem { | ||
726 | label: "m()", | ||
727 | source_range: [73; 73), | ||
728 | delete: [73; 73), | ||
729 | insert: "m()$0", | ||
730 | kind: Function, | ||
731 | lookup: "m", | ||
732 | detail: "fn m()", | ||
733 | documentation: Documentation( | ||
734 | "A trait method", | ||
735 | ), | ||
736 | }, | ||
737 | ] | ||
738 | "### | ||
739 | ); | ||
740 | } | ||
741 | |||
742 | #[test] | ||
743 | fn completes_trait_associated_method_2() { | ||
744 | assert_debug_snapshot!( | ||
745 | do_reference_completion( | ||
746 | " | ||
747 | //- /lib.rs | ||
748 | trait Trait { | ||
749 | /// A trait method | ||
750 | fn m(); | ||
751 | } | ||
752 | |||
753 | struct S; | ||
754 | impl Trait for S {} | ||
755 | |||
756 | fn foo() { let _ = S::<|> } | ||
757 | " | ||
758 | ), | ||
759 | @r###" | ||
760 | [ | ||
761 | CompletionItem { | ||
762 | label: "m()", | ||
763 | source_range: [99; 99), | ||
764 | delete: [99; 99), | ||
765 | insert: "m()$0", | ||
766 | kind: Function, | ||
767 | lookup: "m", | ||
768 | detail: "fn m()", | ||
769 | documentation: Documentation( | ||
770 | "A trait method", | ||
771 | ), | ||
772 | }, | ||
773 | ] | ||
774 | "### | ||
775 | ); | ||
776 | } | ||
777 | |||
778 | #[test] | ||
779 | fn completes_trait_associated_method_3() { | ||
780 | assert_debug_snapshot!( | ||
781 | do_reference_completion( | ||
782 | " | ||
783 | //- /lib.rs | ||
784 | trait Trait { | ||
785 | /// A trait method | ||
786 | fn m(); | ||
787 | } | ||
788 | |||
789 | struct S; | ||
790 | impl Trait for S {} | ||
791 | |||
792 | fn foo() { let _ = <S as Trait>::<|> } | ||
793 | " | ||
794 | ), | ||
795 | @r###" | ||
796 | [ | ||
797 | CompletionItem { | ||
798 | label: "m()", | ||
799 | source_range: [110; 110), | ||
800 | delete: [110; 110), | ||
801 | insert: "m()$0", | ||
802 | kind: Function, | ||
803 | lookup: "m", | ||
804 | detail: "fn m()", | ||
805 | documentation: Documentation( | ||
806 | "A trait method", | ||
807 | ), | ||
808 | }, | ||
809 | ] | ||
810 | "### | ||
811 | ); | ||
812 | } | ||
813 | |||
814 | #[test] | ||
815 | fn completes_type_alias() { | ||
816 | assert_debug_snapshot!( | ||
817 | do_reference_completion( | ||
818 | " | ||
819 | struct S; | ||
820 | impl S { fn foo() {} } | ||
821 | type T = S; | ||
822 | impl T { fn bar() {} } | ||
823 | |||
824 | fn main() { | ||
825 | T::<|>; | ||
826 | } | ||
827 | " | ||
828 | ), | ||
829 | @r###" | ||
830 | [ | ||
831 | CompletionItem { | ||
832 | label: "bar()", | ||
833 | source_range: [185; 185), | ||
834 | delete: [185; 185), | ||
835 | insert: "bar()$0", | ||
836 | kind: Function, | ||
837 | lookup: "bar", | ||
838 | detail: "fn bar()", | ||
839 | }, | ||
840 | CompletionItem { | ||
841 | label: "foo()", | ||
842 | source_range: [185; 185), | ||
843 | delete: [185; 185), | ||
844 | insert: "foo()$0", | ||
845 | kind: Function, | ||
846 | lookup: "foo", | ||
847 | detail: "fn foo()", | ||
848 | }, | ||
849 | ] | ||
850 | "### | ||
851 | ); | ||
852 | } | ||
853 | |||
854 | #[test] | ||
855 | fn completes_qualified_macros() { | ||
856 | assert_debug_snapshot!( | ||
857 | do_reference_completion( | ||
858 | " | ||
859 | #[macro_export] | ||
860 | macro_rules! foo { | ||
861 | () => {} | ||
862 | } | ||
863 | |||
864 | fn main() { | ||
865 | let _ = crate::<|> | ||
866 | } | ||
867 | " | ||
868 | ), | ||
869 | @r###" | ||
870 | [ | ||
871 | CompletionItem { | ||
872 | label: "foo!", | ||
873 | source_range: [179; 179), | ||
874 | delete: [179; 179), | ||
875 | insert: "foo!($0)", | ||
876 | kind: Macro, | ||
877 | detail: "#[macro_export]\nmacro_rules! foo", | ||
878 | }, | ||
879 | CompletionItem { | ||
880 | label: "main()", | ||
881 | source_range: [179; 179), | ||
882 | delete: [179; 179), | ||
883 | insert: "main()$0", | ||
884 | kind: Function, | ||
885 | lookup: "main", | ||
886 | detail: "fn main()", | ||
887 | }, | ||
888 | ] | ||
889 | "### | ||
890 | ); | ||
891 | } | ||
892 | |||
893 | #[test] | ||
894 | fn completes_reexported_items_under_correct_name() { | ||
895 | assert_debug_snapshot!( | ||
896 | do_reference_completion( | ||
897 | r" | ||
898 | fn foo() { | ||
899 | self::m::<|> | ||
900 | } | ||
901 | |||
902 | mod m { | ||
903 | pub use super::p::wrong_fn as right_fn; | ||
904 | pub use super::p::WRONG_CONST as RIGHT_CONST; | ||
905 | pub use super::p::WrongType as RightType; | ||
906 | } | ||
907 | mod p { | ||
908 | fn wrong_fn() {} | ||
909 | const WRONG_CONST: u32 = 1; | ||
910 | struct WrongType {}; | ||
911 | } | ||
912 | " | ||
913 | ), | ||
914 | @r###" | ||
915 | [ | ||
916 | CompletionItem { | ||
917 | label: "RIGHT_CONST", | ||
918 | source_range: [57; 57), | ||
919 | delete: [57; 57), | ||
920 | insert: "RIGHT_CONST", | ||
921 | kind: Const, | ||
922 | }, | ||
923 | CompletionItem { | ||
924 | label: "RightType", | ||
925 | source_range: [57; 57), | ||
926 | delete: [57; 57), | ||
927 | insert: "RightType", | ||
928 | kind: Struct, | ||
929 | }, | ||
930 | CompletionItem { | ||
931 | label: "right_fn()", | ||
932 | source_range: [57; 57), | ||
933 | delete: [57; 57), | ||
934 | insert: "right_fn()$0", | ||
935 | kind: Function, | ||
936 | lookup: "right_fn", | ||
937 | detail: "fn wrong_fn()", | ||
938 | }, | ||
939 | ] | ||
940 | "### | ||
941 | ); | ||
942 | } | ||
943 | |||
944 | #[test] | ||
945 | fn completes_in_simple_macro_call() { | ||
946 | let completions = do_reference_completion( | ||
947 | r#" | ||
948 | macro_rules! m { ($e:expr) => { $e } } | ||
949 | fn main() { m!(self::f<|>); } | ||
950 | fn foo() {} | ||
951 | "#, | ||
952 | ); | ||
953 | assert_debug_snapshot!(completions, @r###" | ||
954 | [ | ||
955 | CompletionItem { | ||
956 | label: "foo()", | ||
957 | source_range: [93; 94), | ||
958 | delete: [93; 94), | ||
959 | insert: "foo()$0", | ||
960 | kind: Function, | ||
961 | lookup: "foo", | ||
962 | detail: "fn foo()", | ||
963 | }, | ||
964 | CompletionItem { | ||
965 | label: "main()", | ||
966 | source_range: [93; 94), | ||
967 | delete: [93; 94), | ||
968 | insert: "main()$0", | ||
969 | kind: Function, | ||
970 | lookup: "main", | ||
971 | detail: "fn main()", | ||
972 | }, | ||
973 | ] | ||
974 | "###); | ||
975 | } | ||
976 | |||
977 | #[test] | ||
978 | fn function_mod_share_name() { | ||
979 | assert_debug_snapshot!( | ||
980 | do_reference_completion( | ||
981 | r" | ||
982 | fn foo() { | ||
983 | self::m::<|> | ||
984 | } | ||
985 | |||
986 | mod m { | ||
987 | pub mod z {} | ||
988 | pub fn z() {} | ||
989 | } | ||
990 | ", | ||
991 | ), | ||
992 | @r###" | ||
993 | [ | ||
994 | CompletionItem { | ||
995 | label: "z", | ||
996 | source_range: [57; 57), | ||
997 | delete: [57; 57), | ||
998 | insert: "z", | ||
999 | kind: Module, | ||
1000 | }, | ||
1001 | CompletionItem { | ||
1002 | label: "z()", | ||
1003 | source_range: [57; 57), | ||
1004 | delete: [57; 57), | ||
1005 | insert: "z()$0", | ||
1006 | kind: Function, | ||
1007 | lookup: "z", | ||
1008 | detail: "pub fn z()", | ||
1009 | }, | ||
1010 | ] | ||
1011 | "### | ||
1012 | ); | ||
1013 | } | ||
1014 | |||
1015 | #[test] | ||
1016 | fn completes_hashmap_new() { | ||
1017 | assert_debug_snapshot!( | ||
1018 | do_reference_completion( | ||
1019 | r" | ||
1020 | struct RandomState; | ||
1021 | struct HashMap<K, V, S = RandomState> {} | ||
1022 | |||
1023 | impl<K, V> HashMap<K, V, RandomState> { | ||
1024 | pub fn new() -> HashMap<K, V, RandomState> { } | ||
1025 | } | ||
1026 | fn foo() { | ||
1027 | HashMap::<|> | ||
1028 | } | ||
1029 | " | ||
1030 | ), | ||
1031 | @r###" | ||
1032 | [ | ||
1033 | CompletionItem { | ||
1034 | label: "new()", | ||
1035 | source_range: [292; 292), | ||
1036 | delete: [292; 292), | ||
1037 | insert: "new()$0", | ||
1038 | kind: Function, | ||
1039 | lookup: "new", | ||
1040 | detail: "pub fn new() -> HashMap<K, V, RandomState>", | ||
1041 | }, | ||
1042 | ] | ||
1043 | "### | ||
1044 | ); | ||
1045 | } | ||
1046 | } | ||