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