]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs
Rollup merge of #99954 - dingxiangfei2009:break-out-let-else-higher-up, r=oli-obk
[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 = 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 qualify_function() {
386         check_assist(
387             qualify_path,
388             r#"
389 test_function$0
390
391 pub mod PubMod {
392     pub fn test_function() {};
393 }
394 "#,
395             r#"
396 PubMod::test_function
397
398 pub mod PubMod {
399     pub fn test_function() {};
400 }
401 "#,
402         );
403     }
404
405     #[test]
406     fn qualify_macro() {
407         check_assist(
408             qualify_path,
409             r#"
410 //- /lib.rs crate:crate_with_macro
411 #[macro_export]
412 macro_rules! foo {
413     () => ()
414 }
415
416 //- /main.rs crate:main deps:crate_with_macro
417 fn main() {
418     foo$0
419 }
420 "#,
421             r#"
422 fn main() {
423     crate_with_macro::foo
424 }
425 "#,
426         );
427     }
428
429     #[test]
430     fn qualify_path_target() {
431         check_assist_target(
432             qualify_path,
433             r#"
434 struct AssistInfo {
435     group_label: Option<$0GroupLabel>,
436 }
437
438 mod m { pub struct GroupLabel; }
439 "#,
440             "GroupLabel",
441         )
442     }
443
444     #[test]
445     fn not_applicable_when_path_start_is_imported() {
446         check_assist_not_applicable(
447             qualify_path,
448             r#"
449 pub mod mod1 {
450     pub mod mod2 {
451         pub mod mod3 {
452             pub struct TestStruct;
453         }
454     }
455 }
456
457 use mod1::mod2;
458 fn main() {
459     mod2::mod3::TestStruct$0
460 }
461 "#,
462         );
463     }
464
465     #[test]
466     fn not_applicable_for_imported_function() {
467         check_assist_not_applicable(
468             qualify_path,
469             r#"
470 pub mod test_mod {
471     pub fn test_function() {}
472 }
473
474 use test_mod::test_function;
475 fn main() {
476     test_function$0
477 }
478 "#,
479         );
480     }
481
482     #[test]
483     fn associated_struct_function() {
484         check_assist(
485             qualify_path,
486             r#"
487 mod test_mod {
488     pub struct TestStruct {}
489     impl TestStruct {
490         pub fn test_function() {}
491     }
492 }
493
494 fn main() {
495     TestStruct::test_function$0
496 }
497 "#,
498             r#"
499 mod test_mod {
500     pub struct TestStruct {}
501     impl TestStruct {
502         pub fn test_function() {}
503     }
504 }
505
506 fn main() {
507     test_mod::TestStruct::test_function
508 }
509 "#,
510         );
511     }
512
513     #[test]
514     fn associated_struct_const() {
515         cov_mark::check!(qualify_path_qualifier_start);
516         check_assist(
517             qualify_path,
518             r#"
519 mod test_mod {
520     pub struct TestStruct {}
521     impl TestStruct {
522         const TEST_CONST: u8 = 42;
523     }
524 }
525
526 fn main() {
527     TestStruct::TEST_CONST$0
528 }
529 "#,
530             r#"
531 mod test_mod {
532     pub struct TestStruct {}
533     impl TestStruct {
534         const TEST_CONST: u8 = 42;
535     }
536 }
537
538 fn main() {
539     test_mod::TestStruct::TEST_CONST
540 }
541 "#,
542         );
543     }
544
545     #[test]
546     fn associated_struct_const_unqualified() {
547         // FIXME: non-trait assoc items completion is unsupported yet, see FIXME in the import_assets.rs for more details
548         check_assist_not_applicable(
549             qualify_path,
550             r#"
551 mod test_mod {
552     pub struct TestStruct {}
553     impl TestStruct {
554         const TEST_CONST: u8 = 42;
555     }
556 }
557
558 fn main() {
559     TEST_CONST$0
560 }
561 "#,
562         );
563     }
564
565     #[test]
566     fn associated_trait_function() {
567         check_assist(
568             qualify_path,
569             r#"
570 mod test_mod {
571     pub trait TestTrait {
572         fn test_function();
573     }
574     pub struct TestStruct {}
575     impl TestTrait for TestStruct {
576         fn test_function() {}
577     }
578 }
579
580 fn main() {
581     test_mod::TestStruct::test_function$0
582 }
583 "#,
584             r#"
585 mod test_mod {
586     pub trait TestTrait {
587         fn test_function();
588     }
589     pub struct TestStruct {}
590     impl TestTrait for TestStruct {
591         fn test_function() {}
592     }
593 }
594
595 fn main() {
596     <test_mod::TestStruct as test_mod::TestTrait>::test_function
597 }
598 "#,
599         );
600     }
601
602     #[test]
603     fn not_applicable_for_imported_trait_for_function() {
604         check_assist_not_applicable(
605             qualify_path,
606             r#"
607 mod test_mod {
608     pub trait TestTrait {
609         fn test_function();
610     }
611     pub trait TestTrait2 {
612         fn test_function();
613     }
614     pub enum TestEnum {
615         One,
616         Two,
617     }
618     impl TestTrait2 for TestEnum {
619         fn test_function() {}
620     }
621     impl TestTrait for TestEnum {
622         fn test_function() {}
623     }
624 }
625
626 use test_mod::TestTrait2;
627 fn main() {
628     test_mod::TestEnum::test_function$0;
629 }
630 "#,
631         )
632     }
633
634     #[test]
635     fn associated_trait_const() {
636         cov_mark::check!(qualify_path_trait_assoc_item);
637         check_assist(
638             qualify_path,
639             r#"
640 mod test_mod {
641     pub trait TestTrait {
642         const TEST_CONST: u8;
643     }
644     pub struct TestStruct {}
645     impl TestTrait for TestStruct {
646         const TEST_CONST: u8 = 42;
647     }
648 }
649
650 fn main() {
651     test_mod::TestStruct::TEST_CONST$0
652 }
653 "#,
654             r#"
655 mod test_mod {
656     pub trait TestTrait {
657         const TEST_CONST: u8;
658     }
659     pub struct TestStruct {}
660     impl TestTrait for TestStruct {
661         const TEST_CONST: u8 = 42;
662     }
663 }
664
665 fn main() {
666     <test_mod::TestStruct as test_mod::TestTrait>::TEST_CONST
667 }
668 "#,
669         );
670     }
671
672     #[test]
673     fn not_applicable_for_imported_trait_for_const() {
674         check_assist_not_applicable(
675             qualify_path,
676             r#"
677 mod test_mod {
678     pub trait TestTrait {
679         const TEST_CONST: u8;
680     }
681     pub trait TestTrait2 {
682         const TEST_CONST: f64;
683     }
684     pub enum TestEnum {
685         One,
686         Two,
687     }
688     impl TestTrait2 for TestEnum {
689         const TEST_CONST: f64 = 42.0;
690     }
691     impl TestTrait for TestEnum {
692         const TEST_CONST: u8 = 42;
693     }
694 }
695
696 use test_mod::TestTrait2;
697 fn main() {
698     test_mod::TestEnum::TEST_CONST$0;
699 }
700 "#,
701         )
702     }
703
704     #[test]
705     fn trait_method() {
706         cov_mark::check!(qualify_path_trait_method);
707         check_assist(
708             qualify_path,
709             r#"
710 mod test_mod {
711     pub trait TestTrait {
712         fn test_method(&self);
713     }
714     pub struct TestStruct {}
715     impl TestTrait for TestStruct {
716         fn test_method(&self) {}
717     }
718 }
719
720 fn main() {
721     let test_struct = test_mod::TestStruct {};
722     test_struct.test_meth$0od()
723 }
724 "#,
725             r#"
726 mod test_mod {
727     pub trait TestTrait {
728         fn test_method(&self);
729     }
730     pub struct TestStruct {}
731     impl TestTrait for TestStruct {
732         fn test_method(&self) {}
733     }
734 }
735
736 fn main() {
737     let test_struct = test_mod::TestStruct {};
738     test_mod::TestTrait::test_method(&test_struct)
739 }
740 "#,
741         );
742     }
743
744     #[test]
745     fn trait_method_multi_params() {
746         check_assist(
747             qualify_path,
748             r#"
749 mod test_mod {
750     pub trait TestTrait {
751         fn test_method(&self, test: i32);
752     }
753     pub struct TestStruct {}
754     impl TestTrait for TestStruct {
755         fn test_method(&self, test: i32) {}
756     }
757 }
758
759 fn main() {
760     let test_struct = test_mod::TestStruct {};
761     test_struct.test_meth$0od(42)
762 }
763 "#,
764             r#"
765 mod test_mod {
766     pub trait TestTrait {
767         fn test_method(&self, test: i32);
768     }
769     pub struct TestStruct {}
770     impl TestTrait for TestStruct {
771         fn test_method(&self, test: i32) {}
772     }
773 }
774
775 fn main() {
776     let test_struct = test_mod::TestStruct {};
777     test_mod::TestTrait::test_method(&test_struct, 42)
778 }
779 "#,
780         );
781     }
782
783     #[test]
784     fn trait_method_consume() {
785         check_assist(
786             qualify_path,
787             r#"
788 mod test_mod {
789     pub trait TestTrait {
790         fn test_method(self);
791     }
792     pub struct TestStruct {}
793     impl TestTrait for TestStruct {
794         fn test_method(self) {}
795     }
796 }
797
798 fn main() {
799     let test_struct = test_mod::TestStruct {};
800     test_struct.test_meth$0od()
801 }
802 "#,
803             r#"
804 mod test_mod {
805     pub trait TestTrait {
806         fn test_method(self);
807     }
808     pub struct TestStruct {}
809     impl TestTrait for TestStruct {
810         fn test_method(self) {}
811     }
812 }
813
814 fn main() {
815     let test_struct = test_mod::TestStruct {};
816     test_mod::TestTrait::test_method(test_struct)
817 }
818 "#,
819         );
820     }
821
822     #[test]
823     fn trait_method_cross_crate() {
824         check_assist(
825             qualify_path,
826             r#"
827 //- /main.rs crate:main deps:dep
828 fn main() {
829     let test_struct = dep::test_mod::TestStruct {};
830     test_struct.test_meth$0od()
831 }
832 //- /dep.rs crate:dep
833 pub mod test_mod {
834     pub trait TestTrait {
835         fn test_method(&self);
836     }
837     pub struct TestStruct {}
838     impl TestTrait for TestStruct {
839         fn test_method(&self) {}
840     }
841 }
842 "#,
843             r#"
844 fn main() {
845     let test_struct = dep::test_mod::TestStruct {};
846     dep::test_mod::TestTrait::test_method(&test_struct)
847 }
848 "#,
849         );
850     }
851
852     #[test]
853     fn assoc_fn_cross_crate() {
854         check_assist(
855             qualify_path,
856             r#"
857 //- /main.rs crate:main deps:dep
858 fn main() {
859     dep::test_mod::TestStruct::test_func$0tion
860 }
861 //- /dep.rs crate:dep
862 pub mod test_mod {
863     pub trait TestTrait {
864         fn test_function();
865     }
866     pub struct TestStruct {}
867     impl TestTrait for TestStruct {
868         fn test_function() {}
869     }
870 }
871 "#,
872             r#"
873 fn main() {
874     <dep::test_mod::TestStruct as dep::test_mod::TestTrait>::test_function
875 }
876 "#,
877         );
878     }
879
880     #[test]
881     fn assoc_const_cross_crate() {
882         check_assist(
883             qualify_path,
884             r#"
885 //- /main.rs crate:main deps:dep
886 fn main() {
887     dep::test_mod::TestStruct::CONST$0
888 }
889 //- /dep.rs crate:dep
890 pub mod test_mod {
891     pub trait TestTrait {
892         const CONST: bool;
893     }
894     pub struct TestStruct {}
895     impl TestTrait for TestStruct {
896         const CONST: bool = true;
897     }
898 }
899 "#,
900             r#"
901 fn main() {
902     <dep::test_mod::TestStruct as dep::test_mod::TestTrait>::CONST
903 }
904 "#,
905         );
906     }
907
908     #[test]
909     fn assoc_fn_as_method_cross_crate() {
910         check_assist_not_applicable(
911             qualify_path,
912             r#"
913 //- /main.rs crate:main deps:dep
914 fn main() {
915     let test_struct = dep::test_mod::TestStruct {};
916     test_struct.test_func$0tion()
917 }
918 //- /dep.rs crate:dep
919 pub mod test_mod {
920     pub trait TestTrait {
921         fn test_function();
922     }
923     pub struct TestStruct {}
924     impl TestTrait for TestStruct {
925         fn test_function() {}
926     }
927 }
928 "#,
929         );
930     }
931
932     #[test]
933     fn private_trait_cross_crate() {
934         check_assist_not_applicable(
935             qualify_path,
936             r#"
937 //- /main.rs crate:main deps:dep
938 fn main() {
939     let test_struct = dep::test_mod::TestStruct {};
940     test_struct.test_meth$0od()
941 }
942 //- /dep.rs crate:dep
943 pub mod test_mod {
944     trait TestTrait {
945         fn test_method(&self);
946     }
947     pub struct TestStruct {}
948     impl TestTrait for TestStruct {
949         fn test_method(&self) {}
950     }
951 }
952 "#,
953         );
954     }
955
956     #[test]
957     fn not_applicable_for_imported_trait_for_method() {
958         check_assist_not_applicable(
959             qualify_path,
960             r#"
961 mod test_mod {
962     pub trait TestTrait {
963         fn test_method(&self);
964     }
965     pub trait TestTrait2 {
966         fn test_method(&self);
967     }
968     pub enum TestEnum {
969         One,
970         Two,
971     }
972     impl TestTrait2 for TestEnum {
973         fn test_method(&self) {}
974     }
975     impl TestTrait for TestEnum {
976         fn test_method(&self) {}
977     }
978 }
979
980 use test_mod::TestTrait2;
981 fn main() {
982     let one = test_mod::TestEnum::One;
983     one.test$0_method();
984 }
985 "#,
986         )
987     }
988
989     #[test]
990     fn dep_import() {
991         check_assist(
992             qualify_path,
993             r"
994 //- /lib.rs crate:dep
995 pub struct Struct;
996
997 //- /main.rs crate:main deps:dep
998 fn main() {
999     Struct$0
1000 }
1001 ",
1002             r"
1003 fn main() {
1004     dep::Struct
1005 }
1006 ",
1007         );
1008     }
1009
1010     #[test]
1011     fn whole_segment() {
1012         // Tests that only imports whose last segment matches the identifier get suggested.
1013         check_assist(
1014             qualify_path,
1015             r"
1016 //- /lib.rs crate:dep
1017 pub mod fmt {
1018     pub trait Display {}
1019 }
1020
1021 pub fn panic_fmt() {}
1022
1023 //- /main.rs crate:main deps:dep
1024 struct S;
1025
1026 impl f$0mt::Display for S {}
1027 ",
1028             r"
1029 struct S;
1030
1031 impl dep::fmt::Display for S {}
1032 ",
1033         );
1034     }
1035
1036     #[test]
1037     fn macro_generated() {
1038         // Tests that macro-generated items are suggested from external crates.
1039         check_assist(
1040             qualify_path,
1041             r"
1042 //- /lib.rs crate:dep
1043 macro_rules! mac {
1044     () => {
1045         pub struct Cheese;
1046     };
1047 }
1048
1049 mac!();
1050
1051 //- /main.rs crate:main deps:dep
1052 fn main() {
1053     Cheese$0;
1054 }
1055 ",
1056             r"
1057 fn main() {
1058     dep::Cheese;
1059 }
1060 ",
1061         );
1062     }
1063
1064     #[test]
1065     fn casing() {
1066         // Tests that differently cased names don't interfere and we only suggest the matching one.
1067         check_assist(
1068             qualify_path,
1069             r"
1070 //- /lib.rs crate:dep
1071 pub struct FMT;
1072 pub struct fmt;
1073
1074 //- /main.rs crate:main deps:dep
1075 fn main() {
1076     FMT$0;
1077 }
1078 ",
1079             r"
1080 fn main() {
1081     dep::FMT;
1082 }
1083 ",
1084         );
1085     }
1086
1087     #[test]
1088     fn keep_generic_annotations() {
1089         check_assist(
1090             qualify_path,
1091             r"
1092 //- /lib.rs crate:dep
1093 pub mod generic { pub struct Thing<'a, T>(&'a T); }
1094
1095 //- /main.rs crate:main deps:dep
1096 fn foo() -> Thin$0g<'static, ()> {}
1097
1098 fn main() {}
1099 ",
1100             r"
1101 fn foo() -> dep::generic::Thing<'static, ()> {}
1102
1103 fn main() {}
1104 ",
1105         );
1106     }
1107
1108     #[test]
1109     fn keep_generic_annotations_leading_colon() {
1110         check_assist(
1111             qualify_path,
1112             r#"
1113 //- /lib.rs crate:dep
1114 pub mod generic { pub struct Thing<'a, T>(&'a T); }
1115
1116 //- /main.rs crate:main deps:dep
1117 fn foo() -> Thin$0g::<'static, ()> {}
1118
1119 fn main() {}
1120 "#,
1121             r"
1122 fn foo() -> dep::generic::Thing::<'static, ()> {}
1123
1124 fn main() {}
1125 ",
1126         );
1127     }
1128
1129     #[test]
1130     fn associated_struct_const_generic() {
1131         check_assist(
1132             qualify_path,
1133             r#"
1134 mod test_mod {
1135     pub struct TestStruct<T> {}
1136     impl<T> TestStruct<T> {
1137         const TEST_CONST: u8 = 42;
1138     }
1139 }
1140
1141 fn main() {
1142     TestStruct::<()>::TEST_CONST$0
1143 }
1144 "#,
1145             r#"
1146 mod test_mod {
1147     pub struct TestStruct<T> {}
1148     impl<T> TestStruct<T> {
1149         const TEST_CONST: u8 = 42;
1150     }
1151 }
1152
1153 fn main() {
1154     test_mod::TestStruct::<()>::TEST_CONST
1155 }
1156 "#,
1157         );
1158     }
1159
1160     #[test]
1161     fn associated_trait_const_generic() {
1162         check_assist(
1163             qualify_path,
1164             r#"
1165 mod test_mod {
1166     pub trait TestTrait {
1167         const TEST_CONST: u8;
1168     }
1169     pub struct TestStruct<T> {}
1170     impl<T> TestTrait for TestStruct<T> {
1171         const TEST_CONST: u8 = 42;
1172     }
1173 }
1174
1175 fn main() {
1176     test_mod::TestStruct::<()>::TEST_CONST$0
1177 }
1178 "#,
1179             r#"
1180 mod test_mod {
1181     pub trait TestTrait {
1182         const TEST_CONST: u8;
1183     }
1184     pub struct TestStruct<T> {}
1185     impl<T> TestTrait for TestStruct<T> {
1186         const TEST_CONST: u8 = 42;
1187     }
1188 }
1189
1190 fn main() {
1191     <test_mod::TestStruct::<()> as test_mod::TestTrait>::TEST_CONST
1192 }
1193 "#,
1194         );
1195     }
1196
1197     #[test]
1198     fn trait_method_generic() {
1199         check_assist(
1200             qualify_path,
1201             r#"
1202 mod test_mod {
1203     pub trait TestTrait {
1204         fn test_method<T>(&self);
1205     }
1206     pub struct TestStruct {}
1207     impl TestTrait for TestStruct {
1208         fn test_method<T>(&self) {}
1209     }
1210 }
1211
1212 fn main() {
1213     let test_struct = test_mod::TestStruct {};
1214     test_struct.test_meth$0od::<()>()
1215 }
1216 "#,
1217             r#"
1218 mod test_mod {
1219     pub trait TestTrait {
1220         fn test_method<T>(&self);
1221     }
1222     pub struct TestStruct {}
1223     impl TestTrait for TestStruct {
1224         fn test_method<T>(&self) {}
1225     }
1226 }
1227
1228 fn main() {
1229     let test_struct = test_mod::TestStruct {};
1230     test_mod::TestTrait::test_method::<()>(&test_struct)
1231 }
1232 "#,
1233         );
1234     }
1235
1236     #[test]
1237     fn works_in_derives() {
1238         check_assist(
1239             qualify_path,
1240             r#"
1241 //- minicore:derive
1242 mod foo {
1243     #[rustc_builtin_macro]
1244     pub macro Copy {}
1245 }
1246 #[derive(Copy$0)]
1247 struct Foo;
1248 "#,
1249             r#"
1250 mod foo {
1251     #[rustc_builtin_macro]
1252     pub macro Copy {}
1253 }
1254 #[derive(foo::Copy)]
1255 struct Foo;
1256 "#,
1257         );
1258     }
1259
1260     #[test]
1261     fn works_in_use_start() {
1262         check_assist(
1263             qualify_path,
1264             r#"
1265 mod bar {
1266     pub mod foo {
1267         pub struct Foo;
1268     }
1269 }
1270 use foo$0::Foo;
1271 "#,
1272             r#"
1273 mod bar {
1274     pub mod foo {
1275         pub struct Foo;
1276     }
1277 }
1278 use bar::foo::Foo;
1279 "#,
1280         );
1281     }
1282
1283     #[test]
1284     fn not_applicable_in_non_start_use() {
1285         check_assist_not_applicable(
1286             qualify_path,
1287             r"
1288 mod bar {
1289     pub mod foo {
1290         pub struct Foo;
1291     }
1292 }
1293 use foo::Foo$0;
1294 ",
1295         );
1296     }
1297 }