diff --git a/crates/ra_assists/src/assists/auto_import.rs b/crates/ra_assists/src/assists/auto_import.rs index ae216944b5..d196f6c5c6 100644 --- a/crates/ra_assists/src/assists/auto_import.rs +++ b/crates/ra_assists/src/assists/auto_import.rs @@ -1,4 +1,4 @@ -use hir::db::HirDatabase; +use hir::{db::HirDatabase, AsName}; use ra_syntax::{ ast::{self, AstNode}, SmolStr, SyntaxElement, @@ -41,15 +41,21 @@ pub(crate) fn auto_import( current_file.syntax().clone() } }; + let source_analyzer = ctx.source_analyzer(&position, None); + let module_with_name_to_import = source_analyzer.module()?; + let path_to_import = ctx.covering_element().ancestors().find_map(ast::Path::cast)?; + if source_analyzer.resolve_path(ctx.db, &path_to_import).is_some() { + return None; + } - let module_with_name_to_import = ctx.source_analyzer(&position, None).module()?; - let name_to_import = hir::InFile { - file_id: ctx.frange.file_id.into(), - value: &find_applicable_name_ref(ctx.covering_element())?, - }; - - let proposed_imports = - imports_locator.find_imports(name_to_import, module_with_name_to_import)?; + let name_to_import = &find_applicable_name_ref(ctx.covering_element())?.as_name(); + let proposed_imports = imports_locator + .find_imports(&name_to_import.to_string()) + .into_iter() + .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def)) + .filter(|use_path| !use_path.segments.is_empty()) + .take(20) + .collect::>(); if proposed_imports.is_empty() { return None; } @@ -57,7 +63,7 @@ pub(crate) fn auto_import( ctx.add_assist_group(AssistId("auto_import"), "auto import", || { proposed_imports .into_iter() - .map(|import| import_to_action(import.to_string(), &position, &path)) + .map(|import| import_to_action(import.to_string(), &position, &path_to_import)) .collect() }) } diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 381a51df6e..9e4ebec470 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -14,9 +14,9 @@ mod test_db; pub mod ast_transform; use either::Either; -use hir::{db::HirDatabase, InFile, ModPath, Module}; +use hir::{db::HirDatabase, ModuleDef}; use ra_db::FileRange; -use ra_syntax::{ast::NameRef, TextRange, TextUnit}; +use ra_syntax::{TextRange, TextUnit}; use ra_text_edit::TextEdit; pub(crate) use crate::assist_ctx::{Assist, AssistCtx}; @@ -85,11 +85,7 @@ where /// accessible from the ra_assists crate. pub trait ImportsLocator { /// Finds all imports for the given name and the module that contains this name. - fn find_imports( - &mut self, - name_to_import: InFile<&NameRef>, - module_with_name_to_import: Module, - ) -> Option>; + fn find_imports(&mut self, name_to_import: &str) -> Vec; } /// Return all the assists applicable at the given position diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index be6dced538..21b0553be8 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -58,6 +58,7 @@ pub use hir_def::{ type_ref::Mutability, }; pub use hir_expand::{ - name, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin, + name::{AsName, Name}, + HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin, }; pub use hir_ty::{display::HirDisplay, CallableDef}; diff --git a/crates/ra_ide/src/imports_locator.rs b/crates/ra_ide/src/imports_locator.rs index e69fb40702..b2fc48159d 100644 --- a/crates/ra_ide/src/imports_locator.rs +++ b/crates/ra_ide/src/imports_locator.rs @@ -3,13 +3,11 @@ use crate::{ db::RootDatabase, - references::{classify_name, classify_name_ref, NameDefinition, NameKind}, + references::{classify_name, NameDefinition, NameKind}, symbol_index::{self, FileSymbol}, Query, }; -use ast::NameRef; -use hir::{db::HirDatabase, InFile, ModPath, Module, SourceBinder}; -use itertools::Itertools; +use hir::{db::HirDatabase, ModuleDef, SourceBinder}; use ra_assists::ImportsLocator; use ra_prof::profile; use ra_syntax::{ast, AstNode, SyntaxKind::NAME}; @@ -23,46 +21,6 @@ impl<'a> ImportsLocatorIde<'a> { Self { source_binder: SourceBinder::new(db) } } - fn search_for_imports( - &mut self, - name_to_import: &ast::NameRef, - module_with_name_to_import: Module, - ) -> Vec { - let _p = profile("search_for_imports"); - let db = self.source_binder.db; - let name_to_import = name_to_import.text(); - - let project_results = { - let mut query = Query::new(name_to_import.to_string()); - query.exact(); - query.limit(40); - symbol_index::world_symbols(db, query) - }; - let lib_results = { - let mut query = Query::new(name_to_import.to_string()); - query.libs(); - query.exact(); - query.limit(40); - symbol_index::world_symbols(db, query) - }; - - project_results - .into_iter() - .chain(lib_results.into_iter()) - .filter_map(|import_candidate| self.get_name_definition(db, &import_candidate)) - .filter_map(|name_definition_to_import| { - if let NameKind::Def(module_def) = name_definition_to_import.kind { - module_with_name_to_import.find_use_path(db, module_def) - } else { - None - } - }) - .filter(|use_path| !use_path.segments.is_empty()) - .unique() - .take(20) - .collect() - } - fn get_name_definition( &mut self, db: &impl HirDatabase, @@ -84,15 +42,35 @@ impl<'a> ImportsLocatorIde<'a> { } impl<'a> ImportsLocator for ImportsLocatorIde<'a> { - fn find_imports( - &mut self, - name_to_import: InFile<&NameRef>, - module_with_name_to_import: Module, - ) -> Option> { - if classify_name_ref(&mut self.source_binder, name_to_import).is_none() { - Some(self.search_for_imports(name_to_import.value, module_with_name_to_import)) - } else { - None - } + fn find_imports(&mut self, name_to_import: &str) -> Vec { + let _p = profile("search_for_imports"); + let db = self.source_binder.db; + + let project_results = { + let mut query = Query::new(name_to_import.to_string()); + query.exact(); + query.limit(40); + symbol_index::world_symbols(db, query) + }; + let lib_results = { + let mut query = Query::new(name_to_import.to_string()); + query.libs(); + query.exact(); + query.limit(40); + symbol_index::world_symbols(db, query) + }; + + project_results + .into_iter() + .chain(lib_results.into_iter()) + .filter_map(|import_candidate| self.get_name_definition(db, &import_candidate)) + .filter_map(|name_definition_to_import| { + if let NameKind::Def(module_def) = name_definition_to_import.kind { + Some(module_def) + } else { + None + } + }) + .collect() } }