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