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