diff options
-rw-r--r-- | crates/assists/src/handlers/auto_import.rs | 22 | ||||
-rw-r--r-- | crates/assists/src/utils/import_assets.rs | 66 |
2 files changed, 45 insertions, 43 deletions
diff --git a/crates/assists/src/handlers/auto_import.rs b/crates/assists/src/handlers/auto_import.rs index 0fd2f94fa..7182a2a5d 100644 --- a/crates/assists/src/handlers/auto_import.rs +++ b/crates/assists/src/handlers/auto_import.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | use syntax::ast; | ||
2 | |||
1 | use crate::{ | 3 | use crate::{ |
2 | utils::import_assets::{ImportAssets, ImportCandidate}, | 4 | utils::import_assets::{ImportAssets, ImportCandidate}, |
3 | utils::{insert_use, mod_path_to_ast, ImportScope}, | 5 | utils::{insert_use, mod_path_to_ast, ImportScope}, |
@@ -24,16 +26,24 @@ use crate::{ | |||
24 | // # pub mod std { pub mod collections { pub struct HashMap { } } } | 26 | // # pub mod std { pub mod collections { pub struct HashMap { } } } |
25 | // ``` | 27 | // ``` |
26 | pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 28 | pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
27 | let auto_import_assets = ImportAssets::new(&ctx)?; | 29 | let import_assets = |
28 | let proposed_imports = auto_import_assets.search_for_imports(&ctx.sema, &ctx.config.insert_use); | 30 | if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::<ast::Path>() { |
31 | ImportAssets::for_regular_path(path_under_caret, &ctx.sema) | ||
32 | } else if let Some(method_under_caret) = | ||
33 | ctx.find_node_at_offset_with_descend::<ast::MethodCallExpr>() | ||
34 | { | ||
35 | ImportAssets::for_method_call(method_under_caret, &ctx.sema) | ||
36 | } else { | ||
37 | None | ||
38 | }?; | ||
39 | let proposed_imports = import_assets.search_for_imports(&ctx.sema, &ctx.config.insert_use); | ||
29 | if proposed_imports.is_empty() { | 40 | if proposed_imports.is_empty() { |
30 | return None; | 41 | return None; |
31 | } | 42 | } |
32 | 43 | ||
33 | let range = ctx.sema.original_range(auto_import_assets.syntax_under_caret()).range; | 44 | let range = ctx.sema.original_range(import_assets.syntax_under_caret()).range; |
34 | let group = import_group_message(auto_import_assets.import_candidate()); | 45 | let group = import_group_message(import_assets.import_candidate()); |
35 | let scope = | 46 | let scope = ImportScope::find_insert_use_container(import_assets.syntax_under_caret(), ctx)?; |
36 | ImportScope::find_insert_use_container(auto_import_assets.syntax_under_caret(), ctx)?; | ||
37 | let syntax = scope.as_syntax_node(); | 47 | let syntax = scope.as_syntax_node(); |
38 | for import in proposed_imports { | 48 | for import in proposed_imports { |
39 | acc.add_group( | 49 | acc.add_group( |
diff --git a/crates/assists/src/utils/import_assets.rs b/crates/assists/src/utils/import_assets.rs index ce5986db7..b816edc82 100644 --- a/crates/assists/src/utils/import_assets.rs +++ b/crates/assists/src/utils/import_assets.rs | |||
@@ -10,6 +10,23 @@ use syntax::{ast, AstNode, SyntaxNode}; | |||
10 | use crate::assist_config::InsertUseConfig; | 10 | use crate::assist_config::InsertUseConfig; |
11 | 11 | ||
12 | #[derive(Debug)] | 12 | #[derive(Debug)] |
13 | pub(crate) enum ImportCandidate { | ||
14 | /// Simple name like 'HashMap' | ||
15 | UnqualifiedName(String), | ||
16 | /// First part of the qualified name. | ||
17 | /// For 'std::collections::HashMap', that will be 'std'. | ||
18 | QualifierStart(String), | ||
19 | /// A trait associated function (with no self parameter) or associated constant. | ||
20 | /// For 'test_mod::TestEnum::test_function', `Type` is the `test_mod::TestEnum` expression type | ||
21 | /// and `String` is the `test_function` | ||
22 | TraitAssocItem(hir::Type, String), | ||
23 | /// A trait method with self parameter. | ||
24 | /// For 'test_enum.test_method()', `Type` is the `test_enum` expression type | ||
25 | /// and `String` is the `test_method` | ||
26 | TraitMethod(hir::Type, String), | ||
27 | } | ||
28 | |||
29 | #[derive(Debug)] | ||
13 | pub(crate) struct ImportAssets { | 30 | pub(crate) struct ImportAssets { |
14 | import_candidate: ImportCandidate, | 31 | import_candidate: ImportCandidate, |
15 | module_with_name_to_import: hir::Module, | 32 | module_with_name_to_import: hir::Module, |
@@ -17,23 +34,7 @@ pub(crate) struct ImportAssets { | |||
17 | } | 34 | } |
18 | 35 | ||
19 | impl ImportAssets { | 36 | impl ImportAssets { |
20 | pub(crate) fn new(ctx: &crate::assist_context::AssistContext) -> Option<Self> { | 37 | pub(crate) fn for_method_call( |
21 | if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::<ast::Path>() { | ||
22 | Self::for_regular_path(path_under_caret, &ctx.sema) | ||
23 | } else { | ||
24 | Self::for_method_call(ctx.find_node_at_offset_with_descend()?, &ctx.sema) | ||
25 | } | ||
26 | } | ||
27 | |||
28 | pub(crate) fn syntax_under_caret(&self) -> &SyntaxNode { | ||
29 | &self.syntax_under_caret | ||
30 | } | ||
31 | |||
32 | pub(crate) fn import_candidate(&self) -> &ImportCandidate { | ||
33 | &self.import_candidate | ||
34 | } | ||
35 | |||
36 | fn for_method_call( | ||
37 | method_call: ast::MethodCallExpr, | 38 | method_call: ast::MethodCallExpr, |
38 | sema: &Semantics<RootDatabase>, | 39 | sema: &Semantics<RootDatabase>, |
39 | ) -> Option<Self> { | 40 | ) -> Option<Self> { |
@@ -46,7 +47,7 @@ impl ImportAssets { | |||
46 | }) | 47 | }) |
47 | } | 48 | } |
48 | 49 | ||
49 | fn for_regular_path( | 50 | pub(crate) fn for_regular_path( |
50 | path_under_caret: ast::Path, | 51 | path_under_caret: ast::Path, |
51 | sema: &Semantics<RootDatabase>, | 52 | sema: &Semantics<RootDatabase>, |
52 | ) -> Option<Self> { | 53 | ) -> Option<Self> { |
@@ -63,6 +64,14 @@ impl ImportAssets { | |||
63 | }) | 64 | }) |
64 | } | 65 | } |
65 | 66 | ||
67 | pub(crate) fn syntax_under_caret(&self) -> &SyntaxNode { | ||
68 | &self.syntax_under_caret | ||
69 | } | ||
70 | |||
71 | pub(crate) fn import_candidate(&self) -> &ImportCandidate { | ||
72 | &self.import_candidate | ||
73 | } | ||
74 | |||
66 | fn get_search_query(&self) -> &str { | 75 | fn get_search_query(&self) -> &str { |
67 | match &self.import_candidate { | 76 | match &self.import_candidate { |
68 | ImportCandidate::UnqualifiedName(name) => name, | 77 | ImportCandidate::UnqualifiedName(name) => name, |
@@ -182,25 +191,8 @@ impl ImportAssets { | |||
182 | } | 191 | } |
183 | } | 192 | } |
184 | 193 | ||
185 | #[derive(Debug)] | ||
186 | pub(crate) enum ImportCandidate { | ||
187 | /// Simple name like 'HashMap' | ||
188 | UnqualifiedName(String), | ||
189 | /// First part of the qualified name. | ||
190 | /// For 'std::collections::HashMap', that will be 'std'. | ||
191 | QualifierStart(String), | ||
192 | /// A trait associated function (with no self parameter) or associated constant. | ||
193 | /// For 'test_mod::TestEnum::test_function', `Type` is the `test_mod::TestEnum` expression type | ||
194 | /// and `String` is the `test_function` | ||
195 | TraitAssocItem(hir::Type, String), | ||
196 | /// A trait method with self parameter. | ||
197 | /// For 'test_enum.test_method()', `Type` is the `test_enum` expression type | ||
198 | /// and `String` is the `test_method` | ||
199 | TraitMethod(hir::Type, String), | ||
200 | } | ||
201 | |||
202 | impl ImportCandidate { | 194 | impl ImportCandidate { |
203 | pub(crate) fn for_method_call( | 195 | fn for_method_call( |
204 | sema: &Semantics<RootDatabase>, | 196 | sema: &Semantics<RootDatabase>, |
205 | method_call: &ast::MethodCallExpr, | 197 | method_call: &ast::MethodCallExpr, |
206 | ) -> Option<Self> { | 198 | ) -> Option<Self> { |
@@ -213,7 +205,7 @@ impl ImportCandidate { | |||
213 | )) | 205 | )) |
214 | } | 206 | } |
215 | 207 | ||
216 | pub(crate) fn for_regular_path( | 208 | fn for_regular_path( |
217 | sema: &Semantics<RootDatabase>, | 209 | sema: &Semantics<RootDatabase>, |
218 | path_under_caret: &ast::Path, | 210 | path_under_caret: &ast::Path, |
219 | ) -> Option<Self> { | 211 | ) -> Option<Self> { |