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