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