diff options
-rw-r--r-- | crates/ra_assists/src/assists/auto_import.rs | 26 | ||||
-rw-r--r-- | crates/ra_assists/src/lib.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 3 | ||||
-rw-r--r-- | crates/ra_ide/src/imports_locator.rs | 70 |
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 @@ | |||
1 | use hir::db::HirDatabase; | 1 | use hir::{db::HirDatabase, AsName}; |
2 | use ra_syntax::{ | 2 | use 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; | |||
14 | pub mod ast_transform; | 14 | pub mod ast_transform; |
15 | 15 | ||
16 | use either::Either; | 16 | use either::Either; |
17 | use hir::{db::HirDatabase, InFile, ModPath, Module}; | 17 | use hir::{db::HirDatabase, ModuleDef}; |
18 | use ra_db::FileRange; | 18 | use ra_db::FileRange; |
19 | use ra_syntax::{ast::NameRef, TextRange, TextUnit}; | 19 | use ra_syntax::{TextRange, TextUnit}; |
20 | use ra_text_edit::TextEdit; | 20 | use ra_text_edit::TextEdit; |
21 | 21 | ||
22 | pub(crate) use crate::assist_ctx::{Assist, AssistCtx}; | 22 | pub(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. |
86 | pub trait ImportsLocator { | 86 | pub 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 | }; |
60 | pub use hir_expand::{ | 60 | pub 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 | }; |
63 | pub use hir_ty::{display::HirDisplay, CallableDef}; | 64 | 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 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 | ||
4 | use crate::{ | 4 | use 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 | }; |
10 | use ast::NameRef; | 10 | use hir::{db::HirDatabase, ModuleDef, SourceBinder}; |
11 | use hir::{db::HirDatabase, InFile, ModPath, Module, SourceBinder}; | ||
12 | use itertools::Itertools; | ||
13 | use ra_assists::ImportsLocator; | 11 | use ra_assists::ImportsLocator; |
14 | use ra_prof::profile; | 12 | use ra_prof::profile; |
15 | use ra_syntax::{ast, AstNode, SyntaxKind::NAME}; | 13 | use 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 | |||
44 | impl<'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 | |||
86 | impl<'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 | } |