aboutsummaryrefslogtreecommitdiff
path: root/crates/assists/src/handlers/qualify_path.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/assists/src/handlers/qualify_path.rs')
-rw-r--r--crates/assists/src/handlers/qualify_path.rs1212
1 files changed, 0 insertions, 1212 deletions
diff --git a/crates/assists/src/handlers/qualify_path.rs b/crates/assists/src/handlers/qualify_path.rs
deleted file mode 100644
index a7d9fd4dc..000000000
--- a/crates/assists/src/handlers/qualify_path.rs
+++ /dev/null
@@ -1,1212 +0,0 @@
1use std::iter;
2
3use hir::AsName;
4use ide_db::helpers::{
5 import_assets::{ImportAssets, ImportCandidate},
6 mod_path_to_ast,
7};
8use ide_db::RootDatabase;
9use syntax::{
10 ast,
11 ast::{make, ArgListOwner},
12 AstNode,
13};
14use test_utils::mark;
15
16use crate::{
17 assist_context::{AssistContext, Assists},
18 AssistId, AssistKind, GroupLabel,
19};
20
21// Assist: qualify_path
22//
23// If the name is unresolved, provides all possible qualified paths for it.
24//
25// ```
26// fn main() {
27// let map = HashMap$0::new();
28// }
29// # pub mod std { pub mod collections { pub struct HashMap { } } }
30// ```
31// ->
32// ```
33// fn main() {
34// let map = std::collections::HashMap::new();
35// }
36// # pub mod std { pub mod collections { pub struct HashMap { } } }
37// ```
38pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
39 let import_assets =
40 if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::<ast::Path>() {
41 ImportAssets::for_regular_path(path_under_caret, &ctx.sema)
42 } else if let Some(method_under_caret) =
43 ctx.find_node_at_offset_with_descend::<ast::MethodCallExpr>()
44 {
45 ImportAssets::for_method_call(method_under_caret, &ctx.sema)
46 } else {
47 None
48 }?;
49 let proposed_imports = import_assets.search_for_relative_paths(&ctx.sema);
50 if proposed_imports.is_empty() {
51 return None;
52 }
53
54 let candidate = import_assets.import_candidate();
55 let range = ctx.sema.original_range(import_assets.syntax_under_caret()).range;
56
57 let qualify_candidate = match candidate {
58 ImportCandidate::Path(candidate) => {
59 if candidate.qualifier.is_some() {
60 mark::hit!(qualify_path_qualifier_start);
61 let path = ast::Path::cast(import_assets.syntax_under_caret().clone())?;
62 let (prev_segment, segment) = (path.qualifier()?.segment()?, path.segment()?);
63 QualifyCandidate::QualifierStart(segment, prev_segment.generic_arg_list())
64 } else {
65 mark::hit!(qualify_path_unqualified_name);
66 let path = ast::Path::cast(import_assets.syntax_under_caret().clone())?;
67 let generics = path.segment()?.generic_arg_list();
68 QualifyCandidate::UnqualifiedName(generics)
69 }
70 }
71 ImportCandidate::TraitAssocItem(_) => {
72 mark::hit!(qualify_path_trait_assoc_item);
73 let path = ast::Path::cast(import_assets.syntax_under_caret().clone())?;
74 let (qualifier, segment) = (path.qualifier()?, path.segment()?);
75 QualifyCandidate::TraitAssocItem(qualifier, segment)
76 }
77 ImportCandidate::TraitMethod(_) => {
78 mark::hit!(qualify_path_trait_method);
79 let mcall_expr = ast::MethodCallExpr::cast(import_assets.syntax_under_caret().clone())?;
80 QualifyCandidate::TraitMethod(ctx.sema.db, mcall_expr)
81 }
82 };
83
84 let group_label = group_label(candidate);
85 for (import, item) in proposed_imports {
86 acc.add_group(
87 &group_label,
88 AssistId("qualify_path", AssistKind::QuickFix),
89 label(candidate, &import),
90 range,
91 |builder| {
92 qualify_candidate.qualify(
93 |replace_with: String| builder.replace(range, replace_with),
94 import,
95 item,
96 )
97 },
98 );
99 }
100 Some(())
101}
102
103enum QualifyCandidate<'db> {
104 QualifierStart(ast::PathSegment, Option<ast::GenericArgList>),
105 UnqualifiedName(Option<ast::GenericArgList>),
106 TraitAssocItem(ast::Path, ast::PathSegment),
107 TraitMethod(&'db RootDatabase, ast::MethodCallExpr),
108}
109
110impl QualifyCandidate<'_> {
111 fn qualify(&self, mut replacer: impl FnMut(String), import: hir::ModPath, item: hir::ItemInNs) {
112 let import = mod_path_to_ast(&import);
113 match self {
114 QualifyCandidate::QualifierStart(segment, generics) => {
115 let generics = generics.as_ref().map_or_else(String::new, ToString::to_string);
116 replacer(format!("{}{}::{}", import, generics, segment));
117 }
118 QualifyCandidate::UnqualifiedName(generics) => {
119 let generics = generics.as_ref().map_or_else(String::new, ToString::to_string);
120 replacer(format!("{}{}", import.to_string(), generics));
121 }
122 QualifyCandidate::TraitAssocItem(qualifier, segment) => {
123 replacer(format!("<{} as {}>::{}", qualifier, import, segment));
124 }
125 &QualifyCandidate::TraitMethod(db, ref mcall_expr) => {
126 Self::qualify_trait_method(db, mcall_expr, replacer, import, item);
127 }
128 }
129 }
130
131 fn qualify_trait_method(
132 db: &RootDatabase,
133 mcall_expr: &ast::MethodCallExpr,
134 mut replacer: impl FnMut(String),
135 import: ast::Path,
136 item: hir::ItemInNs,
137 ) -> Option<()> {
138 let receiver = mcall_expr.receiver()?;
139 let trait_method_name = mcall_expr.name_ref()?;
140 let generics =
141 mcall_expr.generic_arg_list().as_ref().map_or_else(String::new, ToString::to_string);
142 let arg_list = mcall_expr.arg_list().map(|arg_list| arg_list.args());
143 let trait_ = item_as_trait(item)?;
144 let method = find_trait_method(db, trait_, &trait_method_name)?;
145 if let Some(self_access) = method.self_param(db).map(|sp| sp.access(db)) {
146 let receiver = match self_access {
147 hir::Access::Shared => make::expr_ref(receiver, false),
148 hir::Access::Exclusive => make::expr_ref(receiver, true),
149 hir::Access::Owned => receiver,
150 };
151 replacer(format!(
152 "{}::{}{}{}",
153 import,
154 trait_method_name,
155 generics,
156 match arg_list {
157 Some(args) => make::arg_list(iter::once(receiver).chain(args)),
158 None => make::arg_list(iter::once(receiver)),
159 }
160 ));
161 }
162 Some(())
163 }
164}
165
166fn find_trait_method(
167 db: &RootDatabase,
168 trait_: hir::Trait,
169 trait_method_name: &ast::NameRef,
170) -> Option<hir::Function> {
171 if let Some(hir::AssocItem::Function(method)) =
172 trait_.items(db).into_iter().find(|item: &hir::AssocItem| {
173 item.name(db).map(|name| name == trait_method_name.as_name()).unwrap_or(false)
174 })
175 {
176 Some(method)
177 } else {
178 None
179 }
180}
181
182fn item_as_trait(item: hir::ItemInNs) -> Option<hir::Trait> {
183 if let hir::ModuleDef::Trait(trait_) = hir::ModuleDef::from(item.as_module_def_id()?) {
184 Some(trait_)
185 } else {
186 None
187 }
188}
189
190fn group_label(candidate: &ImportCandidate) -> GroupLabel {
191 let name = match candidate {
192 ImportCandidate::Path(it) => &it.name,
193 ImportCandidate::TraitAssocItem(it) | ImportCandidate::TraitMethod(it) => &it.name,
194 };
195 GroupLabel(format!("Qualify {}", name))
196}
197
198fn label(candidate: &ImportCandidate, import: &hir::ModPath) -> String {
199 match candidate {
200 ImportCandidate::Path(candidate) => {
201 if candidate.qualifier.is_some() {
202 format!("Qualify with `{}`", &import)
203 } else {
204 format!("Qualify as `{}`", &import)
205 }
206 }
207 ImportCandidate::TraitAssocItem(_) => format!("Qualify `{}`", &import),
208 ImportCandidate::TraitMethod(_) => format!("Qualify with cast as `{}`", &import),
209 }
210}
211
212#[cfg(test)]
213mod tests {
214 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
215
216 use super::*;
217
218 #[test]
219 fn applicable_when_found_an_import_partial() {
220 mark::check!(qualify_path_unqualified_name);
221 check_assist(
222 qualify_path,
223 r"
224 mod std {
225 pub mod fmt {
226 pub struct Formatter;
227 }
228 }
229
230 use std::fmt;
231
232 $0Formatter
233 ",
234 r"
235 mod std {
236 pub mod fmt {
237 pub struct Formatter;
238 }
239 }
240
241 use std::fmt;
242
243 fmt::Formatter
244 ",
245 );
246 }
247
248 #[test]
249 fn applicable_when_found_an_import() {
250 check_assist(
251 qualify_path,
252 r"
253 $0PubStruct
254
255 pub mod PubMod {
256 pub struct PubStruct;
257 }
258 ",
259 r"
260 PubMod::PubStruct
261
262 pub mod PubMod {
263 pub struct PubStruct;
264 }
265 ",
266 );
267 }
268
269 #[test]
270 fn applicable_in_macros() {
271 check_assist(
272 qualify_path,
273 r"
274 macro_rules! foo {
275 ($i:ident) => { fn foo(a: $i) {} }
276 }
277 foo!(Pub$0Struct);
278
279 pub mod PubMod {
280 pub struct PubStruct;
281 }
282 ",
283 r"
284 macro_rules! foo {
285 ($i:ident) => { fn foo(a: $i) {} }
286 }
287 foo!(PubMod::PubStruct);
288
289 pub mod PubMod {
290 pub struct PubStruct;
291 }
292 ",
293 );
294 }
295
296 #[test]
297 fn applicable_when_found_multiple_imports() {
298 check_assist(
299 qualify_path,
300 r"
301 PubSt$0ruct
302
303 pub mod PubMod1 {
304 pub struct PubStruct;
305 }
306 pub mod PubMod2 {
307 pub struct PubStruct;
308 }
309 pub mod PubMod3 {
310 pub struct PubStruct;
311 }
312 ",
313 r"
314 PubMod3::PubStruct
315
316 pub mod PubMod1 {
317 pub struct PubStruct;
318 }
319 pub mod PubMod2 {
320 pub struct PubStruct;
321 }
322 pub mod PubMod3 {
323 pub struct PubStruct;
324 }
325 ",
326 );
327 }
328
329 #[test]
330 fn not_applicable_for_already_imported_types() {
331 check_assist_not_applicable(
332 qualify_path,
333 r"
334 use PubMod::PubStruct;
335
336 PubStruct$0
337
338 pub mod PubMod {
339 pub struct PubStruct;
340 }
341 ",
342 );
343 }
344
345 #[test]
346 fn not_applicable_for_types_with_private_paths() {
347 check_assist_not_applicable(
348 qualify_path,
349 r"
350 PrivateStruct$0
351
352 pub mod PubMod {
353 struct PrivateStruct;
354 }
355 ",
356 );
357 }
358
359 #[test]
360 fn not_applicable_when_no_imports_found() {
361 check_assist_not_applicable(
362 qualify_path,
363 "
364 PubStruct$0",
365 );
366 }
367
368 #[test]
369 fn not_applicable_in_import_statements() {
370 check_assist_not_applicable(
371 qualify_path,
372 r"
373 use PubStruct$0;
374
375 pub mod PubMod {
376 pub struct PubStruct;
377 }",
378 );
379 }
380
381 #[test]
382 fn qualify_function() {
383 check_assist(
384 qualify_path,
385 r"
386 test_function$0
387
388 pub mod PubMod {
389 pub fn test_function() {};
390 }
391 ",
392 r"
393 PubMod::test_function
394
395 pub mod PubMod {
396 pub fn test_function() {};
397 }
398 ",
399 );
400 }
401
402 #[test]
403 fn qualify_macro() {
404 check_assist(
405 qualify_path,
406 r"
407//- /lib.rs crate:crate_with_macro
408#[macro_export]
409macro_rules! foo {
410 () => ()
411}
412
413//- /main.rs crate:main deps:crate_with_macro
414fn main() {
415 foo$0
416}
417",
418 r"
419fn main() {
420 crate_with_macro::foo
421}
422",
423 );
424 }
425
426 #[test]
427 fn qualify_path_target() {
428 check_assist_target(
429 qualify_path,
430 r"
431 struct AssistInfo {
432 group_label: Option<$0GroupLabel>,
433 }
434
435 mod m { pub struct GroupLabel; }
436 ",
437 "GroupLabel",
438 )
439 }
440
441 #[test]
442 fn not_applicable_when_path_start_is_imported() {
443 check_assist_not_applicable(
444 qualify_path,
445 r"
446 pub mod mod1 {
447 pub mod mod2 {
448 pub mod mod3 {
449 pub struct TestStruct;
450 }
451 }
452 }
453
454 use mod1::mod2;
455 fn main() {
456 mod2::mod3::TestStruct$0
457 }
458 ",
459 );
460 }
461
462 #[test]
463 fn not_applicable_for_imported_function() {
464 check_assist_not_applicable(
465 qualify_path,
466 r"
467 pub mod test_mod {
468 pub fn test_function() {}
469 }
470
471 use test_mod::test_function;
472 fn main() {
473 test_function$0
474 }
475 ",
476 );
477 }
478
479 #[test]
480 fn associated_struct_function() {
481 check_assist(
482 qualify_path,
483 r"
484 mod test_mod {
485 pub struct TestStruct {}
486 impl TestStruct {
487 pub fn test_function() {}
488 }
489 }
490
491 fn main() {
492 TestStruct::test_function$0
493 }
494 ",
495 r"
496 mod test_mod {
497 pub struct TestStruct {}
498 impl TestStruct {
499 pub fn test_function() {}
500 }
501 }
502
503 fn main() {
504 test_mod::TestStruct::test_function
505 }
506 ",
507 );
508 }
509
510 #[test]
511 fn associated_struct_const() {
512 mark::check!(qualify_path_qualifier_start);
513 check_assist(
514 qualify_path,
515 r"
516 mod test_mod {
517 pub struct TestStruct {}
518 impl TestStruct {
519 const TEST_CONST: u8 = 42;
520 }
521 }
522
523 fn main() {
524 TestStruct::TEST_CONST$0
525 }
526 ",
527 r"
528 mod test_mod {
529 pub struct TestStruct {}
530 impl TestStruct {
531 const TEST_CONST: u8 = 42;
532 }
533 }
534
535 fn main() {
536 test_mod::TestStruct::TEST_CONST
537 }
538 ",
539 );
540 }
541
542 #[test]
543 fn associated_trait_function() {
544 check_assist(
545 qualify_path,
546 r"
547 mod test_mod {
548 pub trait TestTrait {
549 fn test_function();
550 }
551 pub struct TestStruct {}
552 impl TestTrait for TestStruct {
553 fn test_function() {}
554 }
555 }
556
557 fn main() {
558 test_mod::TestStruct::test_function$0
559 }
560 ",
561 r"
562 mod test_mod {
563 pub trait TestTrait {
564 fn test_function();
565 }
566 pub struct TestStruct {}
567 impl TestTrait for TestStruct {
568 fn test_function() {}
569 }
570 }
571
572 fn main() {
573 <test_mod::TestStruct as test_mod::TestTrait>::test_function
574 }
575 ",
576 );
577 }
578
579 #[test]
580 fn not_applicable_for_imported_trait_for_function() {
581 check_assist_not_applicable(
582 qualify_path,
583 r"
584 mod test_mod {
585 pub trait TestTrait {
586 fn test_function();
587 }
588 pub trait TestTrait2 {
589 fn test_function();
590 }
591 pub enum TestEnum {
592 One,
593 Two,
594 }
595 impl TestTrait2 for TestEnum {
596 fn test_function() {}
597 }
598 impl TestTrait for TestEnum {
599 fn test_function() {}
600 }
601 }
602
603 use test_mod::TestTrait2;
604 fn main() {
605 test_mod::TestEnum::test_function$0;
606 }
607 ",
608 )
609 }
610
611 #[test]
612 fn associated_trait_const() {
613 mark::check!(qualify_path_trait_assoc_item);
614 check_assist(
615 qualify_path,
616 r"
617 mod test_mod {
618 pub trait TestTrait {
619 const TEST_CONST: u8;
620 }
621 pub struct TestStruct {}
622 impl TestTrait for TestStruct {
623 const TEST_CONST: u8 = 42;
624 }
625 }
626
627 fn main() {
628 test_mod::TestStruct::TEST_CONST$0
629 }
630 ",
631 r"
632 mod test_mod {
633 pub trait TestTrait {
634 const TEST_CONST: u8;
635 }
636 pub struct TestStruct {}
637 impl TestTrait for TestStruct {
638 const TEST_CONST: u8 = 42;
639 }
640 }
641
642 fn main() {
643 <test_mod::TestStruct as test_mod::TestTrait>::TEST_CONST
644 }
645 ",
646 );
647 }
648
649 #[test]
650 fn not_applicable_for_imported_trait_for_const() {
651 check_assist_not_applicable(
652 qualify_path,
653 r"
654 mod test_mod {
655 pub trait TestTrait {
656 const TEST_CONST: u8;
657 }
658 pub trait TestTrait2 {
659 const TEST_CONST: f64;
660 }
661 pub enum TestEnum {
662 One,
663 Two,
664 }
665 impl TestTrait2 for TestEnum {
666 const TEST_CONST: f64 = 42.0;
667 }
668 impl TestTrait for TestEnum {
669 const TEST_CONST: u8 = 42;
670 }
671 }
672
673 use test_mod::TestTrait2;
674 fn main() {
675 test_mod::TestEnum::TEST_CONST$0;
676 }
677 ",
678 )
679 }
680
681 #[test]
682 fn trait_method() {
683 mark::check!(qualify_path_trait_method);
684 check_assist(
685 qualify_path,
686 r"
687 mod test_mod {
688 pub trait TestTrait {
689 fn test_method(&self);
690 }
691 pub struct TestStruct {}
692 impl TestTrait for TestStruct {
693 fn test_method(&self) {}
694 }
695 }
696
697 fn main() {
698 let test_struct = test_mod::TestStruct {};
699 test_struct.test_meth$0od()
700 }
701 ",
702 r"
703 mod test_mod {
704 pub trait TestTrait {
705 fn test_method(&self);
706 }
707 pub struct TestStruct {}
708 impl TestTrait for TestStruct {
709 fn test_method(&self) {}
710 }
711 }
712
713 fn main() {
714 let test_struct = test_mod::TestStruct {};
715 test_mod::TestTrait::test_method(&test_struct)
716 }
717 ",
718 );
719 }
720
721 #[test]
722 fn trait_method_multi_params() {
723 check_assist(
724 qualify_path,
725 r"
726 mod test_mod {
727 pub trait TestTrait {
728 fn test_method(&self, test: i32);
729 }
730 pub struct TestStruct {}
731 impl TestTrait for TestStruct {
732 fn test_method(&self, test: i32) {}
733 }
734 }
735
736 fn main() {
737 let test_struct = test_mod::TestStruct {};
738 test_struct.test_meth$0od(42)
739 }
740 ",
741 r"
742 mod test_mod {
743 pub trait TestTrait {
744 fn test_method(&self, test: i32);
745 }
746 pub struct TestStruct {}
747 impl TestTrait for TestStruct {
748 fn test_method(&self, test: i32) {}
749 }
750 }
751
752 fn main() {
753 let test_struct = test_mod::TestStruct {};
754 test_mod::TestTrait::test_method(&test_struct, 42)
755 }
756 ",
757 );
758 }
759
760 #[test]
761 fn trait_method_consume() {
762 check_assist(
763 qualify_path,
764 r"
765 mod test_mod {
766 pub trait TestTrait {
767 fn test_method(self);
768 }
769 pub struct TestStruct {}
770 impl TestTrait for TestStruct {
771 fn test_method(self) {}
772 }
773 }
774
775 fn main() {
776 let test_struct = test_mod::TestStruct {};
777 test_struct.test_meth$0od()
778 }
779 ",
780 r"
781 mod test_mod {
782 pub trait TestTrait {
783 fn test_method(self);
784 }
785 pub struct TestStruct {}
786 impl TestTrait for TestStruct {
787 fn test_method(self) {}
788 }
789 }
790
791 fn main() {
792 let test_struct = test_mod::TestStruct {};
793 test_mod::TestTrait::test_method(test_struct)
794 }
795 ",
796 );
797 }
798
799 #[test]
800 fn trait_method_cross_crate() {
801 check_assist(
802 qualify_path,
803 r"
804 //- /main.rs crate:main deps:dep
805 fn main() {
806 let test_struct = dep::test_mod::TestStruct {};
807 test_struct.test_meth$0od()
808 }
809 //- /dep.rs crate:dep
810 pub mod test_mod {
811 pub trait TestTrait {
812 fn test_method(&self);
813 }
814 pub struct TestStruct {}
815 impl TestTrait for TestStruct {
816 fn test_method(&self) {}
817 }
818 }
819 ",
820 r"
821 fn main() {
822 let test_struct = dep::test_mod::TestStruct {};
823 dep::test_mod::TestTrait::test_method(&test_struct)
824 }
825 ",
826 );
827 }
828
829 #[test]
830 fn assoc_fn_cross_crate() {
831 check_assist(
832 qualify_path,
833 r"
834 //- /main.rs crate:main deps:dep
835 fn main() {
836 dep::test_mod::TestStruct::test_func$0tion
837 }
838 //- /dep.rs crate:dep
839 pub mod test_mod {
840 pub trait TestTrait {
841 fn test_function();
842 }
843 pub struct TestStruct {}
844 impl TestTrait for TestStruct {
845 fn test_function() {}
846 }
847 }
848 ",
849 r"
850 fn main() {
851 <dep::test_mod::TestStruct as dep::test_mod::TestTrait>::test_function
852 }
853 ",
854 );
855 }
856
857 #[test]
858 fn assoc_const_cross_crate() {
859 check_assist(
860 qualify_path,
861 r"
862 //- /main.rs crate:main deps:dep
863 fn main() {
864 dep::test_mod::TestStruct::CONST$0
865 }
866 //- /dep.rs crate:dep
867 pub mod test_mod {
868 pub trait TestTrait {
869 const CONST: bool;
870 }
871 pub struct TestStruct {}
872 impl TestTrait for TestStruct {
873 const CONST: bool = true;
874 }
875 }
876 ",
877 r"
878 fn main() {
879 <dep::test_mod::TestStruct as dep::test_mod::TestTrait>::CONST
880 }
881 ",
882 );
883 }
884
885 #[test]
886 fn assoc_fn_as_method_cross_crate() {
887 check_assist_not_applicable(
888 qualify_path,
889 r"
890 //- /main.rs crate:main deps:dep
891 fn main() {
892 let test_struct = dep::test_mod::TestStruct {};
893 test_struct.test_func$0tion()
894 }
895 //- /dep.rs crate:dep
896 pub mod test_mod {
897 pub trait TestTrait {
898 fn test_function();
899 }
900 pub struct TestStruct {}
901 impl TestTrait for TestStruct {
902 fn test_function() {}
903 }
904 }
905 ",
906 );
907 }
908
909 #[test]
910 fn private_trait_cross_crate() {
911 check_assist_not_applicable(
912 qualify_path,
913 r"
914 //- /main.rs crate:main deps:dep
915 fn main() {
916 let test_struct = dep::test_mod::TestStruct {};
917 test_struct.test_meth$0od()
918 }
919 //- /dep.rs crate:dep
920 pub mod test_mod {
921 trait TestTrait {
922 fn test_method(&self);
923 }
924 pub struct TestStruct {}
925 impl TestTrait for TestStruct {
926 fn test_method(&self) {}
927 }
928 }
929 ",
930 );
931 }
932
933 #[test]
934 fn not_applicable_for_imported_trait_for_method() {
935 check_assist_not_applicable(
936 qualify_path,
937 r"
938 mod test_mod {
939 pub trait TestTrait {
940 fn test_method(&self);
941 }
942 pub trait TestTrait2 {
943 fn test_method(&self);
944 }
945 pub enum TestEnum {
946 One,
947 Two,
948 }
949 impl TestTrait2 for TestEnum {
950 fn test_method(&self) {}
951 }
952 impl TestTrait for TestEnum {
953 fn test_method(&self) {}
954 }
955 }
956
957 use test_mod::TestTrait2;
958 fn main() {
959 let one = test_mod::TestEnum::One;
960 one.test$0_method();
961 }
962 ",
963 )
964 }
965
966 #[test]
967 fn dep_import() {
968 check_assist(
969 qualify_path,
970 r"
971//- /lib.rs crate:dep
972pub struct Struct;
973
974//- /main.rs crate:main deps:dep
975fn main() {
976 Struct$0
977}
978",
979 r"
980fn main() {
981 dep::Struct
982}
983",
984 );
985 }
986
987 #[test]
988 fn whole_segment() {
989 // Tests that only imports whose last segment matches the identifier get suggested.
990 check_assist(
991 qualify_path,
992 r"
993//- /lib.rs crate:dep
994pub mod fmt {
995 pub trait Display {}
996}
997
998pub fn panic_fmt() {}
999
1000//- /main.rs crate:main deps:dep
1001struct S;
1002
1003impl f$0mt::Display for S {}
1004",
1005 r"
1006struct S;
1007
1008impl dep::fmt::Display for S {}
1009",
1010 );
1011 }
1012
1013 #[test]
1014 fn macro_generated() {
1015 // Tests that macro-generated items are suggested from external crates.
1016 check_assist(
1017 qualify_path,
1018 r"
1019//- /lib.rs crate:dep
1020macro_rules! mac {
1021 () => {
1022 pub struct Cheese;
1023 };
1024}
1025
1026mac!();
1027
1028//- /main.rs crate:main deps:dep
1029fn main() {
1030 Cheese$0;
1031}
1032",
1033 r"
1034fn main() {
1035 dep::Cheese;
1036}
1037",
1038 );
1039 }
1040
1041 #[test]
1042 fn casing() {
1043 // Tests that differently cased names don't interfere and we only suggest the matching one.
1044 check_assist(
1045 qualify_path,
1046 r"
1047//- /lib.rs crate:dep
1048pub struct FMT;
1049pub struct fmt;
1050
1051//- /main.rs crate:main deps:dep
1052fn main() {
1053 FMT$0;
1054}
1055",
1056 r"
1057fn main() {
1058 dep::FMT;
1059}
1060",
1061 );
1062 }
1063
1064 #[test]
1065 fn keep_generic_annotations() {
1066 check_assist(
1067 qualify_path,
1068 r"
1069//- /lib.rs crate:dep
1070pub mod generic { pub struct Thing<'a, T>(&'a T); }
1071
1072//- /main.rs crate:main deps:dep
1073fn foo() -> Thin$0g<'static, ()> {}
1074
1075fn main() {}
1076",
1077 r"
1078fn foo() -> dep::generic::Thing<'static, ()> {}
1079
1080fn main() {}
1081",
1082 );
1083 }
1084
1085 #[test]
1086 fn keep_generic_annotations_leading_colon() {
1087 check_assist(
1088 qualify_path,
1089 r"
1090//- /lib.rs crate:dep
1091pub mod generic { pub struct Thing<'a, T>(&'a T); }
1092
1093//- /main.rs crate:main deps:dep
1094fn foo() -> Thin$0g::<'static, ()> {}
1095
1096fn main() {}
1097",
1098 r"
1099fn foo() -> dep::generic::Thing::<'static, ()> {}
1100
1101fn main() {}
1102",
1103 );
1104 }
1105
1106 #[test]
1107 fn associated_struct_const_generic() {
1108 check_assist(
1109 qualify_path,
1110 r"
1111 mod test_mod {
1112 pub struct TestStruct<T> {}
1113 impl<T> TestStruct<T> {
1114 const TEST_CONST: u8 = 42;
1115 }
1116 }
1117
1118 fn main() {
1119 TestStruct::<()>::TEST_CONST$0
1120 }
1121 ",
1122 r"
1123 mod test_mod {
1124 pub struct TestStruct<T> {}
1125 impl<T> TestStruct<T> {
1126 const TEST_CONST: u8 = 42;
1127 }
1128 }
1129
1130 fn main() {
1131 test_mod::TestStruct::<()>::TEST_CONST
1132 }
1133 ",
1134 );
1135 }
1136
1137 #[test]
1138 fn associated_trait_const_generic() {
1139 check_assist(
1140 qualify_path,
1141 r"
1142 mod test_mod {
1143 pub trait TestTrait {
1144 const TEST_CONST: u8;
1145 }
1146 pub struct TestStruct<T> {}
1147 impl<T> TestTrait for TestStruct<T> {
1148 const TEST_CONST: u8 = 42;
1149 }
1150 }
1151
1152 fn main() {
1153 test_mod::TestStruct::<()>::TEST_CONST$0
1154 }
1155 ",
1156 r"
1157 mod test_mod {
1158 pub trait TestTrait {
1159 const TEST_CONST: u8;
1160 }
1161 pub struct TestStruct<T> {}
1162 impl<T> TestTrait for TestStruct<T> {
1163 const TEST_CONST: u8 = 42;
1164 }
1165 }
1166
1167 fn main() {
1168 <test_mod::TestStruct::<()> as test_mod::TestTrait>::TEST_CONST
1169 }
1170 ",
1171 );
1172 }
1173
1174 #[test]
1175 fn trait_method_generic() {
1176 check_assist(
1177 qualify_path,
1178 r"
1179 mod test_mod {
1180 pub trait TestTrait {
1181 fn test_method<T>(&self);
1182 }
1183 pub struct TestStruct {}
1184 impl TestTrait for TestStruct {
1185 fn test_method<T>(&self) {}
1186 }
1187 }
1188
1189 fn main() {
1190 let test_struct = test_mod::TestStruct {};
1191 test_struct.test_meth$0od::<()>()
1192 }
1193 ",
1194 r"
1195 mod test_mod {
1196 pub trait TestTrait {
1197 fn test_method<T>(&self);
1198 }
1199 pub struct TestStruct {}
1200 impl TestTrait for TestStruct {
1201 fn test_method<T>(&self) {}
1202 }
1203 }
1204
1205 fn main() {
1206 let test_struct = test_mod::TestStruct {};
1207 test_mod::TestTrait::test_method::<()>(&test_struct)
1208 }
1209 ",
1210 );
1211 }
1212}