aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/assists
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src/assists')
-rw-r--r--crates/ra_assists/src/assists/add_import.rs10
-rw-r--r--crates/ra_assists/src/assists/auto_import.rs72
2 files changed, 54 insertions, 28 deletions
diff --git a/crates/ra_assists/src/assists/add_import.rs b/crates/ra_assists/src/assists/add_import.rs
index bf6cfe865..fc038df78 100644
--- a/crates/ra_assists/src/assists/add_import.rs
+++ b/crates/ra_assists/src/assists/add_import.rs
@@ -1,4 +1,4 @@
1use hir::{self, db::HirDatabase}; 1use hir::{self, db::HirDatabase, ModPath};
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{self, NameOwner}, 3 ast::{self, NameOwner},
4 AstNode, Direction, SmolStr, 4 AstNode, Direction, SmolStr,
@@ -20,10 +20,10 @@ pub fn auto_import_text_edit(
20 position: &SyntaxNode, 20 position: &SyntaxNode,
21 // The statement to use as anchor (last resort) 21 // The statement to use as anchor (last resort)
22 anchor: &SyntaxNode, 22 anchor: &SyntaxNode,
23 // The path to import as a sequence of strings 23 path_to_import: &ModPath,
24 target: &[SmolStr],
25 edit: &mut TextEditBuilder, 24 edit: &mut TextEditBuilder,
26) { 25) {
26 let target = path_to_import.to_string().split("::").map(SmolStr::new).collect::<Vec<_>>();
27 let container = position.ancestors().find_map(|n| { 27 let container = position.ancestors().find_map(|n| {
28 if let Some(module) = ast::Module::cast(n.clone()) { 28 if let Some(module) = ast::Module::cast(n.clone()) {
29 return module.item_list().map(|it| it.syntax().clone()); 29 return module.item_list().map(|it| it.syntax().clone());
@@ -32,8 +32,8 @@ pub fn auto_import_text_edit(
32 }); 32 });
33 33
34 if let Some(container) = container { 34 if let Some(container) = container {
35 let action = best_action_for_target(container, anchor.clone(), target); 35 let action = best_action_for_target(container, anchor.clone(), &target);
36 make_assist(&action, target, edit); 36 make_assist(&action, &target, edit);
37 } 37 }
38} 38}
39 39
diff --git a/crates/ra_assists/src/assists/auto_import.rs b/crates/ra_assists/src/assists/auto_import.rs
index 8c483e2da..2068256b0 100644
--- a/crates/ra_assists/src/assists/auto_import.rs
+++ b/crates/ra_assists/src/assists/auto_import.rs
@@ -1,8 +1,6 @@
1use hir::db::HirDatabase; 1use hir::{db::HirDatabase, ModPath};
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{self, AstNode}, 3 ast::{self, AstNode},
4 SmolStr,
5 SyntaxKind::USE_ITEM,
6 SyntaxNode, 4 SyntaxNode,
7}; 5};
8 6
@@ -34,9 +32,11 @@ pub(crate) fn auto_import<F: ImportsLocator>(
34) -> Option<Assist> { 32) -> Option<Assist> {
35 let path_to_import: ast::Path = ctx.find_node_at_offset()?; 33 let path_to_import: ast::Path = ctx.find_node_at_offset()?;
36 let path_to_import_syntax = path_to_import.syntax(); 34 let path_to_import_syntax = path_to_import.syntax();
37 if path_to_import_syntax.ancestors().find(|ancestor| ancestor.kind() == USE_ITEM).is_some() { 35 if path_to_import_syntax.ancestors().find_map(ast::UseItem::cast).is_some() {
38 return None; 36 return None;
39 } 37 }
38 let name_to_import =
39 path_to_import_syntax.descendants().find_map(ast::NameRef::cast)?.syntax().to_string();
40 40
41 let module = path_to_import_syntax.ancestors().find_map(ast::Module::cast); 41 let module = path_to_import_syntax.ancestors().find_map(ast::Module::cast);
42 let position = match module.and_then(|it| it.item_list()) { 42 let position = match module.and_then(|it| it.item_list()) {
@@ -53,38 +53,28 @@ pub(crate) fn auto_import<F: ImportsLocator>(
53 } 53 }
54 54
55 let proposed_imports = imports_locator 55 let proposed_imports = imports_locator
56 .find_imports(&path_to_import_syntax.to_string()) 56 .find_imports(&name_to_import)
57 .into_iter() 57 .into_iter()
58 .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def)) 58 .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def))
59 .filter(|use_path| !use_path.segments.is_empty()) 59 .filter(|use_path| !use_path.segments.is_empty())
60 .take(20) 60 .take(20)
61 .map(|import| import.to_string())
62 .collect::<std::collections::BTreeSet<_>>(); 61 .collect::<std::collections::BTreeSet<_>>();
63 if proposed_imports.is_empty() { 62 if proposed_imports.is_empty() {
64 return None; 63 return None;
65 } 64 }
66 65
67 ctx.add_assist_group( 66 ctx.add_assist_group(AssistId("auto_import"), format!("Import {}", name_to_import), || {
68 AssistId("auto_import"), 67 proposed_imports
69 format!("Import {}", path_to_import_syntax), 68 .into_iter()
70 || { 69 .map(|import| import_to_action(import, &position, &path_to_import_syntax))
71 proposed_imports 70 .collect()
72 .into_iter() 71 })
73 .map(|import| import_to_action(import, &position, &path_to_import_syntax))
74 .collect()
75 },
76 )
77} 72}
78 73
79fn import_to_action(import: String, position: &SyntaxNode, anchor: &SyntaxNode) -> ActionBuilder { 74fn import_to_action(import: ModPath, position: &SyntaxNode, anchor: &SyntaxNode) -> ActionBuilder {
80 let mut action_builder = ActionBuilder::default(); 75 let mut action_builder = ActionBuilder::default();
81 action_builder.label(format!("Import `{}`", &import)); 76 action_builder.label(format!("Import `{}`", &import));
82 auto_import_text_edit( 77 auto_import_text_edit(position, anchor, &import, action_builder.text_edit_builder());
83 position,
84 anchor,
85 &[SmolStr::new(import)],
86 action_builder.text_edit_builder(),
87 );
88 action_builder 78 action_builder
89} 79}
90 80
@@ -121,6 +111,42 @@ mod tests {
121 } 111 }
122 112
123 #[test] 113 #[test]
114 fn auto_imports_are_merged() {
115 check_assist_with_imports_locator(
116 auto_import,
117 TestImportsLocator::new,
118 r"
119 use PubMod::PubStruct1;
120
121 struct Test {
122 test: Pub<|>Struct2<u8>,
123 }
124
125 pub mod PubMod {
126 pub struct PubStruct1;
127 pub struct PubStruct2<T> {
128 _t: T,
129 }
130 }
131 ",
132 r"
133 use PubMod::{PubStruct2, PubStruct1};
134
135 struct Test {
136 test: Pub<|>Struct2<u8>,
137 }
138
139 pub mod PubMod {
140 pub struct PubStruct1;
141 pub struct PubStruct2<T> {
142 _t: T,
143 }
144 }
145 ",
146 );
147 }
148
149 #[test]
124 fn applicable_when_found_multiple_imports() { 150 fn applicable_when_found_multiple_imports() {
125 check_assist_with_imports_locator( 151 check_assist_with_imports_locator(
126 auto_import, 152 auto_import,