]> git.lizzy.rs Git - rust.git/blob - crates/ide-assists/src/handlers/auto_import.rs
style: rename crates to kebab case
[rust.git] / crates / ide-assists / src / handlers / auto_import.rs
1 use ide_db::{
2     helpers::mod_path_to_ast,
3     imports::{
4         import_assets::{ImportAssets, ImportCandidate},
5         insert_use::{insert_use, ImportScope},
6     },
7 };
8 use syntax::{ast, AstNode, NodeOrToken, SyntaxElement};
9
10 use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
11
12 // Feature: Auto Import
13 //
14 // Using the `auto-import` assist it is possible to insert missing imports for unresolved items.
15 // When inserting an import it will do so in a structured manner by keeping imports grouped,
16 // separated by a newline in the following order:
17 //
18 // - `std` and `core`
19 // - External Crates
20 // - Current Crate, paths prefixed by `crate`
21 // - Current Module, paths prefixed by `self`
22 // - Super Module, paths prefixed by `super`
23 //
24 // Example:
25 // ```rust
26 // use std::fs::File;
27 //
28 // use itertools::Itertools;
29 // use syntax::ast;
30 //
31 // use crate::utils::insert_use;
32 //
33 // use self::auto_import;
34 //
35 // use super::AssistContext;
36 // ```
37 //
38 // .Import Granularity
39 //
40 // It is possible to configure how use-trees are merged with the `importGranularity` setting.
41 // It has the following configurations:
42 //
43 // - `crate`: Merge imports from the same crate into a single use statement. This kind of
44 //  nesting is only supported in Rust versions later than 1.24.
45 // - `module`: Merge imports from the same module into a single use statement.
46 // - `item`: Don't merge imports at all, creating one import per item.
47 // - `preserve`: Do not change the granularity of any imports. For auto-import this has the same
48 //  effect as `item`.
49 //
50 // In `VS Code` the configuration for this is `rust-analyzer.assist.importGranularity`.
51 //
52 // .Import Prefix
53 //
54 // The style of imports in the same crate is configurable through the `importPrefix` setting.
55 // It has the following configurations:
56 //
57 // - `crate`: This setting will force paths to be always absolute, starting with the `crate`
58 //  prefix, unless the item is defined outside of the current crate.
59 // - `self`: This setting will force paths that are relative to the current module to always
60 //  start with `self`. This will result in paths that always start with either `crate`, `self`,
61 //  `super` or an extern crate identifier.
62 // - `plain`: This setting does not impose any restrictions in imports.
63 //
64 // In `VS Code` the configuration for this is `rust-analyzer.assist.importPrefix`.
65 //
66 // image::https://user-images.githubusercontent.com/48062697/113020673-b85be580-917a-11eb-9022-59585f35d4f8.gif[]
67
68 // Assist: auto_import
69 //
70 // If the name is unresolved, provides all possible imports for it.
71 //
72 // ```
73 // fn main() {
74 //     let map = HashMap$0::new();
75 // }
76 // # pub mod std { pub mod collections { pub struct HashMap { } } }
77 // ```
78 // ->
79 // ```
80 // use std::collections::HashMap;
81 //
82 // fn main() {
83 //     let map = HashMap::new();
84 // }
85 // # pub mod std { pub mod collections { pub struct HashMap { } } }
86 // ```
87 pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
88     let (import_assets, syntax_under_caret) = find_importable_node(ctx)?;
89     let mut proposed_imports =
90         import_assets.search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind);
91     if proposed_imports.is_empty() {
92         return None;
93     }
94
95     let range = match &syntax_under_caret {
96         NodeOrToken::Node(node) => ctx.sema.original_range(node).range,
97         NodeOrToken::Token(token) => token.text_range(),
98     };
99     let group_label = group_label(import_assets.import_candidate());
100     let scope = ImportScope::find_insert_use_container(
101         &match syntax_under_caret {
102             NodeOrToken::Node(it) => it,
103             NodeOrToken::Token(it) => it.parent()?,
104         },
105         &ctx.sema,
106     )?;
107
108     // we aren't interested in different namespaces
109     proposed_imports.dedup_by(|a, b| a.import_path == b.import_path);
110     for import in proposed_imports {
111         acc.add_group(
112             &group_label,
113             AssistId("auto_import", AssistKind::QuickFix),
114             format!("Import `{}`", import.import_path),
115             range,
116             |builder| {
117                 let scope = match scope.clone() {
118                     ImportScope::File(it) => ImportScope::File(builder.make_mut(it)),
119                     ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
120                     ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
121                 };
122                 insert_use(&scope, mod_path_to_ast(&import.import_path), &ctx.config.insert_use);
123             },
124         );
125     }
126     Some(())
127 }
128
129 pub(super) fn find_importable_node(ctx: &AssistContext) -> Option<(ImportAssets, SyntaxElement)> {
130     if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::<ast::Path>() {
131         ImportAssets::for_exact_path(&path_under_caret, &ctx.sema)
132             .zip(Some(path_under_caret.syntax().clone().into()))
133     } else if let Some(method_under_caret) =
134         ctx.find_node_at_offset_with_descend::<ast::MethodCallExpr>()
135     {
136         ImportAssets::for_method_call(&method_under_caret, &ctx.sema)
137             .zip(Some(method_under_caret.syntax().clone().into()))
138     } else if let Some(pat) = ctx
139         .find_node_at_offset_with_descend::<ast::IdentPat>()
140         .filter(ast::IdentPat::is_simple_ident)
141     {
142         ImportAssets::for_ident_pat(&ctx.sema, &pat).zip(Some(pat.syntax().clone().into()))
143     } else {
144         None
145     }
146 }
147
148 fn group_label(import_candidate: &ImportCandidate) -> GroupLabel {
149     let name = match import_candidate {
150         ImportCandidate::Path(candidate) => format!("Import {}", candidate.name.text()),
151         ImportCandidate::TraitAssocItem(candidate) => {
152             format!("Import a trait for item {}", candidate.assoc_item_name.text())
153         }
154         ImportCandidate::TraitMethod(candidate) => {
155             format!("Import a trait for method {}", candidate.assoc_item_name.text())
156         }
157     };
158     GroupLabel(name)
159 }
160
161 #[cfg(test)]
162 mod tests {
163     use super::*;
164
165     use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
166
167     #[test]
168     fn not_applicable_if_scope_inside_macro() {
169         check_assist_not_applicable(
170             auto_import,
171             r"
172 mod bar {
173     pub struct Baz;
174 }
175 macro_rules! foo {
176     ($it:ident) => {
177         mod __ {
178             fn __(x: $it) {}
179         }
180     };
181 }
182 foo! {
183     Baz$0
184 }
185 ",
186         );
187     }
188
189     #[test]
190     fn applicable_in_attributes() {
191         check_assist(
192             auto_import,
193             r"
194 //- proc_macros: identity
195 #[proc_macros::identity]
196 mod foo {
197     mod bar {
198         const _: Baz$0 = ();
199     }
200 }
201 mod baz {
202     pub struct Baz;
203 }
204 ",
205             r"
206 #[proc_macros::identity]
207 mod foo {
208     mod bar {
209         use crate::baz::Baz;
210
211         const _: Baz = ();
212     }
213 }
214 mod baz {
215     pub struct Baz;
216 }
217 ",
218         );
219     }
220
221     #[test]
222     fn applicable_when_found_an_import_partial() {
223         check_assist(
224             auto_import,
225             r"
226             mod std {
227                 pub mod fmt {
228                     pub struct Formatter;
229                 }
230             }
231
232             use std::fmt;
233
234             $0Formatter
235             ",
236             r"
237             mod std {
238                 pub mod fmt {
239                     pub struct Formatter;
240                 }
241             }
242
243             use std::fmt::{self, Formatter};
244
245             Formatter
246             ",
247         );
248     }
249
250     #[test]
251     fn applicable_when_found_an_import() {
252         check_assist(
253             auto_import,
254             r"
255             $0PubStruct
256
257             pub mod PubMod {
258                 pub struct PubStruct;
259             }
260             ",
261             r"
262             use PubMod::PubStruct;
263
264             PubStruct
265
266             pub mod PubMod {
267                 pub struct PubStruct;
268             }
269             ",
270         );
271     }
272
273     #[test]
274     fn applicable_when_found_an_import_in_macros() {
275         check_assist(
276             auto_import,
277             r"
278             macro_rules! foo {
279                 ($i:ident) => { fn foo(a: $i) {} }
280             }
281             foo!(Pub$0Struct);
282
283             pub mod PubMod {
284                 pub struct PubStruct;
285             }
286             ",
287             r"
288             use PubMod::PubStruct;
289
290             macro_rules! foo {
291                 ($i:ident) => { fn foo(a: $i) {} }
292             }
293             foo!(PubStruct);
294
295             pub mod PubMod {
296                 pub struct PubStruct;
297             }
298             ",
299         );
300     }
301
302     #[test]
303     fn applicable_when_found_multiple_imports() {
304         check_assist(
305             auto_import,
306             r"
307             PubSt$0ruct
308
309             pub mod PubMod1 {
310                 pub struct PubStruct;
311             }
312             pub mod PubMod2 {
313                 pub struct PubStruct;
314             }
315             pub mod PubMod3 {
316                 pub struct PubStruct;
317             }
318             ",
319             r"
320             use PubMod3::PubStruct;
321
322             PubStruct
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         );
335     }
336
337     #[test]
338     fn not_applicable_for_already_imported_types() {
339         check_assist_not_applicable(
340             auto_import,
341             r"
342             use PubMod::PubStruct;
343
344             PubStruct$0
345
346             pub mod PubMod {
347                 pub struct PubStruct;
348             }
349             ",
350         );
351     }
352
353     #[test]
354     fn not_applicable_for_types_with_private_paths() {
355         check_assist_not_applicable(
356             auto_import,
357             r"
358             PrivateStruct$0
359
360             pub mod PubMod {
361                 struct PrivateStruct;
362             }
363             ",
364         );
365     }
366
367     #[test]
368     fn not_applicable_when_no_imports_found() {
369         check_assist_not_applicable(
370             auto_import,
371             "
372             PubStruct$0",
373         );
374     }
375
376     #[test]
377     fn not_applicable_in_import_statements() {
378         check_assist_not_applicable(
379             auto_import,
380             r"
381             use PubStruct$0;
382
383             pub mod PubMod {
384                 pub struct PubStruct;
385             }",
386         );
387     }
388
389     #[test]
390     fn function_import() {
391         check_assist(
392             auto_import,
393             r"
394             test_function$0
395
396             pub mod PubMod {
397                 pub fn test_function() {};
398             }
399             ",
400             r"
401             use PubMod::test_function;
402
403             test_function
404
405             pub mod PubMod {
406                 pub fn test_function() {};
407             }
408             ",
409         );
410     }
411
412     #[test]
413     fn macro_import() {
414         check_assist(
415             auto_import,
416             r"
417 //- /lib.rs crate:crate_with_macro
418 #[macro_export]
419 macro_rules! foo {
420     () => ()
421 }
422
423 //- /main.rs crate:main deps:crate_with_macro
424 fn main() {
425     foo$0
426 }
427 ",
428             r"use crate_with_macro::foo;
429
430 fn main() {
431     foo
432 }
433 ",
434         );
435     }
436
437     #[test]
438     fn auto_import_target() {
439         check_assist_target(
440             auto_import,
441             r"
442             struct AssistInfo {
443                 group_label: Option<$0GroupLabel>,
444             }
445
446             mod m { pub struct GroupLabel; }
447             ",
448             "GroupLabel",
449         )
450     }
451
452     #[test]
453     fn not_applicable_when_path_start_is_imported() {
454         check_assist_not_applicable(
455             auto_import,
456             r"
457             pub mod mod1 {
458                 pub mod mod2 {
459                     pub mod mod3 {
460                         pub struct TestStruct;
461                     }
462                 }
463             }
464
465             use mod1::mod2;
466             fn main() {
467                 mod2::mod3::TestStruct$0
468             }
469             ",
470         );
471     }
472
473     #[test]
474     fn not_applicable_for_imported_function() {
475         check_assist_not_applicable(
476             auto_import,
477             r"
478             pub mod test_mod {
479                 pub fn test_function() {}
480             }
481
482             use test_mod::test_function;
483             fn main() {
484                 test_function$0
485             }
486             ",
487         );
488     }
489
490     #[test]
491     fn associated_struct_function() {
492         check_assist(
493             auto_import,
494             r"
495             mod test_mod {
496                 pub struct TestStruct {}
497                 impl TestStruct {
498                     pub fn test_function() {}
499                 }
500             }
501
502             fn main() {
503                 TestStruct::test_function$0
504             }
505             ",
506             r"
507             use test_mod::TestStruct;
508
509             mod test_mod {
510                 pub struct TestStruct {}
511                 impl TestStruct {
512                     pub fn test_function() {}
513                 }
514             }
515
516             fn main() {
517                 TestStruct::test_function
518             }
519             ",
520         );
521     }
522
523     #[test]
524     fn associated_struct_const() {
525         check_assist(
526             auto_import,
527             r"
528             mod test_mod {
529                 pub struct TestStruct {}
530                 impl TestStruct {
531                     const TEST_CONST: u8 = 42;
532                 }
533             }
534
535             fn main() {
536                 TestStruct::TEST_CONST$0
537             }
538             ",
539             r"
540             use test_mod::TestStruct;
541
542             mod test_mod {
543                 pub struct TestStruct {}
544                 impl TestStruct {
545                     const TEST_CONST: u8 = 42;
546                 }
547             }
548
549             fn main() {
550                 TestStruct::TEST_CONST
551             }
552             ",
553         );
554     }
555
556     #[test]
557     fn associated_trait_function() {
558         check_assist(
559             auto_import,
560             r"
561             mod test_mod {
562                 pub trait TestTrait {
563                     fn test_function();
564                 }
565                 pub struct TestStruct {}
566                 impl TestTrait for TestStruct {
567                     fn test_function() {}
568                 }
569             }
570
571             fn main() {
572                 test_mod::TestStruct::test_function$0
573             }
574             ",
575             r"
576             use test_mod::TestTrait;
577
578             mod test_mod {
579                 pub trait TestTrait {
580                     fn test_function();
581                 }
582                 pub struct TestStruct {}
583                 impl TestTrait for TestStruct {
584                     fn test_function() {}
585                 }
586             }
587
588             fn main() {
589                 test_mod::TestStruct::test_function
590             }
591             ",
592         );
593     }
594
595     #[test]
596     fn not_applicable_for_imported_trait_for_function() {
597         check_assist_not_applicable(
598             auto_import,
599             r"
600             mod test_mod {
601                 pub trait TestTrait {
602                     fn test_function();
603                 }
604                 pub trait TestTrait2 {
605                     fn test_function();
606                 }
607                 pub enum TestEnum {
608                     One,
609                     Two,
610                 }
611                 impl TestTrait2 for TestEnum {
612                     fn test_function() {}
613                 }
614                 impl TestTrait for TestEnum {
615                     fn test_function() {}
616                 }
617             }
618
619             use test_mod::TestTrait2;
620             fn main() {
621                 test_mod::TestEnum::test_function$0;
622             }
623             ",
624         )
625     }
626
627     #[test]
628     fn associated_trait_const() {
629         check_assist(
630             auto_import,
631             r"
632             mod test_mod {
633                 pub trait TestTrait {
634                     const TEST_CONST: u8;
635                 }
636                 pub struct TestStruct {}
637                 impl TestTrait for TestStruct {
638                     const TEST_CONST: u8 = 42;
639                 }
640             }
641
642             fn main() {
643                 test_mod::TestStruct::TEST_CONST$0
644             }
645             ",
646             r"
647             use test_mod::TestTrait;
648
649             mod test_mod {
650                 pub trait TestTrait {
651                     const TEST_CONST: u8;
652                 }
653                 pub struct TestStruct {}
654                 impl TestTrait for TestStruct {
655                     const TEST_CONST: u8 = 42;
656                 }
657             }
658
659             fn main() {
660                 test_mod::TestStruct::TEST_CONST
661             }
662             ",
663         );
664     }
665
666     #[test]
667     fn not_applicable_for_imported_trait_for_const() {
668         check_assist_not_applicable(
669             auto_import,
670             r"
671             mod test_mod {
672                 pub trait TestTrait {
673                     const TEST_CONST: u8;
674                 }
675                 pub trait TestTrait2 {
676                     const TEST_CONST: f64;
677                 }
678                 pub enum TestEnum {
679                     One,
680                     Two,
681                 }
682                 impl TestTrait2 for TestEnum {
683                     const TEST_CONST: f64 = 42.0;
684                 }
685                 impl TestTrait for TestEnum {
686                     const TEST_CONST: u8 = 42;
687                 }
688             }
689
690             use test_mod::TestTrait2;
691             fn main() {
692                 test_mod::TestEnum::TEST_CONST$0;
693             }
694             ",
695         )
696     }
697
698     #[test]
699     fn trait_method() {
700         check_assist(
701             auto_import,
702             r"
703             mod test_mod {
704                 pub trait TestTrait {
705                     fn test_method(&self);
706                 }
707                 pub struct TestStruct {}
708                 impl TestTrait for TestStruct {
709                     fn test_method(&self) {}
710                 }
711             }
712
713             fn main() {
714                 let test_struct = test_mod::TestStruct {};
715                 test_struct.test_meth$0od()
716             }
717             ",
718             r"
719             use test_mod::TestTrait;
720
721             mod test_mod {
722                 pub trait TestTrait {
723                     fn test_method(&self);
724                 }
725                 pub struct TestStruct {}
726                 impl TestTrait for TestStruct {
727                     fn test_method(&self) {}
728                 }
729             }
730
731             fn main() {
732                 let test_struct = test_mod::TestStruct {};
733                 test_struct.test_method()
734             }
735             ",
736         );
737     }
738
739     #[test]
740     fn trait_method_cross_crate() {
741         check_assist(
742             auto_import,
743             r"
744             //- /main.rs crate:main deps:dep
745             fn main() {
746                 let test_struct = dep::test_mod::TestStruct {};
747                 test_struct.test_meth$0od()
748             }
749             //- /dep.rs crate:dep
750             pub mod test_mod {
751                 pub trait TestTrait {
752                     fn test_method(&self);
753                 }
754                 pub struct TestStruct {}
755                 impl TestTrait for TestStruct {
756                     fn test_method(&self) {}
757                 }
758             }
759             ",
760             r"
761             use dep::test_mod::TestTrait;
762
763             fn main() {
764                 let test_struct = dep::test_mod::TestStruct {};
765                 test_struct.test_method()
766             }
767             ",
768         );
769     }
770
771     #[test]
772     fn assoc_fn_cross_crate() {
773         check_assist(
774             auto_import,
775             r"
776             //- /main.rs crate:main deps:dep
777             fn main() {
778                 dep::test_mod::TestStruct::test_func$0tion
779             }
780             //- /dep.rs crate:dep
781             pub mod test_mod {
782                 pub trait TestTrait {
783                     fn test_function();
784                 }
785                 pub struct TestStruct {}
786                 impl TestTrait for TestStruct {
787                     fn test_function() {}
788                 }
789             }
790             ",
791             r"
792             use dep::test_mod::TestTrait;
793
794             fn main() {
795                 dep::test_mod::TestStruct::test_function
796             }
797             ",
798         );
799     }
800
801     #[test]
802     fn assoc_const_cross_crate() {
803         check_assist(
804             auto_import,
805             r"
806             //- /main.rs crate:main deps:dep
807             fn main() {
808                 dep::test_mod::TestStruct::CONST$0
809             }
810             //- /dep.rs crate:dep
811             pub mod test_mod {
812                 pub trait TestTrait {
813                     const CONST: bool;
814                 }
815                 pub struct TestStruct {}
816                 impl TestTrait for TestStruct {
817                     const CONST: bool = true;
818                 }
819             }
820             ",
821             r"
822             use dep::test_mod::TestTrait;
823
824             fn main() {
825                 dep::test_mod::TestStruct::CONST
826             }
827             ",
828         );
829     }
830
831     #[test]
832     fn assoc_fn_as_method_cross_crate() {
833         check_assist_not_applicable(
834             auto_import,
835             r"
836             //- /main.rs crate:main deps:dep
837             fn main() {
838                 let test_struct = dep::test_mod::TestStruct {};
839                 test_struct.test_func$0tion()
840             }
841             //- /dep.rs crate:dep
842             pub mod test_mod {
843                 pub trait TestTrait {
844                     fn test_function();
845                 }
846                 pub struct TestStruct {}
847                 impl TestTrait for TestStruct {
848                     fn test_function() {}
849                 }
850             }
851             ",
852         );
853     }
854
855     #[test]
856     fn private_trait_cross_crate() {
857         check_assist_not_applicable(
858             auto_import,
859             r"
860             //- /main.rs crate:main deps:dep
861             fn main() {
862                 let test_struct = dep::test_mod::TestStruct {};
863                 test_struct.test_meth$0od()
864             }
865             //- /dep.rs crate:dep
866             pub mod test_mod {
867                 trait TestTrait {
868                     fn test_method(&self);
869                 }
870                 pub struct TestStruct {}
871                 impl TestTrait for TestStruct {
872                     fn test_method(&self) {}
873                 }
874             }
875             ",
876         );
877     }
878
879     #[test]
880     fn not_applicable_for_imported_trait_for_method() {
881         check_assist_not_applicable(
882             auto_import,
883             r"
884             mod test_mod {
885                 pub trait TestTrait {
886                     fn test_method(&self);
887                 }
888                 pub trait TestTrait2 {
889                     fn test_method(&self);
890                 }
891                 pub enum TestEnum {
892                     One,
893                     Two,
894                 }
895                 impl TestTrait2 for TestEnum {
896                     fn test_method(&self) {}
897                 }
898                 impl TestTrait for TestEnum {
899                     fn test_method(&self) {}
900                 }
901             }
902
903             use test_mod::TestTrait2;
904             fn main() {
905                 let one = test_mod::TestEnum::One;
906                 one.test$0_method();
907             }
908             ",
909         )
910     }
911
912     #[test]
913     fn dep_import() {
914         check_assist(
915             auto_import,
916             r"
917 //- /lib.rs crate:dep
918 pub struct Struct;
919
920 //- /main.rs crate:main deps:dep
921 fn main() {
922     Struct$0
923 }
924 ",
925             r"use dep::Struct;
926
927 fn main() {
928     Struct
929 }
930 ",
931         );
932     }
933
934     #[test]
935     fn whole_segment() {
936         // Tests that only imports whose last segment matches the identifier get suggested.
937         check_assist(
938             auto_import,
939             r"
940 //- /lib.rs crate:dep
941 pub mod fmt {
942     pub trait Display {}
943 }
944
945 pub fn panic_fmt() {}
946
947 //- /main.rs crate:main deps:dep
948 struct S;
949
950 impl f$0mt::Display for S {}
951 ",
952             r"use dep::fmt;
953
954 struct S;
955
956 impl fmt::Display for S {}
957 ",
958         );
959     }
960
961     #[test]
962     fn macro_generated() {
963         // Tests that macro-generated items are suggested from external crates.
964         check_assist(
965             auto_import,
966             r"
967 //- /lib.rs crate:dep
968 macro_rules! mac {
969     () => {
970         pub struct Cheese;
971     };
972 }
973
974 mac!();
975
976 //- /main.rs crate:main deps:dep
977 fn main() {
978     Cheese$0;
979 }
980 ",
981             r"use dep::Cheese;
982
983 fn main() {
984     Cheese;
985 }
986 ",
987         );
988     }
989
990     #[test]
991     fn casing() {
992         // Tests that differently cased names don't interfere and we only suggest the matching one.
993         check_assist(
994             auto_import,
995             r"
996 //- /lib.rs crate:dep
997 pub struct FMT;
998 pub struct fmt;
999
1000 //- /main.rs crate:main deps:dep
1001 fn main() {
1002     FMT$0;
1003 }
1004 ",
1005             r"use dep::FMT;
1006
1007 fn main() {
1008     FMT;
1009 }
1010 ",
1011         );
1012     }
1013
1014     #[test]
1015     fn inner_items() {
1016         check_assist(
1017             auto_import,
1018             r#"
1019 mod baz {
1020     pub struct Foo {}
1021 }
1022
1023 mod bar {
1024     fn bar() {
1025         Foo$0;
1026         println!("Hallo");
1027     }
1028 }
1029 "#,
1030             r#"
1031 mod baz {
1032     pub struct Foo {}
1033 }
1034
1035 mod bar {
1036     use crate::baz::Foo;
1037
1038     fn bar() {
1039         Foo;
1040         println!("Hallo");
1041     }
1042 }
1043 "#,
1044         );
1045     }
1046
1047     #[test]
1048     fn uses_abs_path_with_extern_crate_clash() {
1049         cov_mark::check!(ambiguous_crate_start);
1050         check_assist(
1051             auto_import,
1052             r#"
1053 //- /main.rs crate:main deps:foo
1054 mod foo {}
1055
1056 const _: () = {
1057     Foo$0
1058 };
1059 //- /foo.rs crate:foo
1060 pub struct Foo
1061 "#,
1062             r#"
1063 use ::foo::Foo;
1064
1065 mod foo {}
1066
1067 const _: () = {
1068     Foo
1069 };
1070 "#,
1071         );
1072     }
1073
1074     #[test]
1075     fn works_on_ident_patterns() {
1076         check_assist(
1077             auto_import,
1078             r#"
1079 mod foo {
1080     pub struct Foo {}
1081 }
1082 fn foo() {
1083     let Foo$0;
1084 }
1085 "#,
1086             r#"
1087 use foo::Foo;
1088
1089 mod foo {
1090     pub struct Foo {}
1091 }
1092 fn foo() {
1093     let Foo;
1094 }
1095 "#,
1096         );
1097     }
1098
1099     #[test]
1100     fn works_in_derives() {
1101         check_assist(
1102             auto_import,
1103             r#"
1104 //- minicore:derive
1105 mod foo {
1106     #[rustc_builtin_macro]
1107     pub macro Copy {}
1108 }
1109 #[derive(Copy$0)]
1110 struct Foo;
1111 "#,
1112             r#"
1113 use foo::Copy;
1114
1115 mod foo {
1116     #[rustc_builtin_macro]
1117     pub macro Copy {}
1118 }
1119 #[derive(Copy)]
1120 struct Foo;
1121 "#,
1122         );
1123     }
1124 }