diff options
Diffstat (limited to 'crates/ra_assists/src/handlers/auto_import.rs')
-rw-r--r-- | crates/ra_assists/src/handlers/auto_import.rs | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/crates/ra_assists/src/handlers/auto_import.rs b/crates/ra_assists/src/handlers/auto_import.rs index e88c121eb..1fb701da5 100644 --- a/crates/ra_assists/src/handlers/auto_import.rs +++ b/crates/ra_assists/src/handlers/auto_import.rs | |||
@@ -27,31 +27,34 @@ use std::collections::BTreeSet; | |||
27 | // # pub mod std { pub mod collections { pub struct HashMap { } } } | 27 | // # pub mod std { pub mod collections { pub struct HashMap { } } } |
28 | // ``` | 28 | // ``` |
29 | pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> { | 29 | pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> { |
30 | let path_to_import: ast::Path = ctx.find_node_at_offset()?; | 30 | let path_under_caret: ast::Path = ctx.find_node_at_offset()?; |
31 | let path_to_import_syntax = path_to_import.syntax(); | 31 | if path_under_caret.syntax().ancestors().find_map(ast::UseItem::cast).is_some() { |
32 | if path_to_import_syntax.ancestors().find_map(ast::UseItem::cast).is_some() { | ||
33 | return None; | 32 | return None; |
34 | } | 33 | } |
35 | let name_to_import = | ||
36 | path_to_import_syntax.descendants().find_map(ast::NameRef::cast)?.syntax().to_string(); | ||
37 | 34 | ||
38 | let module = path_to_import_syntax.ancestors().find_map(ast::Module::cast); | 35 | let module = path_under_caret.syntax().ancestors().find_map(ast::Module::cast); |
39 | let position = match module.and_then(|it| it.item_list()) { | 36 | let position = match module.and_then(|it| it.item_list()) { |
40 | Some(item_list) => item_list.syntax().clone(), | 37 | Some(item_list) => item_list.syntax().clone(), |
41 | None => { | 38 | None => { |
42 | let current_file = path_to_import_syntax.ancestors().find_map(ast::SourceFile::cast)?; | 39 | let current_file = |
40 | path_under_caret.syntax().ancestors().find_map(ast::SourceFile::cast)?; | ||
43 | current_file.syntax().clone() | 41 | current_file.syntax().clone() |
44 | } | 42 | } |
45 | }; | 43 | }; |
46 | let source_analyzer = ctx.source_analyzer(&position, None); | 44 | let source_analyzer = ctx.source_analyzer(&position, None); |
47 | let module_with_name_to_import = source_analyzer.module()?; | 45 | let module_with_name_to_import = source_analyzer.module()?; |
48 | if source_analyzer.resolve_path(ctx.db, &path_to_import).is_some() { | 46 | |
47 | let name_ref_to_import = | ||
48 | path_under_caret.syntax().descendants().find_map(ast::NameRef::cast)?; | ||
49 | if source_analyzer | ||
50 | .resolve_path(ctx.db, &name_ref_to_import.syntax().ancestors().find_map(ast::Path::cast)?) | ||
51 | .is_some() | ||
52 | { | ||
49 | return None; | 53 | return None; |
50 | } | 54 | } |
51 | 55 | ||
52 | let mut imports_locator = ImportsLocator::new(ctx.db); | 56 | let name_to_import = name_ref_to_import.syntax().to_string(); |
53 | 57 | let proposed_imports = ImportsLocator::new(ctx.db) | |
54 | let proposed_imports = imports_locator | ||
55 | .find_imports(&name_to_import) | 58 | .find_imports(&name_to_import) |
56 | .into_iter() | 59 | .into_iter() |
57 | .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def)) | 60 | .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def)) |
@@ -66,10 +69,10 @@ pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> { | |||
66 | let mut group = ctx.add_assist_group(format!("Import {}", name_to_import)); | 69 | let mut group = ctx.add_assist_group(format!("Import {}", name_to_import)); |
67 | for import in proposed_imports { | 70 | for import in proposed_imports { |
68 | group.add_assist(AssistId("auto_import"), format!("Import `{}`", &import), |edit| { | 71 | group.add_assist(AssistId("auto_import"), format!("Import `{}`", &import), |edit| { |
69 | edit.target(path_to_import_syntax.text_range()); | 72 | edit.target(path_under_caret.syntax().text_range()); |
70 | insert_use_statement( | 73 | insert_use_statement( |
71 | &position, | 74 | &position, |
72 | path_to_import_syntax, | 75 | path_under_caret.syntax(), |
73 | &import, | 76 | &import, |
74 | edit.text_edit_builder(), | 77 | edit.text_edit_builder(), |
75 | ); | 78 | ); |
@@ -266,4 +269,25 @@ mod tests { | |||
266 | "GroupLabel", | 269 | "GroupLabel", |
267 | ) | 270 | ) |
268 | } | 271 | } |
272 | |||
273 | #[test] | ||
274 | fn not_applicable_when_path_start_is_imported() { | ||
275 | check_assist_not_applicable( | ||
276 | auto_import, | ||
277 | r" | ||
278 | pub mod mod1 { | ||
279 | pub mod mod2 { | ||
280 | pub mod mod3 { | ||
281 | pub struct TestStruct; | ||
282 | } | ||
283 | } | ||
284 | } | ||
285 | |||
286 | use mod1::mod2; | ||
287 | fn main() { | ||
288 | mod2::mod3::TestStruct<|> | ||
289 | } | ||
290 | ", | ||
291 | ); | ||
292 | } | ||
269 | } | 293 | } |