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