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