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