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