From 316795e074dff8f627f8c70c85d236420ecfb3a6 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 24 Dec 2019 02:19:09 +0200 Subject: Initial auto import action implementation --- crates/ra_ide/src/assists.rs | 7 +-- crates/ra_ide/src/imports_locator.rs | 97 ++++++++++++++++++++++++++++++++++++ crates/ra_ide/src/lib.rs | 1 + 3 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 crates/ra_ide/src/imports_locator.rs (limited to 'crates/ra_ide/src') diff --git a/crates/ra_ide/src/assists.rs b/crates/ra_ide/src/assists.rs index a936900da..c43c45c65 100644 --- a/crates/ra_ide/src/assists.rs +++ b/crates/ra_ide/src/assists.rs @@ -2,8 +2,9 @@ use ra_db::{FilePosition, FileRange}; -use crate::{db::RootDatabase, FileId, SourceChange, SourceFileEdit}; - +use crate::{ + db::RootDatabase, imports_locator::ImportsLocatorIde, FileId, SourceChange, SourceFileEdit, +}; use either::Either; pub use ra_assists::AssistId; use ra_assists::{AssistAction, AssistLabel}; @@ -16,7 +17,7 @@ pub struct Assist { } pub(crate) fn assists(db: &RootDatabase, frange: FileRange) -> Vec { - ra_assists::assists(db, frange) + ra_assists::assists_with_imports_locator(db, frange, ImportsLocatorIde::new(db)) .into_iter() .map(|assist| { let file_id = frange.file_id; diff --git a/crates/ra_ide/src/imports_locator.rs b/crates/ra_ide/src/imports_locator.rs new file mode 100644 index 000000000..23391ac3b --- /dev/null +++ b/crates/ra_ide/src/imports_locator.rs @@ -0,0 +1,97 @@ +//! This module contains an import search funcionality that is provided to the ra_assists module. +//! Later, this should be moved away to a separate crate that is accessible from the ra_assists module. + +use crate::{ + db::RootDatabase, + references::{classify_name, classify_name_ref, NameDefinition, NameKind}, + symbol_index::{self, FileSymbol}, + Query, +}; +use ast::NameRef; +use hir::{db::HirDatabase, InFile, ModPath, Module, SourceBinder}; +use itertools::Itertools; +use ra_assists::ImportsLocator; +use ra_prof::profile; +use ra_syntax::{ast, AstNode, SyntaxKind::NAME}; + +pub(crate) struct ImportsLocatorIde<'a> { + source_binder: SourceBinder<'a, RootDatabase>, +} + +impl<'a> ImportsLocatorIde<'a> { + pub(crate) fn new(db: &'a RootDatabase) -> Self { + 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(10); + 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(10); + 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() + .collect() + } + + fn get_name_definition( + &mut self, + db: &impl HirDatabase, + import_candidate: &FileSymbol, + ) -> Option { + let _p = profile("get_name_definition"); + let file_id = import_candidate.file_id.into(); + let candidate_node = import_candidate.ptr.to_node(&db.parse_or_expand(file_id)?); + let candidate_name_node = if candidate_node.kind() != NAME { + candidate_node.children().find(|it| it.kind() == NAME)? + } else { + candidate_node + }; + classify_name( + &mut self.source_binder, + hir::InFile { file_id, value: &ast::Name::cast(candidate_name_node)? }, + ) + } +} + +impl<'a> ImportsLocator<'a> 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 + } + } +} diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 62fe6d2a9..03ad6b2c1 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -30,6 +30,7 @@ mod syntax_highlighting; mod parent_module; mod references; mod impls; +mod imports_locator; mod assists; mod diagnostics; mod syntax_tree; -- cgit v1.2.3 From f57239729cb9d6f60eb09d8cfd8244066b5e182c Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 23 Jan 2020 21:15:16 +0200 Subject: Remove unnecessary lifetime parameter --- crates/ra_ide/src/imports_locator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_ide/src') diff --git a/crates/ra_ide/src/imports_locator.rs b/crates/ra_ide/src/imports_locator.rs index 23391ac3b..ab9cd7990 100644 --- a/crates/ra_ide/src/imports_locator.rs +++ b/crates/ra_ide/src/imports_locator.rs @@ -82,7 +82,7 @@ impl<'a> ImportsLocatorIde<'a> { } } -impl<'a> ImportsLocator<'a> for ImportsLocatorIde<'a> { +impl<'a> ImportsLocator for ImportsLocatorIde<'a> { fn find_imports( &mut self, name_to_import: InFile<&NameRef>, -- cgit v1.2.3 From bef5cf0b9929539e8d9fece006bfd3db1b68bec4 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 23 Jan 2020 21:30:59 +0200 Subject: Raise the import search query cap --- crates/ra_ide/src/imports_locator.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'crates/ra_ide/src') diff --git a/crates/ra_ide/src/imports_locator.rs b/crates/ra_ide/src/imports_locator.rs index ab9cd7990..e69fb4070 100644 --- a/crates/ra_ide/src/imports_locator.rs +++ b/crates/ra_ide/src/imports_locator.rs @@ -35,14 +35,14 @@ impl<'a> ImportsLocatorIde<'a> { let project_results = { let mut query = Query::new(name_to_import.to_string()); query.exact(); - query.limit(10); + 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(10); + query.limit(40); symbol_index::world_symbols(db, query) }; @@ -59,6 +59,7 @@ impl<'a> ImportsLocatorIde<'a> { }) .filter(|use_path| !use_path.segments.is_empty()) .unique() + .take(20) .collect() } -- cgit v1.2.3 From d0a782ef1c53ef5c5d3b49b02c498f7a688c3a4d Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 24 Jan 2020 09:33:18 +0200 Subject: Have a better trait interface --- crates/ra_ide/src/imports_locator.rs | 70 +++++++++++++----------------------- 1 file changed, 24 insertions(+), 46 deletions(-) (limited to 'crates/ra_ide/src') diff --git a/crates/ra_ide/src/imports_locator.rs b/crates/ra_ide/src/imports_locator.rs index e69fb4070..b2fc48159 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,14 +21,30 @@ impl<'a> ImportsLocatorIde<'a> { Self { source_binder: SourceBinder::new(db) } } - fn search_for_imports( + fn get_name_definition( &mut self, - name_to_import: &ast::NameRef, - module_with_name_to_import: Module, - ) -> Vec { + db: &impl HirDatabase, + import_candidate: &FileSymbol, + ) -> Option { + let _p = profile("get_name_definition"); + let file_id = import_candidate.file_id.into(); + let candidate_node = import_candidate.ptr.to_node(&db.parse_or_expand(file_id)?); + let candidate_name_node = if candidate_node.kind() != NAME { + candidate_node.children().find(|it| it.kind() == NAME)? + } else { + candidate_node + }; + classify_name( + &mut self.source_binder, + hir::InFile { file_id, value: &ast::Name::cast(candidate_name_node)? }, + ) + } +} + +impl<'a> ImportsLocator for ImportsLocatorIde<'a> { + fn find_imports(&mut self, name_to_import: &str) -> 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()); @@ -52,47 +66,11 @@ impl<'a> ImportsLocatorIde<'a> { .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) + Some(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, - import_candidate: &FileSymbol, - ) -> Option { - let _p = profile("get_name_definition"); - let file_id = import_candidate.file_id.into(); - let candidate_node = import_candidate.ptr.to_node(&db.parse_or_expand(file_id)?); - let candidate_name_node = if candidate_node.kind() != NAME { - candidate_node.children().find(|it| it.kind() == NAME)? - } else { - candidate_node - }; - classify_name( - &mut self.source_binder, - hir::InFile { file_id, value: &ast::Name::cast(candidate_name_node)? }, - ) - } -} - -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 - } - } } -- cgit v1.2.3 From 9be1ab7ff948d89334a8acbc309c8235d4ab374f Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 27 Jan 2020 14:42:45 +0200 Subject: Code review fixes --- crates/ra_ide/src/imports_locator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_ide/src') diff --git a/crates/ra_ide/src/imports_locator.rs b/crates/ra_ide/src/imports_locator.rs index b2fc48159..48b014c7d 100644 --- a/crates/ra_ide/src/imports_locator.rs +++ b/crates/ra_ide/src/imports_locator.rs @@ -41,7 +41,7 @@ impl<'a> ImportsLocatorIde<'a> { } } -impl<'a> ImportsLocator for ImportsLocatorIde<'a> { +impl ImportsLocator for ImportsLocatorIde<'_> { fn find_imports(&mut self, name_to_import: &str) -> Vec { let _p = profile("search_for_imports"); let db = self.source_binder.db; -- cgit v1.2.3