aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/assists/src/handlers/auto_import.rs22
-rw-r--r--crates/assists/src/utils/import_assets.rs66
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 @@
1use syntax::ast;
2
1use crate::{ 3use 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// ```
26pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 28pub(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};
10use crate::assist_config::InsertUseConfig; 10use crate::assist_config::InsertUseConfig;
11 11
12#[derive(Debug)] 12#[derive(Debug)]
13pub(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)]
13pub(crate) struct ImportAssets { 30pub(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
19impl ImportAssets { 36impl 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)]
186pub(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
202impl ImportCandidate { 194impl 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> {