ide_assists/handlers/
auto_import.rs

1use std::cmp::Reverse;
2
3use either::Either;
4use hir::{Module, Type, db::HirDatabase};
5use ide_db::{
6    active_parameter::ActiveParameter,
7    helpers::mod_path_to_ast,
8    imports::{
9        import_assets::{ImportAssets, ImportCandidate, LocatedImport},
10        insert_use::{ImportScope, insert_use, insert_use_as_alias},
11    },
12};
13use syntax::{AstNode, Edition, SyntaxNode, ast, match_ast};
14
15use crate::{AssistContext, AssistId, Assists, GroupLabel};
16
17// Feature: Auto Import
18//
19// Using the `auto-import` assist it is possible to insert missing imports for unresolved items.
20// When inserting an import it will do so in a structured manner by keeping imports grouped,
21// separated by a newline in the following order:
22//
23// - `std` and `core`
24// - External Crates
25// - Current Crate, paths prefixed by `crate`
26// - Current Module, paths prefixed by `self`
27// - Super Module, paths prefixed by `super`
28//
29// Example:
30// ```rust
31// use std::fs::File;
32//
33// use itertools::Itertools;
34// use syntax::ast;
35//
36// use crate::utils::insert_use;
37//
38// use self::auto_import;
39//
40// use super::AssistContext;
41// ```
42//
43// #### Import Granularity
44//
45// It is possible to configure how use-trees are merged with the `imports.granularity.group` setting.
46// It has the following configurations:
47//
48// - `crate`: Merge imports from the same crate into a single use statement. This kind of
49//  nesting is only supported in Rust versions later than 1.24.
50// - `module`: Merge imports from the same module into a single use statement.
51// - `item`: Don't merge imports at all, creating one import per item.
52// - `preserve`: Do not change the granularity of any imports. For auto-import this has the same
53//  effect as `item`.
54// - `one`: Merge all imports into a single use statement as long as they have the same visibility
55//  and attributes.
56//
57// In `VS Code` the configuration for this is `rust-analyzer.imports.granularity.group`.
58//
59// #### Import Prefix
60//
61// The style of imports in the same crate is configurable through the `imports.prefix` setting.
62// It has the following configurations:
63//
64// - `crate`: This setting will force paths to be always absolute, starting with the `crate`
65//  prefix, unless the item is defined outside of the current crate.
66// - `self`: This setting will force paths that are relative to the current module to always
67//  start with `self`. This will result in paths that always start with either `crate`, `self`,
68//  `super` or an extern crate identifier.
69// - `plain`: This setting does not impose any restrictions in imports.
70//
71// In `VS Code` the configuration for this is `rust-analyzer.imports.prefix`.
72//
73// ![Auto Import](https://user-images.githubusercontent.com/48062697/113020673-b85be580-917a-11eb-9022-59585f35d4f8.gif)
74
75// Assist: auto_import
76//
77// If the name is unresolved, provides all possible imports for it.
78//
79// ```
80// fn main() {
81//     let map = HashMap$0::new();
82// }
83// # pub mod std { pub mod collections { pub struct HashMap { } } }
84// ```
85// ->
86// ```
87// use std::collections::HashMap;
88//
89// fn main() {
90//     let map = HashMap::new();
91// }
92// # pub mod std { pub mod collections { pub struct HashMap { } } }
93// ```
94pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
95    let cfg = ctx.config.import_path_config();
96
97    let (import_assets, syntax_under_caret, expected) = find_importable_node(ctx)?;
98    let mut proposed_imports: Vec<_> = import_assets
99        .search_for_imports(&ctx.sema, cfg, ctx.config.insert_use.prefix_kind)
100        .collect();
101    if proposed_imports.is_empty() {
102        return None;
103    }
104
105    let range = ctx.sema.original_range(&syntax_under_caret).range;
106    let scope = ImportScope::find_insert_use_container(&syntax_under_caret, &ctx.sema)?;
107
108    // we aren't interested in different namespaces
109    proposed_imports.sort_by(|a, b| a.import_path.cmp(&b.import_path));
110    proposed_imports.dedup_by(|a, b| a.import_path == b.import_path);
111
112    let current_module = ctx.sema.scope(scope.as_syntax_node()).map(|scope| scope.module());
113    // prioritize more relevant imports
114    proposed_imports.sort_by_key(|import| {
115        Reverse(relevance_score(ctx, import, expected.as_ref(), current_module.as_ref()))
116    });
117    let edition =
118        current_module.map(|it| it.krate(ctx.db()).edition(ctx.db())).unwrap_or(Edition::CURRENT);
119
120    let group_label = group_label(import_assets.import_candidate());
121    for import in proposed_imports {
122        let import_path = import.import_path;
123
124        let (assist_id, import_name) =
125            (AssistId::quick_fix("auto_import"), import_path.display(ctx.db(), edition));
126        acc.add_group(
127            &group_label,
128            assist_id,
129            format!("Import `{import_name}`"),
130            range,
131            |builder| {
132                let scope = builder.make_import_scope_mut(scope.clone());
133                insert_use(&scope, mod_path_to_ast(&import_path, edition), &ctx.config.insert_use);
134            },
135        );
136
137        match import_assets.import_candidate() {
138            ImportCandidate::TraitAssocItem(name) | ImportCandidate::TraitMethod(name) => {
139                let is_method =
140                    matches!(import_assets.import_candidate(), ImportCandidate::TraitMethod(_));
141                let type_ = if is_method { "method" } else { "item" };
142                let group_label = GroupLabel(format!(
143                    "Import a trait for {} {} by alias",
144                    type_,
145                    name.assoc_item_name.text()
146                ));
147                acc.add_group(
148                    &group_label,
149                    assist_id,
150                    format!("Import `{import_name} as _`"),
151                    range,
152                    |builder| {
153                        let scope = builder.make_import_scope_mut(scope.clone());
154                        insert_use_as_alias(
155                            &scope,
156                            mod_path_to_ast(&import_path, edition),
157                            &ctx.config.insert_use,
158                        );
159                    },
160                );
161            }
162            _ => {}
163        }
164    }
165    Some(())
166}
167
168pub(super) fn find_importable_node<'a: 'db, 'db>(
169    ctx: &'a AssistContext<'db>,
170) -> Option<(ImportAssets<'db>, SyntaxNode, Option<Type<'db>>)> {
171    // Deduplicate this with the `expected_type_and_name` logic for completions
172    let expected = |expr_or_pat: Either<ast::Expr, ast::Pat>| match expr_or_pat {
173        Either::Left(expr) => {
174            let parent = expr.syntax().parent()?;
175            // FIXME: Expand this
176            match_ast! {
177                match parent {
178                    ast::ArgList(list) => {
179                        ActiveParameter::at_arg(
180                            &ctx.sema,
181                            list,
182                            expr.syntax().text_range().start(),
183                        ).map(|ap| ap.ty)
184                    },
185                    ast::LetStmt(stmt) => {
186                        ctx.sema.type_of_pat(&stmt.pat()?).map(|t| t.original)
187                    },
188                    _ => None,
189                }
190            }
191        }
192        Either::Right(pat) => {
193            let parent = pat.syntax().parent()?;
194            // FIXME: Expand this
195            match_ast! {
196                match parent {
197                    ast::LetStmt(stmt) => {
198                        ctx.sema.type_of_expr(&stmt.initializer()?).map(|t| t.original)
199                    },
200                    _ => None,
201                }
202            }
203        }
204    };
205
206    if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::<ast::Path>() {
207        let expected =
208            path_under_caret.top_path().syntax().parent().and_then(Either::cast).and_then(expected);
209        ImportAssets::for_exact_path(&path_under_caret, &ctx.sema)
210            .map(|it| (it, path_under_caret.syntax().clone(), expected))
211    } else if let Some(method_under_caret) =
212        ctx.find_node_at_offset_with_descend::<ast::MethodCallExpr>()
213    {
214        let expected = expected(Either::Left(method_under_caret.clone().into()));
215        ImportAssets::for_method_call(&method_under_caret, &ctx.sema)
216            .map(|it| (it, method_under_caret.syntax().clone(), expected))
217    } else if ctx.find_node_at_offset_with_descend::<ast::Param>().is_some() {
218        None
219    } else if let Some(pat) = ctx
220        .find_node_at_offset_with_descend::<ast::IdentPat>()
221        .filter(ast::IdentPat::is_simple_ident)
222    {
223        let expected = expected(Either::Right(pat.clone().into()));
224        ImportAssets::for_ident_pat(&ctx.sema, &pat).map(|it| (it, pat.syntax().clone(), expected))
225    } else {
226        None
227    }
228}
229
230fn group_label(import_candidate: &ImportCandidate<'_>) -> GroupLabel {
231    let name = match import_candidate {
232        ImportCandidate::Path(candidate) => format!("Import {}", candidate.name.text()),
233        ImportCandidate::TraitAssocItem(candidate) => {
234            format!("Import a trait for item {}", candidate.assoc_item_name.text())
235        }
236        ImportCandidate::TraitMethod(candidate) => {
237            format!("Import a trait for method {}", candidate.assoc_item_name.text())
238        }
239    };
240    GroupLabel(name)
241}
242
243/// Determine how relevant a given import is in the current context. Higher scores are more
244/// relevant.
245pub(crate) fn relevance_score(
246    ctx: &AssistContext<'_>,
247    import: &LocatedImport,
248    expected: Option<&Type<'_>>,
249    current_module: Option<&Module>,
250) -> i32 {
251    let mut score = 0;
252
253    let db = ctx.db();
254
255    let item_module = match import.item_to_import {
256        hir::ItemInNs::Types(item) | hir::ItemInNs::Values(item) => item.module(db),
257        hir::ItemInNs::Macros(makro) => Some(makro.module(db)),
258    };
259
260    if let Some(expected) = expected {
261        let ty = match import.item_to_import {
262            hir::ItemInNs::Types(module_def) | hir::ItemInNs::Values(module_def) => {
263                match module_def {
264                    hir::ModuleDef::Function(function) => Some(function.ret_type(ctx.db())),
265                    hir::ModuleDef::Adt(adt) => Some(match adt {
266                        hir::Adt::Struct(it) => it.ty(ctx.db()),
267                        hir::Adt::Union(it) => it.ty(ctx.db()),
268                        hir::Adt::Enum(it) => it.ty(ctx.db()),
269                    }),
270                    hir::ModuleDef::Variant(variant) => Some(variant.constructor_ty(ctx.db())),
271                    hir::ModuleDef::Const(it) => Some(it.ty(ctx.db())),
272                    hir::ModuleDef::Static(it) => Some(it.ty(ctx.db())),
273                    hir::ModuleDef::TypeAlias(it) => Some(it.ty(ctx.db())),
274                    hir::ModuleDef::BuiltinType(it) => Some(it.ty(ctx.db())),
275                    _ => None,
276                }
277            }
278            hir::ItemInNs::Macros(_) => None,
279        };
280        if let Some(ty) = ty {
281            if ty == *expected {
282                score = 100000;
283            } else if ty.could_unify_with(ctx.db(), expected) {
284                score = 10000;
285            }
286        }
287    }
288
289    match item_module.zip(current_module) {
290        // get the distance between the imported path and the current module
291        // (prefer items that are more local)
292        Some((item_module, current_module)) => {
293            score -= module_distance_heuristic(db, current_module, &item_module) as i32;
294        }
295
296        // could not find relevant modules, so just use the length of the path as an estimate
297        None => return -(2 * import.import_path.len() as i32),
298    }
299
300    score
301}
302
303/// A heuristic that gives a higher score to modules that are more separated.
304fn module_distance_heuristic(db: &dyn HirDatabase, current: &Module, item: &Module) -> usize {
305    // get the path starting from the item to the respective crate roots
306    let mut current_path = current.path_to_root(db);
307    let mut item_path = item.path_to_root(db);
308
309    // we want paths going from the root to the item
310    current_path.reverse();
311    item_path.reverse();
312
313    // length of the common prefix of the two paths
314    let prefix_length = current_path.iter().zip(&item_path).take_while(|(a, b)| a == b).count();
315
316    // how many modules differ between the two paths (all modules, removing any duplicates)
317    let distinct_length = current_path.len() + item_path.len() - 2 * prefix_length;
318
319    // cost of importing from another crate
320    let crate_boundary_cost = if current.krate(db) == item.krate(db) {
321        0
322    } else if item.krate(db).origin(db).is_local() {
323        2
324    } else if item.krate(db).is_builtin(db) {
325        3
326    } else {
327        4
328    };
329
330    distinct_length + crate_boundary_cost
331}
332
333#[cfg(test)]
334mod tests {
335    use super::*;
336
337    use hir::{FileRange, Semantics};
338    use ide_db::{RootDatabase, assists::AssistResolveStrategy};
339    use test_fixture::WithFixture;
340
341    use crate::tests::{
342        TEST_CONFIG, check_assist, check_assist_by_label, check_assist_not_applicable,
343        check_assist_target,
344    };
345
346    fn check_auto_import_order(before: &str, order: &[&str]) {
347        let (db, file_id, range_or_offset) = RootDatabase::with_range_or_offset(before);
348        let frange = FileRange { file_id, range: range_or_offset.into() };
349
350        let sema = Semantics::new(&db);
351        let config = TEST_CONFIG;
352        let ctx = AssistContext::new(sema, &config, frange);
353        let mut acc = Assists::new(&ctx, AssistResolveStrategy::All);
354        auto_import(&mut acc, &ctx);
355        let assists = acc.finish();
356
357        let labels = assists.iter().map(|assist| assist.label.to_string()).collect::<Vec<_>>();
358
359        assert_eq!(labels, order);
360    }
361
362    #[test]
363    fn ignore_parameter_name() {
364        check_assist_not_applicable(
365            auto_import,
366            r"
367            mod foo {
368                pub mod bar {}
369            }
370
371            fn foo(bar$0: &str) {}
372            ",
373        );
374    }
375
376    #[test]
377    fn prefer_shorter_paths() {
378        let before = r"
379//- /main.rs crate:main deps:foo,bar
380HashMap$0::new();
381
382//- /lib.rs crate:foo
383pub mod collections { pub struct HashMap; }
384
385//- /lib.rs crate:bar
386pub mod collections { pub mod hash_map { pub struct HashMap; } }
387        ";
388
389        check_auto_import_order(
390            before,
391            &["Import `foo::collections::HashMap`", "Import `bar::collections::hash_map::HashMap`"],
392        )
393    }
394
395    #[test]
396    fn prefer_same_crate() {
397        let before = r"
398//- /main.rs crate:main deps:foo
399HashMap$0::new();
400
401mod collections {
402    pub mod hash_map {
403        pub struct HashMap;
404    }
405}
406
407//- /lib.rs crate:foo
408pub struct HashMap;
409        ";
410
411        check_auto_import_order(
412            before,
413            &["Import `collections::hash_map::HashMap`", "Import `foo::HashMap`"],
414        )
415    }
416
417    #[test]
418    fn prefer_workspace() {
419        let before = r"
420//- /main.rs crate:main deps:foo,bar
421HashMap$0::new();
422
423//- /lib.rs crate:foo
424pub mod module {
425    pub struct HashMap;
426}
427
428//- /lib.rs crate:bar library
429pub struct HashMap;
430        ";
431
432        check_auto_import_order(before, &["Import `foo::module::HashMap`", "Import `bar::HashMap`"])
433    }
434
435    #[test]
436    fn prefer_non_local_over_long_path() {
437        let before = r"
438//- /main.rs crate:main deps:foo,bar
439HashMap$0::new();
440
441//- /lib.rs crate:foo
442pub mod deeply {
443    pub mod nested {
444        pub mod module {
445            pub struct HashMap;
446        }
447    }
448}
449
450//- /lib.rs crate:bar library
451pub struct HashMap;
452        ";
453
454        check_auto_import_order(
455            before,
456            &["Import `bar::HashMap`", "Import `foo::deeply::nested::module::HashMap`"],
457        )
458    }
459
460    #[test]
461    fn not_applicable_if_scope_inside_macro() {
462        check_assist_not_applicable(
463            auto_import,
464            r"
465mod bar {
466    pub struct Baz;
467}
468macro_rules! foo {
469    ($it:ident) => {
470        mod __ {
471            fn __(x: $it) {}
472        }
473    };
474}
475foo! {
476    Baz$0
477}
478",
479        );
480    }
481
482    #[test]
483    fn applicable_in_attributes() {
484        check_assist(
485            auto_import,
486            r"
487//- proc_macros: identity
488#[proc_macros::identity]
489mod foo {
490    mod bar {
491        const _: Baz$0 = ();
492    }
493}
494mod baz {
495    pub struct Baz;
496}
497",
498            r"
499#[proc_macros::identity]
500mod foo {
501    mod bar {
502        use crate::baz::Baz;
503
504        const _: Baz = ();
505    }
506}
507mod baz {
508    pub struct Baz;
509}
510",
511        );
512    }
513
514    #[test]
515    fn applicable_when_found_an_import_partial() {
516        check_assist(
517            auto_import,
518            r"
519            mod std {
520                pub mod fmt {
521                    pub struct Formatter;
522                }
523            }
524
525            use std::fmt;
526
527            $0Formatter
528            ",
529            r"
530            mod std {
531                pub mod fmt {
532                    pub struct Formatter;
533                }
534            }
535
536            use std::fmt::{self, Formatter};
537
538            Formatter
539            ",
540        );
541    }
542
543    #[test]
544    fn applicable_when_found_an_import() {
545        check_assist(
546            auto_import,
547            r"
548            $0PubStruct
549
550            pub mod PubMod {
551                pub struct PubStruct;
552            }
553            ",
554            r"
555            use PubMod::PubStruct;
556
557            PubStruct
558
559            pub mod PubMod {
560                pub struct PubStruct;
561            }
562            ",
563        );
564    }
565
566    #[test]
567    fn applicable_when_found_an_import_in_macros() {
568        check_assist(
569            auto_import,
570            r"
571            macro_rules! foo {
572                ($i:ident) => { fn foo(a: $i) {} }
573            }
574            foo!(Pub$0Struct);
575
576            pub mod PubMod {
577                pub struct PubStruct;
578            }
579            ",
580            r"
581            use PubMod::PubStruct;
582
583            macro_rules! foo {
584                ($i:ident) => { fn foo(a: $i) {} }
585            }
586            foo!(PubStruct);
587
588            pub mod PubMod {
589                pub struct PubStruct;
590            }
591            ",
592        );
593    }
594
595    #[test]
596    fn applicable_when_found_multiple_imports() {
597        check_assist(
598            auto_import,
599            r"
600            PubSt$0ruct
601
602            pub mod PubMod1 {
603                pub struct PubStruct;
604            }
605            pub mod PubMod2 {
606                pub struct PubStruct;
607            }
608            pub mod PubMod3 {
609                pub struct PubStruct;
610            }
611            ",
612            r"
613            use PubMod1::PubStruct;
614
615            PubStruct
616
617            pub mod PubMod1 {
618                pub struct PubStruct;
619            }
620            pub mod PubMod2 {
621                pub struct PubStruct;
622            }
623            pub mod PubMod3 {
624                pub struct PubStruct;
625            }
626            ",
627        );
628    }
629
630    #[test]
631    fn not_applicable_for_already_imported_types() {
632        check_assist_not_applicable(
633            auto_import,
634            r"
635            use PubMod::PubStruct;
636
637            PubStruct$0
638
639            pub mod PubMod {
640                pub struct PubStruct;
641            }
642            ",
643        );
644    }
645
646    #[test]
647    fn not_applicable_for_types_with_private_paths() {
648        check_assist_not_applicable(
649            auto_import,
650            r"
651            PrivateStruct$0
652
653            pub mod PubMod {
654                struct PrivateStruct;
655            }
656            ",
657        );
658    }
659
660    #[test]
661    fn not_applicable_when_no_imports_found() {
662        check_assist_not_applicable(
663            auto_import,
664            "
665            PubStruct$0",
666        );
667    }
668
669    #[test]
670    fn function_import() {
671        check_assist(
672            auto_import,
673            r"
674            test_function$0
675
676            pub mod PubMod {
677                pub fn test_function() {};
678            }
679            ",
680            r"
681            use PubMod::test_function;
682
683            test_function
684
685            pub mod PubMod {
686                pub fn test_function() {};
687            }
688            ",
689        );
690    }
691
692    #[test]
693    fn macro_import() {
694        check_assist(
695            auto_import,
696            r"
697//- /lib.rs crate:crate_with_macro
698#[macro_export]
699macro_rules! foo {
700    () => ()
701}
702
703//- /main.rs crate:main deps:crate_with_macro
704fn main() {
705    foo$0
706}
707",
708            r"use crate_with_macro::foo;
709
710fn main() {
711    foo
712}
713",
714        );
715    }
716
717    #[test]
718    fn auto_import_target() {
719        check_assist_target(
720            auto_import,
721            r"
722            struct AssistInfo {
723                group_label: Option<$0GroupLabel>,
724            }
725
726            mod m { pub struct GroupLabel; }
727            ",
728            "GroupLabel",
729        )
730    }
731
732    #[test]
733    fn not_applicable_when_path_start_is_imported() {
734        check_assist_not_applicable(
735            auto_import,
736            r"
737            pub mod mod1 {
738                pub mod mod2 {
739                    pub mod mod3 {
740                        pub struct TestStruct;
741                    }
742                }
743            }
744
745            use mod1::mod2;
746            fn main() {
747                mod2::mod3::TestStruct$0
748            }
749            ",
750        );
751    }
752
753    #[test]
754    fn not_applicable_for_imported_function() {
755        check_assist_not_applicable(
756            auto_import,
757            r"
758            pub mod test_mod {
759                pub fn test_function() {}
760            }
761
762            use test_mod::test_function;
763            fn main() {
764                test_function$0
765            }
766            ",
767        );
768    }
769
770    #[test]
771    fn associated_struct_function() {
772        check_assist(
773            auto_import,
774            r"
775            mod test_mod {
776                pub struct TestStruct {}
777                impl TestStruct {
778                    pub fn test_function() {}
779                }
780            }
781
782            fn main() {
783                TestStruct::test_function$0
784            }
785            ",
786            r"
787            use test_mod::TestStruct;
788
789            mod test_mod {
790                pub struct TestStruct {}
791                impl TestStruct {
792                    pub fn test_function() {}
793                }
794            }
795
796            fn main() {
797                TestStruct::test_function
798            }
799            ",
800        );
801    }
802
803    #[test]
804    fn associated_struct_const() {
805        check_assist(
806            auto_import,
807            r"
808            mod test_mod {
809                pub struct TestStruct {}
810                impl TestStruct {
811                    const TEST_CONST: u8 = 42;
812                }
813            }
814
815            fn main() {
816                TestStruct::TEST_CONST$0
817            }
818            ",
819            r"
820            use test_mod::TestStruct;
821
822            mod test_mod {
823                pub struct TestStruct {}
824                impl TestStruct {
825                    const TEST_CONST: u8 = 42;
826                }
827            }
828
829            fn main() {
830                TestStruct::TEST_CONST
831            }
832            ",
833        );
834    }
835
836    #[test]
837    fn associated_trait_function() {
838        check_assist_by_label(
839            auto_import,
840            r"
841            mod test_mod {
842                pub trait TestTrait {
843                    fn test_function();
844                }
845                pub struct TestStruct {}
846                impl TestTrait for TestStruct {
847                    fn test_function() {}
848                }
849            }
850
851            fn main() {
852                test_mod::TestStruct::test_function$0
853            }
854            ",
855            r"
856            use test_mod::TestTrait;
857
858            mod test_mod {
859                pub trait TestTrait {
860                    fn test_function();
861                }
862                pub struct TestStruct {}
863                impl TestTrait for TestStruct {
864                    fn test_function() {}
865                }
866            }
867
868            fn main() {
869                test_mod::TestStruct::test_function
870            }
871            ",
872            "Import `test_mod::TestTrait`",
873        );
874
875        check_assist_by_label(
876            auto_import,
877            r"
878            mod test_mod {
879                pub trait TestTrait {
880                    fn test_function();
881                }
882                pub struct TestStruct {}
883                impl TestTrait for TestStruct {
884                    fn test_function() {}
885                }
886            }
887
888            fn main() {
889                test_mod::TestStruct::test_function$0
890            }
891            ",
892            r"
893            use test_mod::TestTrait as _;
894
895            mod test_mod {
896                pub trait TestTrait {
897                    fn test_function();
898                }
899                pub struct TestStruct {}
900                impl TestTrait for TestStruct {
901                    fn test_function() {}
902                }
903            }
904
905            fn main() {
906                test_mod::TestStruct::test_function
907            }
908            ",
909            "Import `test_mod::TestTrait as _`",
910        );
911    }
912
913    #[test]
914    fn not_applicable_for_imported_trait_for_function() {
915        check_assist_not_applicable(
916            auto_import,
917            r"
918            mod test_mod {
919                pub trait TestTrait {
920                    fn test_function();
921                }
922                pub trait TestTrait2 {
923                    fn test_function();
924                }
925                pub enum TestEnum {
926                    One,
927                    Two,
928                }
929                impl TestTrait2 for TestEnum {
930                    fn test_function() {}
931                }
932                impl TestTrait for TestEnum {
933                    fn test_function() {}
934                }
935            }
936
937            use test_mod::TestTrait2;
938            fn main() {
939                test_mod::TestEnum::test_function$0;
940            }
941            ",
942        )
943    }
944
945    #[test]
946    fn associated_trait_const() {
947        check_assist_by_label(
948            auto_import,
949            r"
950            mod test_mod {
951                pub trait TestTrait {
952                    const TEST_CONST: u8;
953                }
954                pub struct TestStruct {}
955                impl TestTrait for TestStruct {
956                    const TEST_CONST: u8 = 42;
957                }
958            }
959
960            fn main() {
961                test_mod::TestStruct::TEST_CONST$0
962            }
963            ",
964            r"
965            use test_mod::TestTrait as _;
966
967            mod test_mod {
968                pub trait TestTrait {
969                    const TEST_CONST: u8;
970                }
971                pub struct TestStruct {}
972                impl TestTrait for TestStruct {
973                    const TEST_CONST: u8 = 42;
974                }
975            }
976
977            fn main() {
978                test_mod::TestStruct::TEST_CONST
979            }
980            ",
981            "Import `test_mod::TestTrait as _`",
982        );
983
984        check_assist_by_label(
985            auto_import,
986            r"
987            mod test_mod {
988                pub trait TestTrait {
989                    const TEST_CONST: u8;
990                }
991                pub struct TestStruct {}
992                impl TestTrait for TestStruct {
993                    const TEST_CONST: u8 = 42;
994                }
995            }
996
997            fn main() {
998                test_mod::TestStruct::TEST_CONST$0
999            }
1000            ",
1001            r"
1002            use test_mod::TestTrait;
1003
1004            mod test_mod {
1005                pub trait TestTrait {
1006                    const TEST_CONST: u8;
1007                }
1008                pub struct TestStruct {}
1009                impl TestTrait for TestStruct {
1010                    const TEST_CONST: u8 = 42;
1011                }
1012            }
1013
1014            fn main() {
1015                test_mod::TestStruct::TEST_CONST
1016            }
1017            ",
1018            "Import `test_mod::TestTrait`",
1019        );
1020    }
1021
1022    #[test]
1023    fn not_applicable_for_imported_trait_for_const() {
1024        check_assist_not_applicable(
1025            auto_import,
1026            r"
1027            mod test_mod {
1028                pub trait TestTrait {
1029                    const TEST_CONST: u8;
1030                }
1031                pub trait TestTrait2 {
1032                    const TEST_CONST: f64;
1033                }
1034                pub enum TestEnum {
1035                    One,
1036                    Two,
1037                }
1038                impl TestTrait2 for TestEnum {
1039                    const TEST_CONST: f64 = 42.0;
1040                }
1041                impl TestTrait for TestEnum {
1042                    const TEST_CONST: u8 = 42;
1043                }
1044            }
1045
1046            use test_mod::TestTrait2;
1047            fn main() {
1048                test_mod::TestEnum::TEST_CONST$0;
1049            }
1050            ",
1051        )
1052    }
1053
1054    #[test]
1055    fn trait_method() {
1056        check_assist_by_label(
1057            auto_import,
1058            r"
1059            mod test_mod {
1060                pub trait TestTrait {
1061                    fn test_method(&self);
1062                }
1063                pub struct TestStruct {}
1064                impl TestTrait for TestStruct {
1065                    fn test_method(&self) {}
1066                }
1067            }
1068
1069            fn main() {
1070                let test_struct = test_mod::TestStruct {};
1071                test_struct.test_meth$0od()
1072            }
1073            ",
1074            r"
1075            use test_mod::TestTrait as _;
1076
1077            mod test_mod {
1078                pub trait TestTrait {
1079                    fn test_method(&self);
1080                }
1081                pub struct TestStruct {}
1082                impl TestTrait for TestStruct {
1083                    fn test_method(&self) {}
1084                }
1085            }
1086
1087            fn main() {
1088                let test_struct = test_mod::TestStruct {};
1089                test_struct.test_method()
1090            }
1091            ",
1092            "Import `test_mod::TestTrait as _`",
1093        );
1094
1095        check_assist_by_label(
1096            auto_import,
1097            r"
1098            mod test_mod {
1099                pub trait TestTrait {
1100                    fn test_method(&self);
1101                }
1102                pub struct TestStruct {}
1103                impl TestTrait for TestStruct {
1104                    fn test_method(&self) {}
1105                }
1106            }
1107
1108            fn main() {
1109                let test_struct = test_mod::TestStruct {};
1110                test_struct.test_meth$0od()
1111            }
1112            ",
1113            r"
1114            use test_mod::TestTrait;
1115
1116            mod test_mod {
1117                pub trait TestTrait {
1118                    fn test_method(&self);
1119                }
1120                pub struct TestStruct {}
1121                impl TestTrait for TestStruct {
1122                    fn test_method(&self) {}
1123                }
1124            }
1125
1126            fn main() {
1127                let test_struct = test_mod::TestStruct {};
1128                test_struct.test_method()
1129            }
1130            ",
1131            "Import `test_mod::TestTrait`",
1132        );
1133    }
1134
1135    #[test]
1136    fn trait_method_cross_crate() {
1137        check_assist_by_label(
1138            auto_import,
1139            r"
1140            //- /main.rs crate:main deps:dep
1141            fn main() {
1142                let test_struct = dep::test_mod::TestStruct {};
1143                test_struct.test_meth$0od()
1144            }
1145            //- /dep.rs crate:dep
1146            pub mod test_mod {
1147                pub trait TestTrait {
1148                    fn test_method(&self);
1149                }
1150                pub struct TestStruct {}
1151                impl TestTrait for TestStruct {
1152                    fn test_method(&self) {}
1153                }
1154            }
1155            ",
1156            r"
1157            use dep::test_mod::TestTrait as _;
1158
1159            fn main() {
1160                let test_struct = dep::test_mod::TestStruct {};
1161                test_struct.test_method()
1162            }
1163            ",
1164            "Import `dep::test_mod::TestTrait as _`",
1165        );
1166
1167        check_assist_by_label(
1168            auto_import,
1169            r"
1170            //- /main.rs crate:main deps:dep
1171            fn main() {
1172                let test_struct = dep::test_mod::TestStruct {};
1173                test_struct.test_meth$0od()
1174            }
1175            //- /dep.rs crate:dep
1176            pub mod test_mod {
1177                pub trait TestTrait {
1178                    fn test_method(&self);
1179                }
1180                pub struct TestStruct {}
1181                impl TestTrait for TestStruct {
1182                    fn test_method(&self) {}
1183                }
1184            }
1185            ",
1186            r"
1187            use dep::test_mod::TestTrait;
1188
1189            fn main() {
1190                let test_struct = dep::test_mod::TestStruct {};
1191                test_struct.test_method()
1192            }
1193            ",
1194            "Import `dep::test_mod::TestTrait`",
1195        );
1196    }
1197
1198    #[test]
1199    fn assoc_fn_cross_crate() {
1200        check_assist_by_label(
1201            auto_import,
1202            r"
1203            //- /main.rs crate:main deps:dep
1204            fn main() {
1205                dep::test_mod::TestStruct::test_func$0tion
1206            }
1207            //- /dep.rs crate:dep
1208            pub mod test_mod {
1209                pub trait TestTrait {
1210                    fn test_function();
1211                }
1212                pub struct TestStruct {}
1213                impl TestTrait for TestStruct {
1214                    fn test_function() {}
1215                }
1216            }
1217            ",
1218            r"
1219            use dep::test_mod::TestTrait as _;
1220
1221            fn main() {
1222                dep::test_mod::TestStruct::test_function
1223            }
1224            ",
1225            "Import `dep::test_mod::TestTrait as _`",
1226        );
1227
1228        check_assist_by_label(
1229            auto_import,
1230            r"
1231            //- /main.rs crate:main deps:dep
1232            fn main() {
1233                dep::test_mod::TestStruct::test_func$0tion
1234            }
1235            //- /dep.rs crate:dep
1236            pub mod test_mod {
1237                pub trait TestTrait {
1238                    fn test_function();
1239                }
1240                pub struct TestStruct {}
1241                impl TestTrait for TestStruct {
1242                    fn test_function() {}
1243                }
1244            }
1245            ",
1246            r"
1247            use dep::test_mod::TestTrait;
1248
1249            fn main() {
1250                dep::test_mod::TestStruct::test_function
1251            }
1252            ",
1253            "Import `dep::test_mod::TestTrait`",
1254        );
1255    }
1256
1257    #[test]
1258    fn assoc_const_cross_crate() {
1259        check_assist_by_label(
1260            auto_import,
1261            r"
1262            //- /main.rs crate:main deps:dep
1263            fn main() {
1264                dep::test_mod::TestStruct::CONST$0
1265            }
1266            //- /dep.rs crate:dep
1267            pub mod test_mod {
1268                pub trait TestTrait {
1269                    const CONST: bool;
1270                }
1271                pub struct TestStruct {}
1272                impl TestTrait for TestStruct {
1273                    const CONST: bool = true;
1274                }
1275            }
1276            ",
1277            r"
1278            use dep::test_mod::TestTrait as _;
1279
1280            fn main() {
1281                dep::test_mod::TestStruct::CONST
1282            }
1283            ",
1284            "Import `dep::test_mod::TestTrait as _`",
1285        );
1286
1287        check_assist_by_label(
1288            auto_import,
1289            r"
1290            //- /main.rs crate:main deps:dep
1291            fn main() {
1292                dep::test_mod::TestStruct::CONST$0
1293            }
1294            //- /dep.rs crate:dep
1295            pub mod test_mod {
1296                pub trait TestTrait {
1297                    const CONST: bool;
1298                }
1299                pub struct TestStruct {}
1300                impl TestTrait for TestStruct {
1301                    const CONST: bool = true;
1302                }
1303            }
1304            ",
1305            r"
1306            use dep::test_mod::TestTrait;
1307
1308            fn main() {
1309                dep::test_mod::TestStruct::CONST
1310            }
1311            ",
1312            "Import `dep::test_mod::TestTrait`",
1313        );
1314    }
1315
1316    #[test]
1317    fn assoc_fn_as_method_cross_crate() {
1318        check_assist_not_applicable(
1319            auto_import,
1320            r"
1321            //- /main.rs crate:main deps:dep
1322            fn main() {
1323                let test_struct = dep::test_mod::TestStruct {};
1324                test_struct.test_func$0tion()
1325            }
1326            //- /dep.rs crate:dep
1327            pub mod test_mod {
1328                pub trait TestTrait {
1329                    fn test_function();
1330                }
1331                pub struct TestStruct {}
1332                impl TestTrait for TestStruct {
1333                    fn test_function() {}
1334                }
1335            }
1336            ",
1337        );
1338    }
1339
1340    #[test]
1341    fn private_trait_cross_crate() {
1342        check_assist_not_applicable(
1343            auto_import,
1344            r"
1345            //- /main.rs crate:main deps:dep
1346            fn main() {
1347                let test_struct = dep::test_mod::TestStruct {};
1348                test_struct.test_meth$0od()
1349            }
1350            //- /dep.rs crate:dep
1351            pub mod test_mod {
1352                trait TestTrait {
1353                    fn test_method(&self);
1354                }
1355                pub struct TestStruct {}
1356                impl TestTrait for TestStruct {
1357                    fn test_method(&self) {}
1358                }
1359            }
1360            ",
1361        );
1362    }
1363
1364    #[test]
1365    fn not_applicable_for_imported_trait_for_method() {
1366        check_assist_not_applicable(
1367            auto_import,
1368            r"
1369            mod test_mod {
1370                pub trait TestTrait {
1371                    fn test_method(&self);
1372                }
1373                pub trait TestTrait2 {
1374                    fn test_method(&self);
1375                }
1376                pub enum TestEnum {
1377                    One,
1378                    Two,
1379                }
1380                impl TestTrait2 for TestEnum {
1381                    fn test_method(&self) {}
1382                }
1383                impl TestTrait for TestEnum {
1384                    fn test_method(&self) {}
1385                }
1386            }
1387
1388            use test_mod::TestTrait2;
1389            fn main() {
1390                let one = test_mod::TestEnum::One;
1391                one.test$0_method();
1392            }
1393            ",
1394        )
1395    }
1396
1397    #[test]
1398    fn dep_import() {
1399        check_assist(
1400            auto_import,
1401            r"
1402//- /lib.rs crate:dep
1403pub struct Struct;
1404
1405//- /main.rs crate:main deps:dep
1406fn main() {
1407    Struct$0
1408}
1409",
1410            r"use dep::Struct;
1411
1412fn main() {
1413    Struct
1414}
1415",
1416        );
1417    }
1418
1419    #[test]
1420    fn whole_segment() {
1421        // Tests that only imports whose last segment matches the identifier get suggested.
1422        check_assist(
1423            auto_import,
1424            r"
1425//- /lib.rs crate:dep
1426pub mod fmt {
1427    pub trait Display {}
1428}
1429
1430pub fn panic_fmt() {}
1431
1432//- /main.rs crate:main deps:dep
1433struct S;
1434
1435impl f$0mt::Display for S {}
1436",
1437            r"use dep::fmt;
1438
1439struct S;
1440
1441impl fmt::Display for S {}
1442",
1443        );
1444    }
1445
1446    #[test]
1447    fn macro_generated() {
1448        // Tests that macro-generated items are suggested from external crates.
1449        check_assist(
1450            auto_import,
1451            r"
1452//- /lib.rs crate:dep
1453macro_rules! mac {
1454    () => {
1455        pub struct Cheese;
1456    };
1457}
1458
1459mac!();
1460
1461//- /main.rs crate:main deps:dep
1462fn main() {
1463    Cheese$0;
1464}
1465",
1466            r"use dep::Cheese;
1467
1468fn main() {
1469    Cheese;
1470}
1471",
1472        );
1473    }
1474
1475    #[test]
1476    fn casing() {
1477        // Tests that differently cased names don't interfere and we only suggest the matching one.
1478        check_assist(
1479            auto_import,
1480            r"
1481//- /lib.rs crate:dep
1482pub struct FMT;
1483pub struct fmt;
1484
1485//- /main.rs crate:main deps:dep
1486fn main() {
1487    FMT$0;
1488}
1489",
1490            r"use dep::FMT;
1491
1492fn main() {
1493    FMT;
1494}
1495",
1496        );
1497    }
1498
1499    #[test]
1500    fn inner_items() {
1501        check_assist(
1502            auto_import,
1503            r#"
1504mod baz {
1505    pub struct Foo {}
1506}
1507
1508mod bar {
1509    fn bar() {
1510        Foo$0;
1511        println!("Hallo");
1512    }
1513}
1514"#,
1515            r#"
1516mod baz {
1517    pub struct Foo {}
1518}
1519
1520mod bar {
1521    use crate::baz::Foo;
1522
1523    fn bar() {
1524        Foo;
1525        println!("Hallo");
1526    }
1527}
1528"#,
1529        );
1530    }
1531
1532    #[test]
1533    fn uses_abs_path_with_extern_crate_clash() {
1534        cov_mark::check!(ambiguous_crate_start);
1535        check_assist(
1536            auto_import,
1537            r#"
1538//- /main.rs crate:main deps:foo
1539mod foo {}
1540
1541const _: () = {
1542    Foo$0
1543};
1544//- /foo.rs crate:foo
1545pub struct Foo
1546"#,
1547            r#"
1548use ::foo::Foo;
1549
1550mod foo {}
1551
1552const _: () = {
1553    Foo
1554};
1555"#,
1556        );
1557    }
1558
1559    #[test]
1560    fn works_on_ident_patterns() {
1561        check_assist(
1562            auto_import,
1563            r#"
1564mod foo {
1565    pub struct Foo {}
1566}
1567fn foo() {
1568    let Foo$0;
1569}
1570"#,
1571            r#"
1572use foo::Foo;
1573
1574mod foo {
1575    pub struct Foo {}
1576}
1577fn foo() {
1578    let Foo;
1579}
1580"#,
1581        );
1582    }
1583
1584    #[test]
1585    fn works_in_derives() {
1586        check_assist(
1587            auto_import,
1588            r#"
1589//- minicore:derive
1590mod foo {
1591    #[rustc_builtin_macro]
1592    pub macro Copy {}
1593}
1594#[derive(Copy$0)]
1595struct Foo;
1596"#,
1597            r#"
1598use foo::Copy;
1599
1600mod foo {
1601    #[rustc_builtin_macro]
1602    pub macro Copy {}
1603}
1604#[derive(Copy)]
1605struct Foo;
1606"#,
1607        );
1608    }
1609
1610    #[test]
1611    fn works_in_use_start() {
1612        check_assist(
1613            auto_import,
1614            r#"
1615mod bar {
1616    pub mod foo {
1617        pub struct Foo;
1618    }
1619}
1620use foo$0::Foo;
1621"#,
1622            r#"
1623mod bar {
1624    pub mod foo {
1625        pub struct Foo;
1626    }
1627}
1628use bar::foo;
1629use foo::Foo;
1630"#,
1631        );
1632    }
1633
1634    #[test]
1635    fn not_applicable_in_non_start_use() {
1636        check_assist_not_applicable(
1637            auto_import,
1638            r"
1639mod bar {
1640    pub mod foo {
1641        pub struct Foo;
1642    }
1643}
1644use foo::Foo$0;
1645",
1646        );
1647    }
1648
1649    #[test]
1650    fn considers_pub_crate() {
1651        check_assist(
1652            auto_import,
1653            r#"
1654mod foo {
1655    pub struct Foo;
1656}
1657
1658pub(crate) use self::foo::*;
1659
1660mod bar {
1661    fn main() {
1662        Foo$0;
1663    }
1664}
1665"#,
1666            r#"
1667mod foo {
1668    pub struct Foo;
1669}
1670
1671pub(crate) use self::foo::*;
1672
1673mod bar {
1674    use crate::Foo;
1675
1676    fn main() {
1677        Foo;
1678    }
1679}
1680"#,
1681        );
1682    }
1683
1684    #[test]
1685    fn local_inline_import_has_alias() {
1686        // FIXME wrong import
1687        check_assist(
1688            auto_import,
1689            r#"
1690struct S<T>(T);
1691use S as IoResult;
1692
1693mod foo {
1694    pub fn bar() -> S$0<()> {}
1695}
1696"#,
1697            r#"
1698struct S<T>(T);
1699use S as IoResult;
1700
1701mod foo {
1702    use crate::S;
1703
1704    pub fn bar() -> S<()> {}
1705}
1706"#,
1707        );
1708    }
1709
1710    #[test]
1711    fn alias_local() {
1712        // FIXME wrong import
1713        check_assist(
1714            auto_import,
1715            r#"
1716struct S<T>(T);
1717use S as IoResult;
1718
1719mod foo {
1720    pub fn bar() -> IoResult$0<()> {}
1721}
1722"#,
1723            r#"
1724struct S<T>(T);
1725use S as IoResult;
1726
1727mod foo {
1728    use crate::S;
1729
1730    pub fn bar() -> IoResult<()> {}
1731}
1732"#,
1733        );
1734    }
1735
1736    #[test]
1737    fn preserve_raw_identifiers_strict() {
1738        check_assist(
1739            auto_import,
1740            r"
1741            r#as$0
1742
1743            pub mod ffi_mod {
1744                pub fn r#as() {};
1745            }
1746            ",
1747            r"
1748            use ffi_mod::r#as;
1749
1750            r#as
1751
1752            pub mod ffi_mod {
1753                pub fn r#as() {};
1754            }
1755            ",
1756        );
1757    }
1758
1759    #[test]
1760    fn preserve_raw_identifiers_reserved() {
1761        check_assist(
1762            auto_import,
1763            r"
1764            r#abstract$0
1765
1766            pub mod ffi_mod {
1767                pub fn r#abstract() {};
1768            }
1769            ",
1770            r"
1771            use ffi_mod::r#abstract;
1772
1773            r#abstract
1774
1775            pub mod ffi_mod {
1776                pub fn r#abstract() {};
1777            }
1778            ",
1779        );
1780    }
1781
1782    #[test]
1783    fn prefers_type_match() {
1784        check_assist(
1785            auto_import,
1786            r"
1787mod sync { pub mod atomic { pub enum Ordering { V } } }
1788mod cmp { pub enum Ordering { V } }
1789fn takes_ordering(_: sync::atomic::Ordering) {}
1790fn main() {
1791    takes_ordering(Ordering$0);
1792}
1793",
1794            r"
1795use sync::atomic::Ordering;
1796
1797mod sync { pub mod atomic { pub enum Ordering { V } } }
1798mod cmp { pub enum Ordering { V } }
1799fn takes_ordering(_: sync::atomic::Ordering) {}
1800fn main() {
1801    takes_ordering(Ordering);
1802}
1803",
1804        );
1805        check_assist(
1806            auto_import,
1807            r"
1808mod sync { pub mod atomic { pub enum Ordering { V } } }
1809mod cmp { pub enum Ordering { V } }
1810fn takes_ordering(_: cmp::Ordering) {}
1811fn main() {
1812    takes_ordering(Ordering$0);
1813}
1814",
1815            r"
1816use cmp::Ordering;
1817
1818mod sync { pub mod atomic { pub enum Ordering { V } } }
1819mod cmp { pub enum Ordering { V } }
1820fn takes_ordering(_: cmp::Ordering) {}
1821fn main() {
1822    takes_ordering(Ordering);
1823}
1824",
1825        );
1826    }
1827
1828    #[test]
1829    fn prefers_type_match2() {
1830        check_assist(
1831            auto_import,
1832            r"
1833mod sync { pub mod atomic { pub enum Ordering { V } } }
1834mod cmp { pub enum Ordering { V } }
1835fn takes_ordering(_: sync::atomic::Ordering) {}
1836fn main() {
1837    takes_ordering(Ordering$0::V);
1838}
1839",
1840            r"
1841use sync::atomic::Ordering;
1842
1843mod sync { pub mod atomic { pub enum Ordering { V } } }
1844mod cmp { pub enum Ordering { V } }
1845fn takes_ordering(_: sync::atomic::Ordering) {}
1846fn main() {
1847    takes_ordering(Ordering::V);
1848}
1849",
1850        );
1851        check_assist(
1852            auto_import,
1853            r"
1854mod sync { pub mod atomic { pub enum Ordering { V } } }
1855mod cmp { pub enum Ordering { V } }
1856fn takes_ordering(_: cmp::Ordering) {}
1857fn main() {
1858    takes_ordering(Ordering$0::V);
1859}
1860",
1861            r"
1862use cmp::Ordering;
1863
1864mod sync { pub mod atomic { pub enum Ordering { V } } }
1865mod cmp { pub enum Ordering { V } }
1866fn takes_ordering(_: cmp::Ordering) {}
1867fn main() {
1868    takes_ordering(Ordering::V);
1869}
1870",
1871        );
1872    }
1873
1874    #[test]
1875    fn carries_cfg_attr() {
1876        check_assist(
1877            auto_import,
1878            r#"
1879mod m {
1880    pub struct S;
1881}
1882
1883#[cfg(test)]
1884fn foo(_: S$0) {}
1885"#,
1886            r#"
1887#[cfg(test)]
1888use m::S;
1889
1890mod m {
1891    pub struct S;
1892}
1893
1894#[cfg(test)]
1895fn foo(_: S) {}
1896"#,
1897        );
1898    }
1899}