Skip to main content

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