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