]> git.lizzy.rs Git - rust.git/blob - crates/ide_assists/src/handlers/qualify_path.rs
Fix labels for single import assists
[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     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(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(candidate: &ImportCandidate, import: &LocatedImport) -> String {
203     match candidate {
204         ImportCandidate::Path(candidate) => {
205             if candidate.qualifier.is_some() {
206                 format!("Qualify with `{}`", import.import_path)
207             } else {
208                 format!("Qualify as `{}`", import.import_path)
209             }
210         }
211         ImportCandidate::TraitAssocItem(_) => format!("Qualify `{}`", import.import_path),
212         ImportCandidate::TraitMethod(_) => format!("Qualify with cast as `{}`", import.import_path),
213     }
214 }
215
216 #[cfg(test)]
217 mod tests {
218     use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
219
220     use super::*;
221
222     #[test]
223     fn applicable_when_found_an_import_partial() {
224         cov_mark::check!(qualify_path_unqualified_name);
225         check_assist(
226             qualify_path,
227             r"
228             mod std {
229                 pub mod fmt {
230                     pub struct Formatter;
231                 }
232             }
233
234             use std::fmt;
235
236             $0Formatter
237             ",
238             r"
239             mod std {
240                 pub mod fmt {
241                     pub struct Formatter;
242                 }
243             }
244
245             use std::fmt;
246
247             fmt::Formatter
248             ",
249         );
250     }
251
252     #[test]
253     fn applicable_when_found_an_import() {
254         check_assist(
255             qualify_path,
256             r"
257             $0PubStruct
258
259             pub mod PubMod {
260                 pub struct PubStruct;
261             }
262             ",
263             r"
264             PubMod::PubStruct
265
266             pub mod PubMod {
267                 pub struct PubStruct;
268             }
269             ",
270         );
271     }
272
273     #[test]
274     fn applicable_in_macros() {
275         check_assist(
276             qualify_path,
277             r"
278             macro_rules! foo {
279                 ($i:ident) => { fn foo(a: $i) {} }
280             }
281             foo!(Pub$0Struct);
282
283             pub mod PubMod {
284                 pub struct PubStruct;
285             }
286             ",
287             r"
288             macro_rules! foo {
289                 ($i:ident) => { fn foo(a: $i) {} }
290             }
291             foo!(PubMod::PubStruct);
292
293             pub mod PubMod {
294                 pub struct PubStruct;
295             }
296             ",
297         );
298     }
299
300     #[test]
301     fn applicable_when_found_multiple_imports() {
302         check_assist(
303             qualify_path,
304             r"
305             PubSt$0ruct
306
307             pub mod PubMod1 {
308                 pub struct PubStruct;
309             }
310             pub mod PubMod2 {
311                 pub struct PubStruct;
312             }
313             pub mod PubMod3 {
314                 pub struct PubStruct;
315             }
316             ",
317             r"
318             PubMod3::PubStruct
319
320             pub mod PubMod1 {
321                 pub struct PubStruct;
322             }
323             pub mod PubMod2 {
324                 pub struct PubStruct;
325             }
326             pub mod PubMod3 {
327                 pub struct PubStruct;
328             }
329             ",
330         );
331     }
332
333     #[test]
334     fn not_applicable_for_already_imported_types() {
335         check_assist_not_applicable(
336             qualify_path,
337             r"
338             use PubMod::PubStruct;
339
340             PubStruct$0
341
342             pub mod PubMod {
343                 pub struct PubStruct;
344             }
345             ",
346         );
347     }
348
349     #[test]
350     fn not_applicable_for_types_with_private_paths() {
351         check_assist_not_applicable(
352             qualify_path,
353             r"
354             PrivateStruct$0
355
356             pub mod PubMod {
357                 struct PrivateStruct;
358             }
359             ",
360         );
361     }
362
363     #[test]
364     fn not_applicable_when_no_imports_found() {
365         check_assist_not_applicable(
366             qualify_path,
367             "
368             PubStruct$0",
369         );
370     }
371
372     #[test]
373     fn not_applicable_in_import_statements() {
374         check_assist_not_applicable(
375             qualify_path,
376             r"
377             use PubStruct$0;
378
379             pub mod PubMod {
380                 pub struct PubStruct;
381             }",
382         );
383     }
384
385     #[test]
386     fn qualify_function() {
387         check_assist(
388             qualify_path,
389             r"
390             test_function$0
391
392             pub mod PubMod {
393                 pub fn test_function() {};
394             }
395             ",
396             r"
397             PubMod::test_function
398
399             pub mod PubMod {
400                 pub fn test_function() {};
401             }
402             ",
403         );
404     }
405
406     #[test]
407     fn qualify_macro() {
408         check_assist(
409             qualify_path,
410             r"
411 //- /lib.rs crate:crate_with_macro
412 #[macro_export]
413 macro_rules! foo {
414     () => ()
415 }
416
417 //- /main.rs crate:main deps:crate_with_macro
418 fn main() {
419     foo$0
420 }
421 ",
422             r"
423 fn main() {
424     crate_with_macro::foo
425 }
426 ",
427         );
428     }
429
430     #[test]
431     fn qualify_path_target() {
432         check_assist_target(
433             qualify_path,
434             r"
435             struct AssistInfo {
436                 group_label: Option<$0GroupLabel>,
437             }
438
439             mod m { pub struct GroupLabel; }
440             ",
441             "GroupLabel",
442         )
443     }
444
445     #[test]
446     fn not_applicable_when_path_start_is_imported() {
447         check_assist_not_applicable(
448             qualify_path,
449             r"
450             pub mod mod1 {
451                 pub mod mod2 {
452                     pub mod mod3 {
453                         pub struct TestStruct;
454                     }
455                 }
456             }
457
458             use mod1::mod2;
459             fn main() {
460                 mod2::mod3::TestStruct$0
461             }
462             ",
463         );
464     }
465
466     #[test]
467     fn not_applicable_for_imported_function() {
468         check_assist_not_applicable(
469             qualify_path,
470             r"
471             pub mod test_mod {
472                 pub fn test_function() {}
473             }
474
475             use test_mod::test_function;
476             fn main() {
477                 test_function$0
478             }
479             ",
480         );
481     }
482
483     #[test]
484     fn associated_struct_function() {
485         check_assist(
486             qualify_path,
487             r"
488             mod test_mod {
489                 pub struct TestStruct {}
490                 impl TestStruct {
491                     pub fn test_function() {}
492                 }
493             }
494
495             fn main() {
496                 TestStruct::test_function$0
497             }
498             ",
499             r"
500             mod test_mod {
501                 pub struct TestStruct {}
502                 impl TestStruct {
503                     pub fn test_function() {}
504                 }
505             }
506
507             fn main() {
508                 test_mod::TestStruct::test_function
509             }
510             ",
511         );
512     }
513
514     #[test]
515     fn associated_struct_const() {
516         cov_mark::check!(qualify_path_qualifier_start);
517         check_assist(
518             qualify_path,
519             r"
520             mod test_mod {
521                 pub struct TestStruct {}
522                 impl TestStruct {
523                     const TEST_CONST: u8 = 42;
524                 }
525             }
526
527             fn main() {
528                 TestStruct::TEST_CONST$0
529             }
530             ",
531             r"
532             mod test_mod {
533                 pub struct TestStruct {}
534                 impl TestStruct {
535                     const TEST_CONST: u8 = 42;
536                 }
537             }
538
539             fn main() {
540                 test_mod::TestStruct::TEST_CONST
541             }
542             ",
543         );
544     }
545
546     #[test]
547     fn associated_trait_function() {
548         check_assist(
549             qualify_path,
550             r"
551             mod test_mod {
552                 pub trait TestTrait {
553                     fn test_function();
554                 }
555                 pub struct TestStruct {}
556                 impl TestTrait for TestStruct {
557                     fn test_function() {}
558                 }
559             }
560
561             fn main() {
562                 test_mod::TestStruct::test_function$0
563             }
564             ",
565             r"
566             mod test_mod {
567                 pub trait TestTrait {
568                     fn test_function();
569                 }
570                 pub struct TestStruct {}
571                 impl TestTrait for TestStruct {
572                     fn test_function() {}
573                 }
574             }
575
576             fn main() {
577                 <test_mod::TestStruct as test_mod::TestTrait>::test_function
578             }
579             ",
580         );
581     }
582
583     #[test]
584     fn not_applicable_for_imported_trait_for_function() {
585         check_assist_not_applicable(
586             qualify_path,
587             r"
588             mod test_mod {
589                 pub trait TestTrait {
590                     fn test_function();
591                 }
592                 pub trait TestTrait2 {
593                     fn test_function();
594                 }
595                 pub enum TestEnum {
596                     One,
597                     Two,
598                 }
599                 impl TestTrait2 for TestEnum {
600                     fn test_function() {}
601                 }
602                 impl TestTrait for TestEnum {
603                     fn test_function() {}
604                 }
605             }
606
607             use test_mod::TestTrait2;
608             fn main() {
609                 test_mod::TestEnum::test_function$0;
610             }
611             ",
612         )
613     }
614
615     #[test]
616     fn associated_trait_const() {
617         cov_mark::check!(qualify_path_trait_assoc_item);
618         check_assist(
619             qualify_path,
620             r"
621             mod test_mod {
622                 pub trait TestTrait {
623                     const TEST_CONST: u8;
624                 }
625                 pub struct TestStruct {}
626                 impl TestTrait for TestStruct {
627                     const TEST_CONST: u8 = 42;
628                 }
629             }
630
631             fn main() {
632                 test_mod::TestStruct::TEST_CONST$0
633             }
634             ",
635             r"
636             mod test_mod {
637                 pub trait TestTrait {
638                     const TEST_CONST: u8;
639                 }
640                 pub struct TestStruct {}
641                 impl TestTrait for TestStruct {
642                     const TEST_CONST: u8 = 42;
643                 }
644             }
645
646             fn main() {
647                 <test_mod::TestStruct as test_mod::TestTrait>::TEST_CONST
648             }
649             ",
650         );
651     }
652
653     #[test]
654     fn not_applicable_for_imported_trait_for_const() {
655         check_assist_not_applicable(
656             qualify_path,
657             r"
658             mod test_mod {
659                 pub trait TestTrait {
660                     const TEST_CONST: u8;
661                 }
662                 pub trait TestTrait2 {
663                     const TEST_CONST: f64;
664                 }
665                 pub enum TestEnum {
666                     One,
667                     Two,
668                 }
669                 impl TestTrait2 for TestEnum {
670                     const TEST_CONST: f64 = 42.0;
671                 }
672                 impl TestTrait for TestEnum {
673                     const TEST_CONST: u8 = 42;
674                 }
675             }
676
677             use test_mod::TestTrait2;
678             fn main() {
679                 test_mod::TestEnum::TEST_CONST$0;
680             }
681             ",
682         )
683     }
684
685     #[test]
686     fn trait_method() {
687         cov_mark::check!(qualify_path_trait_method);
688         check_assist(
689             qualify_path,
690             r"
691             mod test_mod {
692                 pub trait TestTrait {
693                     fn test_method(&self);
694                 }
695                 pub struct TestStruct {}
696                 impl TestTrait for TestStruct {
697                     fn test_method(&self) {}
698                 }
699             }
700
701             fn main() {
702                 let test_struct = test_mod::TestStruct {};
703                 test_struct.test_meth$0od()
704             }
705             ",
706             r"
707             mod test_mod {
708                 pub trait TestTrait {
709                     fn test_method(&self);
710                 }
711                 pub struct TestStruct {}
712                 impl TestTrait for TestStruct {
713                     fn test_method(&self) {}
714                 }
715             }
716
717             fn main() {
718                 let test_struct = test_mod::TestStruct {};
719                 test_mod::TestTrait::test_method(&test_struct)
720             }
721             ",
722         );
723     }
724
725     #[test]
726     fn trait_method_multi_params() {
727         check_assist(
728             qualify_path,
729             r"
730             mod test_mod {
731                 pub trait TestTrait {
732                     fn test_method(&self, test: i32);
733                 }
734                 pub struct TestStruct {}
735                 impl TestTrait for TestStruct {
736                     fn test_method(&self, test: i32) {}
737                 }
738             }
739
740             fn main() {
741                 let test_struct = test_mod::TestStruct {};
742                 test_struct.test_meth$0od(42)
743             }
744             ",
745             r"
746             mod test_mod {
747                 pub trait TestTrait {
748                     fn test_method(&self, test: i32);
749                 }
750                 pub struct TestStruct {}
751                 impl TestTrait for TestStruct {
752                     fn test_method(&self, test: i32) {}
753                 }
754             }
755
756             fn main() {
757                 let test_struct = test_mod::TestStruct {};
758                 test_mod::TestTrait::test_method(&test_struct, 42)
759             }
760             ",
761         );
762     }
763
764     #[test]
765     fn trait_method_consume() {
766         check_assist(
767             qualify_path,
768             r"
769             mod test_mod {
770                 pub trait TestTrait {
771                     fn test_method(self);
772                 }
773                 pub struct TestStruct {}
774                 impl TestTrait for TestStruct {
775                     fn test_method(self) {}
776                 }
777             }
778
779             fn main() {
780                 let test_struct = test_mod::TestStruct {};
781                 test_struct.test_meth$0od()
782             }
783             ",
784             r"
785             mod test_mod {
786                 pub trait TestTrait {
787                     fn test_method(self);
788                 }
789                 pub struct TestStruct {}
790                 impl TestTrait for TestStruct {
791                     fn test_method(self) {}
792                 }
793             }
794
795             fn main() {
796                 let test_struct = test_mod::TestStruct {};
797                 test_mod::TestTrait::test_method(test_struct)
798             }
799             ",
800         );
801     }
802
803     #[test]
804     fn trait_method_cross_crate() {
805         check_assist(
806             qualify_path,
807             r"
808             //- /main.rs crate:main deps:dep
809             fn main() {
810                 let test_struct = dep::test_mod::TestStruct {};
811                 test_struct.test_meth$0od()
812             }
813             //- /dep.rs crate:dep
814             pub mod test_mod {
815                 pub trait TestTrait {
816                     fn test_method(&self);
817                 }
818                 pub struct TestStruct {}
819                 impl TestTrait for TestStruct {
820                     fn test_method(&self) {}
821                 }
822             }
823             ",
824             r"
825             fn main() {
826                 let test_struct = dep::test_mod::TestStruct {};
827                 dep::test_mod::TestTrait::test_method(&test_struct)
828             }
829             ",
830         );
831     }
832
833     #[test]
834     fn assoc_fn_cross_crate() {
835         check_assist(
836             qualify_path,
837             r"
838             //- /main.rs crate:main deps:dep
839             fn main() {
840                 dep::test_mod::TestStruct::test_func$0tion
841             }
842             //- /dep.rs crate:dep
843             pub mod test_mod {
844                 pub trait TestTrait {
845                     fn test_function();
846                 }
847                 pub struct TestStruct {}
848                 impl TestTrait for TestStruct {
849                     fn test_function() {}
850                 }
851             }
852             ",
853             r"
854             fn main() {
855                 <dep::test_mod::TestStruct as dep::test_mod::TestTrait>::test_function
856             }
857             ",
858         );
859     }
860
861     #[test]
862     fn assoc_const_cross_crate() {
863         check_assist(
864             qualify_path,
865             r"
866             //- /main.rs crate:main deps:dep
867             fn main() {
868                 dep::test_mod::TestStruct::CONST$0
869             }
870             //- /dep.rs crate:dep
871             pub mod test_mod {
872                 pub trait TestTrait {
873                     const CONST: bool;
874                 }
875                 pub struct TestStruct {}
876                 impl TestTrait for TestStruct {
877                     const CONST: bool = true;
878                 }
879             }
880             ",
881             r"
882             fn main() {
883                 <dep::test_mod::TestStruct as dep::test_mod::TestTrait>::CONST
884             }
885             ",
886         );
887     }
888
889     #[test]
890     fn assoc_fn_as_method_cross_crate() {
891         check_assist_not_applicable(
892             qualify_path,
893             r"
894             //- /main.rs crate:main deps:dep
895             fn main() {
896                 let test_struct = dep::test_mod::TestStruct {};
897                 test_struct.test_func$0tion()
898             }
899             //- /dep.rs crate:dep
900             pub mod test_mod {
901                 pub trait TestTrait {
902                     fn test_function();
903                 }
904                 pub struct TestStruct {}
905                 impl TestTrait for TestStruct {
906                     fn test_function() {}
907                 }
908             }
909             ",
910         );
911     }
912
913     #[test]
914     fn private_trait_cross_crate() {
915         check_assist_not_applicable(
916             qualify_path,
917             r"
918             //- /main.rs crate:main deps:dep
919             fn main() {
920                 let test_struct = dep::test_mod::TestStruct {};
921                 test_struct.test_meth$0od()
922             }
923             //- /dep.rs crate:dep
924             pub mod test_mod {
925                 trait TestTrait {
926                     fn test_method(&self);
927                 }
928                 pub struct TestStruct {}
929                 impl TestTrait for TestStruct {
930                     fn test_method(&self) {}
931                 }
932             }
933             ",
934         );
935     }
936
937     #[test]
938     fn not_applicable_for_imported_trait_for_method() {
939         check_assist_not_applicable(
940             qualify_path,
941             r"
942             mod test_mod {
943                 pub trait TestTrait {
944                     fn test_method(&self);
945                 }
946                 pub trait TestTrait2 {
947                     fn test_method(&self);
948                 }
949                 pub enum TestEnum {
950                     One,
951                     Two,
952                 }
953                 impl TestTrait2 for TestEnum {
954                     fn test_method(&self) {}
955                 }
956                 impl TestTrait for TestEnum {
957                     fn test_method(&self) {}
958                 }
959             }
960
961             use test_mod::TestTrait2;
962             fn main() {
963                 let one = test_mod::TestEnum::One;
964                 one.test$0_method();
965             }
966             ",
967         )
968     }
969
970     #[test]
971     fn dep_import() {
972         check_assist(
973             qualify_path,
974             r"
975 //- /lib.rs crate:dep
976 pub struct Struct;
977
978 //- /main.rs crate:main deps:dep
979 fn main() {
980     Struct$0
981 }
982 ",
983             r"
984 fn main() {
985     dep::Struct
986 }
987 ",
988         );
989     }
990
991     #[test]
992     fn whole_segment() {
993         // Tests that only imports whose last segment matches the identifier get suggested.
994         check_assist(
995             qualify_path,
996             r"
997 //- /lib.rs crate:dep
998 pub mod fmt {
999     pub trait Display {}
1000 }
1001
1002 pub fn panic_fmt() {}
1003
1004 //- /main.rs crate:main deps:dep
1005 struct S;
1006
1007 impl f$0mt::Display for S {}
1008 ",
1009             r"
1010 struct S;
1011
1012 impl dep::fmt::Display for S {}
1013 ",
1014         );
1015     }
1016
1017     #[test]
1018     fn macro_generated() {
1019         // Tests that macro-generated items are suggested from external crates.
1020         check_assist(
1021             qualify_path,
1022             r"
1023 //- /lib.rs crate:dep
1024 macro_rules! mac {
1025     () => {
1026         pub struct Cheese;
1027     };
1028 }
1029
1030 mac!();
1031
1032 //- /main.rs crate:main deps:dep
1033 fn main() {
1034     Cheese$0;
1035 }
1036 ",
1037             r"
1038 fn main() {
1039     dep::Cheese;
1040 }
1041 ",
1042         );
1043     }
1044
1045     #[test]
1046     fn casing() {
1047         // Tests that differently cased names don't interfere and we only suggest the matching one.
1048         check_assist(
1049             qualify_path,
1050             r"
1051 //- /lib.rs crate:dep
1052 pub struct FMT;
1053 pub struct fmt;
1054
1055 //- /main.rs crate:main deps:dep
1056 fn main() {
1057     FMT$0;
1058 }
1059 ",
1060             r"
1061 fn main() {
1062     dep::FMT;
1063 }
1064 ",
1065         );
1066     }
1067
1068     #[test]
1069     fn keep_generic_annotations() {
1070         check_assist(
1071             qualify_path,
1072             r"
1073 //- /lib.rs crate:dep
1074 pub mod generic { pub struct Thing<'a, T>(&'a T); }
1075
1076 //- /main.rs crate:main deps:dep
1077 fn foo() -> Thin$0g<'static, ()> {}
1078
1079 fn main() {}
1080 ",
1081             r"
1082 fn foo() -> dep::generic::Thing<'static, ()> {}
1083
1084 fn main() {}
1085 ",
1086         );
1087     }
1088
1089     #[test]
1090     fn keep_generic_annotations_leading_colon() {
1091         check_assist(
1092             qualify_path,
1093             r"
1094 //- /lib.rs crate:dep
1095 pub mod generic { pub struct Thing<'a, T>(&'a T); }
1096
1097 //- /main.rs crate:main deps:dep
1098 fn foo() -> Thin$0g::<'static, ()> {}
1099
1100 fn main() {}
1101 ",
1102             r"
1103 fn foo() -> dep::generic::Thing::<'static, ()> {}
1104
1105 fn main() {}
1106 ",
1107         );
1108     }
1109
1110     #[test]
1111     fn associated_struct_const_generic() {
1112         check_assist(
1113             qualify_path,
1114             r"
1115             mod test_mod {
1116                 pub struct TestStruct<T> {}
1117                 impl<T> TestStruct<T> {
1118                     const TEST_CONST: u8 = 42;
1119                 }
1120             }
1121
1122             fn main() {
1123                 TestStruct::<()>::TEST_CONST$0
1124             }
1125             ",
1126             r"
1127             mod test_mod {
1128                 pub struct TestStruct<T> {}
1129                 impl<T> TestStruct<T> {
1130                     const TEST_CONST: u8 = 42;
1131                 }
1132             }
1133
1134             fn main() {
1135                 test_mod::TestStruct::<()>::TEST_CONST
1136             }
1137             ",
1138         );
1139     }
1140
1141     #[test]
1142     fn associated_trait_const_generic() {
1143         check_assist(
1144             qualify_path,
1145             r"
1146             mod test_mod {
1147                 pub trait TestTrait {
1148                     const TEST_CONST: u8;
1149                 }
1150                 pub struct TestStruct<T> {}
1151                 impl<T> TestTrait for TestStruct<T> {
1152                     const TEST_CONST: u8 = 42;
1153                 }
1154             }
1155
1156             fn main() {
1157                 test_mod::TestStruct::<()>::TEST_CONST$0
1158             }
1159             ",
1160             r"
1161             mod test_mod {
1162                 pub trait TestTrait {
1163                     const TEST_CONST: u8;
1164                 }
1165                 pub struct TestStruct<T> {}
1166                 impl<T> TestTrait for TestStruct<T> {
1167                     const TEST_CONST: u8 = 42;
1168                 }
1169             }
1170
1171             fn main() {
1172                 <test_mod::TestStruct::<()> as test_mod::TestTrait>::TEST_CONST
1173             }
1174             ",
1175         );
1176     }
1177
1178     #[test]
1179     fn trait_method_generic() {
1180         check_assist(
1181             qualify_path,
1182             r"
1183             mod test_mod {
1184                 pub trait TestTrait {
1185                     fn test_method<T>(&self);
1186                 }
1187                 pub struct TestStruct {}
1188                 impl TestTrait for TestStruct {
1189                     fn test_method<T>(&self) {}
1190                 }
1191             }
1192
1193             fn main() {
1194                 let test_struct = test_mod::TestStruct {};
1195                 test_struct.test_meth$0od::<()>()
1196             }
1197             ",
1198             r"
1199             mod test_mod {
1200                 pub trait TestTrait {
1201                     fn test_method<T>(&self);
1202                 }
1203                 pub struct TestStruct {}
1204                 impl TestTrait for TestStruct {
1205                     fn test_method<T>(&self) {}
1206                 }
1207             }
1208
1209             fn main() {
1210                 let test_struct = test_mod::TestStruct {};
1211                 test_mod::TestTrait::test_method::<()>(&test_struct)
1212             }
1213             ",
1214         );
1215     }
1216 }