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