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