aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/assists/auto_import.rs26
-rw-r--r--crates/ra_assists/src/lib.rs10
-rw-r--r--crates/ra_hir/src/lib.rs3
-rw-r--r--crates/ra_ide/src/imports_locator.rs70
4 files changed, 45 insertions, 64 deletions
diff --git a/crates/ra_assists/src/assists/auto_import.rs b/crates/ra_assists/src/assists/auto_import.rs
index ae216944b..d196f6c5c 100644
--- a/crates/ra_assists/src/assists/auto_import.rs
+++ b/crates/ra_assists/src/assists/auto_import.rs
@@ -1,4 +1,4 @@
1use hir::db::HirDatabase; 1use hir::{db::HirDatabase, AsName};
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{self, AstNode}, 3 ast::{self, AstNode},
4 SmolStr, SyntaxElement, 4 SmolStr, SyntaxElement,
@@ -41,15 +41,21 @@ pub(crate) fn auto_import<F: ImportsLocator>(
41 current_file.syntax().clone() 41 current_file.syntax().clone()
42 } 42 }
43 }; 43 };
44 let source_analyzer = ctx.source_analyzer(&position, None);
45 let module_with_name_to_import = source_analyzer.module()?;
46 let path_to_import = ctx.covering_element().ancestors().find_map(ast::Path::cast)?;
47 if source_analyzer.resolve_path(ctx.db, &path_to_import).is_some() {
48 return None;
49 }
44 50
45 let module_with_name_to_import = ctx.source_analyzer(&position, None).module()?; 51 let name_to_import = &find_applicable_name_ref(ctx.covering_element())?.as_name();
46 let name_to_import = hir::InFile { 52 let proposed_imports = imports_locator
47 file_id: ctx.frange.file_id.into(), 53 .find_imports(&name_to_import.to_string())
48 value: &find_applicable_name_ref(ctx.covering_element())?, 54 .into_iter()
49 }; 55 .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def))
50 56 .filter(|use_path| !use_path.segments.is_empty())
51 let proposed_imports = 57 .take(20)
52 imports_locator.find_imports(name_to_import, module_with_name_to_import)?; 58 .collect::<std::collections::HashSet<_>>();
53 if proposed_imports.is_empty() { 59 if proposed_imports.is_empty() {
54 return None; 60 return None;
55 } 61 }
@@ -57,7 +63,7 @@ pub(crate) fn auto_import<F: ImportsLocator>(
57 ctx.add_assist_group(AssistId("auto_import"), "auto import", || { 63 ctx.add_assist_group(AssistId("auto_import"), "auto import", || {
58 proposed_imports 64 proposed_imports
59 .into_iter() 65 .into_iter()
60 .map(|import| import_to_action(import.to_string(), &position, &path)) 66 .map(|import| import_to_action(import.to_string(), &position, &path_to_import))
61 .collect() 67 .collect()
62 }) 68 })
63} 69}
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index 381a51df6..9e4ebec47 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -14,9 +14,9 @@ mod test_db;
14pub mod ast_transform; 14pub mod ast_transform;
15 15
16use either::Either; 16use either::Either;
17use hir::{db::HirDatabase, InFile, ModPath, Module}; 17use hir::{db::HirDatabase, ModuleDef};
18use ra_db::FileRange; 18use ra_db::FileRange;
19use ra_syntax::{ast::NameRef, TextRange, TextUnit}; 19use ra_syntax::{TextRange, TextUnit};
20use ra_text_edit::TextEdit; 20use ra_text_edit::TextEdit;
21 21
22pub(crate) use crate::assist_ctx::{Assist, AssistCtx}; 22pub(crate) use crate::assist_ctx::{Assist, AssistCtx};
@@ -85,11 +85,7 @@ where
85/// accessible from the ra_assists crate. 85/// accessible from the ra_assists crate.
86pub trait ImportsLocator { 86pub trait ImportsLocator {
87 /// Finds all imports for the given name and the module that contains this name. 87 /// Finds all imports for the given name and the module that contains this name.
88 fn find_imports( 88 fn find_imports(&mut self, name_to_import: &str) -> Vec<ModuleDef>;
89 &mut self,
90 name_to_import: InFile<&NameRef>,
91 module_with_name_to_import: Module,
92 ) -> Option<Vec<ModPath>>;
93} 89}
94 90
95/// Return all the assists applicable at the given position 91/// 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 be6dced53..21b0553be 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -58,6 +58,7 @@ pub use hir_def::{
58 type_ref::Mutability, 58 type_ref::Mutability,
59}; 59};
60pub use hir_expand::{ 60pub use hir_expand::{
61 name, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin, 61 name::{AsName, Name},
62 HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin,
62}; 63};
63pub use hir_ty::{display::HirDisplay, CallableDef}; 64pub 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 e69fb4070..b2fc48159 100644
--- a/crates/ra_ide/src/imports_locator.rs
+++ b/crates/ra_ide/src/imports_locator.rs
@@ -3,13 +3,11 @@
3 3
4use crate::{ 4use crate::{
5 db::RootDatabase, 5 db::RootDatabase,
6 references::{classify_name, classify_name_ref, NameDefinition, NameKind}, 6 references::{classify_name, NameDefinition, NameKind},
7 symbol_index::{self, FileSymbol}, 7 symbol_index::{self, FileSymbol},
8 Query, 8 Query,
9}; 9};
10use ast::NameRef; 10use hir::{db::HirDatabase, ModuleDef, SourceBinder};
11use hir::{db::HirDatabase, InFile, ModPath, Module, SourceBinder};
12use itertools::Itertools;
13use ra_assists::ImportsLocator; 11use ra_assists::ImportsLocator;
14use ra_prof::profile; 12use ra_prof::profile;
15use ra_syntax::{ast, AstNode, SyntaxKind::NAME}; 13use ra_syntax::{ast, AstNode, SyntaxKind::NAME};
@@ -23,14 +21,30 @@ impl<'a> ImportsLocatorIde<'a> {
23 Self { source_binder: SourceBinder::new(db) } 21 Self { source_binder: SourceBinder::new(db) }
24 } 22 }
25 23
26 fn search_for_imports( 24 fn get_name_definition(
27 &mut self, 25 &mut self,
28 name_to_import: &ast::NameRef, 26 db: &impl HirDatabase,
29 module_with_name_to_import: Module, 27 import_candidate: &FileSymbol,
30 ) -> Vec<ModPath> { 28 ) -> Option<NameDefinition> {
29 let _p = profile("get_name_definition");
30 let file_id = import_candidate.file_id.into();
31 let candidate_node = import_candidate.ptr.to_node(&db.parse_or_expand(file_id)?);
32 let candidate_name_node = if candidate_node.kind() != NAME {
33 candidate_node.children().find(|it| it.kind() == NAME)?
34 } else {
35 candidate_node
36 };
37 classify_name(
38 &mut self.source_binder,
39 hir::InFile { file_id, value: &ast::Name::cast(candidate_name_node)? },
40 )
41 }
42}
43
44impl<'a> ImportsLocator for ImportsLocatorIde<'a> {
45 fn find_imports(&mut self, name_to_import: &str) -> Vec<ModuleDef> {
31 let _p = profile("search_for_imports"); 46 let _p = profile("search_for_imports");
32 let db = self.source_binder.db; 47 let db = self.source_binder.db;
33 let name_to_import = name_to_import.text();
34 48
35 let project_results = { 49 let project_results = {
36 let mut query = Query::new(name_to_import.to_string()); 50 let mut query = Query::new(name_to_import.to_string());
@@ -52,47 +66,11 @@ impl<'a> ImportsLocatorIde<'a> {
52 .filter_map(|import_candidate| self.get_name_definition(db, &import_candidate)) 66 .filter_map(|import_candidate| self.get_name_definition(db, &import_candidate))
53 .filter_map(|name_definition_to_import| { 67 .filter_map(|name_definition_to_import| {
54 if let NameKind::Def(module_def) = name_definition_to_import.kind { 68 if let NameKind::Def(module_def) = name_definition_to_import.kind {
55 module_with_name_to_import.find_use_path(db, module_def) 69 Some(module_def)
56 } else { 70 } else {
57 None 71 None
58 } 72 }
59 }) 73 })
60 .filter(|use_path| !use_path.segments.is_empty())
61 .unique()
62 .take(20)
63 .collect() 74 .collect()
64 } 75 }
65
66 fn get_name_definition(
67 &mut self,
68 db: &impl HirDatabase,
69 import_candidate: &FileSymbol,
70 ) -> Option<NameDefinition> {
71 let _p = profile("get_name_definition");
72 let file_id = import_candidate.file_id.into();
73 let candidate_node = import_candidate.ptr.to_node(&db.parse_or_expand(file_id)?);
74 let candidate_name_node = if candidate_node.kind() != NAME {
75 candidate_node.children().find(|it| it.kind() == NAME)?
76 } else {
77 candidate_node
78 };
79 classify_name(
80 &mut self.source_binder,
81 hir::InFile { file_id, value: &ast::Name::cast(candidate_name_node)? },
82 )
83 }
84}
85
86impl<'a> ImportsLocator for ImportsLocatorIde<'a> {
87 fn find_imports(
88 &mut self,
89 name_to_import: InFile<&NameRef>,
90 module_with_name_to_import: Module,
91 ) -> Option<Vec<ModPath>> {
92 if classify_name_ref(&mut self.source_binder, name_to_import).is_none() {
93 Some(self.search_for_imports(name_to_import.value, module_with_name_to_import))
94 } else {
95 None
96 }
97 }
98} 76}