aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists')
-rw-r--r--crates/ra_assists/src/handlers/auto_import.rs48
1 files changed, 36 insertions, 12 deletions
diff --git a/crates/ra_assists/src/handlers/auto_import.rs b/crates/ra_assists/src/handlers/auto_import.rs
index e88c121eb..1081c9a5b 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// ```
29pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> { 29pub(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))
@@ -69,7 +72,7 @@ pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> {
69 edit.target(path_to_import_syntax.text_range()); 72 edit.target(path_to_import_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}