diff --git a/crates/assists/src/handlers/auto_import.rs b/crates/assists/src/handlers/auto_import.rs index 0fd2f94fa40..7182a2a5d61 100644 --- a/crates/assists/src/handlers/auto_import.rs +++ b/crates/assists/src/handlers/auto_import.rs @@ -1,3 +1,5 @@ +use syntax::ast; + use crate::{ utils::import_assets::{ImportAssets, ImportCandidate}, utils::{insert_use, mod_path_to_ast, ImportScope}, @@ -24,16 +26,24 @@ use crate::{ // # pub mod std { pub mod collections { pub struct HashMap { } } } // ``` pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { - let auto_import_assets = ImportAssets::new(&ctx)?; - let proposed_imports = auto_import_assets.search_for_imports(&ctx.sema, &ctx.config.insert_use); + let import_assets = + if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::() { + ImportAssets::for_regular_path(path_under_caret, &ctx.sema) + } else if let Some(method_under_caret) = + ctx.find_node_at_offset_with_descend::() + { + ImportAssets::for_method_call(method_under_caret, &ctx.sema) + } else { + None + }?; + let proposed_imports = import_assets.search_for_imports(&ctx.sema, &ctx.config.insert_use); if proposed_imports.is_empty() { return None; } - let range = ctx.sema.original_range(auto_import_assets.syntax_under_caret()).range; - let group = import_group_message(auto_import_assets.import_candidate()); - let scope = - ImportScope::find_insert_use_container(auto_import_assets.syntax_under_caret(), ctx)?; + let range = ctx.sema.original_range(import_assets.syntax_under_caret()).range; + let group = import_group_message(import_assets.import_candidate()); + let scope = ImportScope::find_insert_use_container(import_assets.syntax_under_caret(), ctx)?; let syntax = scope.as_syntax_node(); for import in proposed_imports { acc.add_group( diff --git a/crates/assists/src/utils/import_assets.rs b/crates/assists/src/utils/import_assets.rs index ce5986db71c..b816edc8216 100644 --- a/crates/assists/src/utils/import_assets.rs +++ b/crates/assists/src/utils/import_assets.rs @@ -9,6 +9,23 @@ use syntax::{ast, AstNode, SyntaxNode}; use crate::assist_config::InsertUseConfig; +#[derive(Debug)] +pub(crate) enum ImportCandidate { + /// Simple name like 'HashMap' + UnqualifiedName(String), + /// First part of the qualified name. + /// For 'std::collections::HashMap', that will be 'std'. + QualifierStart(String), + /// A trait associated function (with no self parameter) or associated constant. + /// For 'test_mod::TestEnum::test_function', `Type` is the `test_mod::TestEnum` expression type + /// and `String` is the `test_function` + TraitAssocItem(hir::Type, String), + /// A trait method with self parameter. + /// For 'test_enum.test_method()', `Type` is the `test_enum` expression type + /// and `String` is the `test_method` + TraitMethod(hir::Type, String), +} + #[derive(Debug)] pub(crate) struct ImportAssets { import_candidate: ImportCandidate, @@ -17,23 +34,7 @@ pub(crate) struct ImportAssets { } impl ImportAssets { - pub(crate) fn new(ctx: &crate::assist_context::AssistContext) -> Option { - if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::() { - Self::for_regular_path(path_under_caret, &ctx.sema) - } else { - Self::for_method_call(ctx.find_node_at_offset_with_descend()?, &ctx.sema) - } - } - - pub(crate) fn syntax_under_caret(&self) -> &SyntaxNode { - &self.syntax_under_caret - } - - pub(crate) fn import_candidate(&self) -> &ImportCandidate { - &self.import_candidate - } - - fn for_method_call( + pub(crate) fn for_method_call( method_call: ast::MethodCallExpr, sema: &Semantics, ) -> Option { @@ -46,7 +47,7 @@ impl ImportAssets { }) } - fn for_regular_path( + pub(crate) fn for_regular_path( path_under_caret: ast::Path, sema: &Semantics, ) -> Option { @@ -63,6 +64,14 @@ impl ImportAssets { }) } + pub(crate) fn syntax_under_caret(&self) -> &SyntaxNode { + &self.syntax_under_caret + } + + pub(crate) fn import_candidate(&self) -> &ImportCandidate { + &self.import_candidate + } + fn get_search_query(&self) -> &str { match &self.import_candidate { ImportCandidate::UnqualifiedName(name) => name, @@ -182,25 +191,8 @@ impl ImportAssets { } } -#[derive(Debug)] -pub(crate) enum ImportCandidate { - /// Simple name like 'HashMap' - UnqualifiedName(String), - /// First part of the qualified name. - /// For 'std::collections::HashMap', that will be 'std'. - QualifierStart(String), - /// A trait associated function (with no self parameter) or associated constant. - /// For 'test_mod::TestEnum::test_function', `Type` is the `test_mod::TestEnum` expression type - /// and `String` is the `test_function` - TraitAssocItem(hir::Type, String), - /// A trait method with self parameter. - /// For 'test_enum.test_method()', `Type` is the `test_enum` expression type - /// and `String` is the `test_method` - TraitMethod(hir::Type, String), -} - impl ImportCandidate { - pub(crate) fn for_method_call( + fn for_method_call( sema: &Semantics, method_call: &ast::MethodCallExpr, ) -> Option { @@ -213,7 +205,7 @@ impl ImportCandidate { )) } - pub(crate) fn for_regular_path( + fn for_regular_path( sema: &Semantics, path_under_caret: &ast::Path, ) -> Option {