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