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