aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_assists
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_assists')
-rw-r--r--crates/ide_assists/src/handlers/auto_import.rs52
-rw-r--r--crates/ide_assists/src/handlers/qualify_path.rs40
-rw-r--r--crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs33
3 files changed, 54 insertions, 71 deletions
diff --git a/crates/ide_assists/src/handlers/auto_import.rs b/crates/ide_assists/src/handlers/auto_import.rs
index 1422224ac..7caee8df0 100644
--- a/crates/ide_assists/src/handlers/auto_import.rs
+++ b/crates/ide_assists/src/handlers/auto_import.rs
@@ -1,7 +1,7 @@
1use ide_db::helpers::{ 1use ide_db::helpers::{
2 import_assets::{ImportAssets, ImportCandidate}, 2 import_assets::{ImportAssets, ImportCandidate},
3 insert_use::{insert_use, ImportScope}, 3 insert_use::{insert_use, ImportScope},
4 mod_path_to_ast, 4 item_name, mod_path_to_ast,
5}; 5};
6use syntax::{ast, AstNode, SyntaxNode}; 6use syntax::{ast, AstNode, SyntaxNode};
7 7
@@ -92,14 +92,19 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
92 let range = ctx.sema.original_range(&syntax_under_caret).range; 92 let range = ctx.sema.original_range(&syntax_under_caret).range;
93 let group = import_group_message(import_assets.import_candidate()); 93 let group = import_group_message(import_assets.import_candidate());
94 let scope = ImportScope::find_insert_use_container(&syntax_under_caret, &ctx.sema)?; 94 let scope = ImportScope::find_insert_use_container(&syntax_under_caret, &ctx.sema)?;
95 for (import, _) in proposed_imports { 95 for import in proposed_imports {
96 let name = match item_name(ctx.db(), import.original_item) {
97 Some(name) => name,
98 None => continue,
99 };
96 acc.add_group( 100 acc.add_group(
97 &group, 101 &group,
98 AssistId("auto_import", AssistKind::QuickFix), 102 AssistId("auto_import", AssistKind::QuickFix),
99 format!("Import `{}`", &import), 103 format!("Import `{}`", name),
100 range, 104 range,
101 |builder| { 105 |builder| {
102 let rewriter = insert_use(&scope, mod_path_to_ast(&import), ctx.config.insert_use); 106 let rewriter =
107 insert_use(&scope, mod_path_to_ast(&import.import_path), ctx.config.insert_use);
103 builder.rewrite(rewriter); 108 builder.rewrite(rewriter);
104 }, 109 },
105 ); 110 );
@@ -125,10 +130,10 @@ fn import_group_message(import_candidate: &ImportCandidate) -> GroupLabel {
125 let name = match import_candidate { 130 let name = match import_candidate {
126 ImportCandidate::Path(candidate) => format!("Import {}", candidate.name.text()), 131 ImportCandidate::Path(candidate) => format!("Import {}", candidate.name.text()),
127 ImportCandidate::TraitAssocItem(candidate) => { 132 ImportCandidate::TraitAssocItem(candidate) => {
128 format!("Import a trait for item {}", candidate.name.text()) 133 format!("Import a trait for item {}", candidate.assoc_item_name.text())
129 } 134 }
130 ImportCandidate::TraitMethod(candidate) => { 135 ImportCandidate::TraitMethod(candidate) => {
131 format!("Import a trait for method {}", candidate.name.text()) 136 format!("Import a trait for method {}", candidate.assoc_item_name.text())
132 } 137 }
133 }; 138 };
134 GroupLabel(name) 139 GroupLabel(name)
@@ -221,41 +226,6 @@ mod tests {
221 } 226 }
222 227
223 #[test] 228 #[test]
224 fn auto_imports_are_merged() {
225 check_assist(
226 auto_import,
227 r"
228 use PubMod::PubStruct1;
229
230 struct Test {
231 test: Pub$0Struct2<u8>,
232 }
233
234 pub mod PubMod {
235 pub struct PubStruct1;
236 pub struct PubStruct2<T> {
237 _t: T,
238 }
239 }
240 ",
241 r"
242 use PubMod::{PubStruct1, PubStruct2};
243
244 struct Test {
245 test: PubStruct2<u8>,
246 }
247
248 pub mod PubMod {
249 pub struct PubStruct1;
250 pub struct PubStruct2<T> {
251 _t: T,
252 }
253 }
254 ",
255 );
256 }
257
258 #[test]
259 fn applicable_when_found_multiple_imports() { 229 fn applicable_when_found_multiple_imports() {
260 check_assist( 230 check_assist(
261 auto_import, 231 auto_import,
diff --git a/crates/ide_assists/src/handlers/qualify_path.rs b/crates/ide_assists/src/handlers/qualify_path.rs
index d3e34e540..272874ae3 100644
--- a/crates/ide_assists/src/handlers/qualify_path.rs
+++ b/crates/ide_assists/src/handlers/qualify_path.rs
@@ -1,7 +1,10 @@
1use std::iter; 1use std::iter;
2 2
3use hir::AsAssocItem; 3use hir::AsAssocItem;
4use ide_db::helpers::{import_assets::ImportCandidate, mod_path_to_ast}; 4use ide_db::helpers::{
5 import_assets::{ImportCandidate, LocatedImport},
6 item_name, mod_path_to_ast,
7};
5use ide_db::RootDatabase; 8use ide_db::RootDatabase;
6use syntax::{ 9use syntax::{
7 ast, 10 ast,
@@ -71,17 +74,17 @@ pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
71 }; 74 };
72 75
73 let group_label = group_label(candidate); 76 let group_label = group_label(candidate);
74 for (import, item) in proposed_imports { 77 for import in proposed_imports {
75 acc.add_group( 78 acc.add_group(
76 &group_label, 79 &group_label,
77 AssistId("qualify_path", AssistKind::QuickFix), 80 AssistId("qualify_path", AssistKind::QuickFix),
78 label(candidate, &import), 81 label(ctx.db(), candidate, &import),
79 range, 82 range,
80 |builder| { 83 |builder| {
81 qualify_candidate.qualify( 84 qualify_candidate.qualify(
82 |replace_with: String| builder.replace(range, replace_with), 85 |replace_with: String| builder.replace(range, replace_with),
83 import, 86 &import.import_path,
84 item, 87 import.item_to_import,
85 ) 88 )
86 }, 89 },
87 ); 90 );
@@ -97,8 +100,13 @@ enum QualifyCandidate<'db> {
97} 100}
98 101
99impl QualifyCandidate<'_> { 102impl QualifyCandidate<'_> {
100 fn qualify(&self, mut replacer: impl FnMut(String), import: hir::ModPath, item: hir::ItemInNs) { 103 fn qualify(
101 let import = mod_path_to_ast(&import); 104 &self,
105 mut replacer: impl FnMut(String),
106 import: &hir::ModPath,
107 item: hir::ItemInNs,
108 ) {
109 let import = mod_path_to_ast(import);
102 match self { 110 match self {
103 QualifyCandidate::QualifierStart(segment, generics) => { 111 QualifyCandidate::QualifierStart(segment, generics) => {
104 let generics = generics.as_ref().map_or_else(String::new, ToString::to_string); 112 let generics = generics.as_ref().map_or_else(String::new, ToString::to_string);
@@ -183,23 +191,29 @@ fn item_as_trait(db: &RootDatabase, item: hir::ItemInNs) -> Option<hir::Trait> {
183fn group_label(candidate: &ImportCandidate) -> GroupLabel { 191fn group_label(candidate: &ImportCandidate) -> GroupLabel {
184 let name = match candidate { 192 let name = match candidate {
185 ImportCandidate::Path(it) => &it.name, 193 ImportCandidate::Path(it) => &it.name,
186 ImportCandidate::TraitAssocItem(it) | ImportCandidate::TraitMethod(it) => &it.name, 194 ImportCandidate::TraitAssocItem(it) | ImportCandidate::TraitMethod(it) => {
195 &it.assoc_item_name
196 }
187 } 197 }
188 .text(); 198 .text();
189 GroupLabel(format!("Qualify {}", name)) 199 GroupLabel(format!("Qualify {}", name))
190} 200}
191 201
192fn label(candidate: &ImportCandidate, import: &hir::ModPath) -> String { 202fn label(db: &RootDatabase, candidate: &ImportCandidate, import: &LocatedImport) -> String {
203 let display_path = match item_name(db, import.original_item) {
204 Some(display_path) => display_path.to_string(),
205 None => "{unknown}".to_string(),
206 };
193 match candidate { 207 match candidate {
194 ImportCandidate::Path(candidate) => { 208 ImportCandidate::Path(candidate) => {
195 if candidate.qualifier.is_some() { 209 if candidate.qualifier.is_some() {
196 format!("Qualify with `{}`", &import) 210 format!("Qualify with `{}`", display_path)
197 } else { 211 } else {
198 format!("Qualify as `{}`", &import) 212 format!("Qualify as `{}`", display_path)
199 } 213 }
200 } 214 }
201 ImportCandidate::TraitAssocItem(_) => format!("Qualify `{}`", &import), 215 ImportCandidate::TraitAssocItem(_) => format!("Qualify `{}`", display_path),
202 ImportCandidate::TraitMethod(_) => format!("Qualify with cast as `{}`", &import), 216 ImportCandidate::TraitMethod(_) => format!("Qualify with cast as `{}`", display_path),
203 } 217 }
204} 218}
205 219
diff --git a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
index c69bc5cac..88fe2fe90 100644
--- a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -1,5 +1,6 @@
1use hir::ModuleDef;
1use ide_db::helpers::mod_path_to_ast; 2use ide_db::helpers::mod_path_to_ast;
2use ide_db::imports_locator; 3use ide_db::items_locator;
3use itertools::Itertools; 4use itertools::Itertools;
4use syntax::{ 5use syntax::{
5 ast::{self, make, AstNode, NameOwner}, 6 ast::{self, make, AstNode, NameOwner},
@@ -64,22 +65,20 @@ pub(crate) fn replace_derive_with_manual_impl(
64 let current_module = ctx.sema.scope(annotated_name.syntax()).module()?; 65 let current_module = ctx.sema.scope(annotated_name.syntax()).module()?;
65 let current_crate = current_module.krate(); 66 let current_crate = current_module.krate();
66 67
67 let found_traits = imports_locator::find_exact_imports( 68 let found_traits =
68 &ctx.sema, 69 items_locator::with_exact_name(&ctx.sema, current_crate, trait_token.text().to_string())
69 current_crate, 70 .into_iter()
70 trait_token.text().to_string(), 71 .filter_map(|item| match ModuleDef::from(item.as_module_def_id()?) {
71 ) 72 ModuleDef::Trait(trait_) => Some(trait_),
72 .filter_map(|candidate: either::Either<hir::ModuleDef, hir::MacroDef>| match candidate { 73 _ => None,
73 either::Either::Left(hir::ModuleDef::Trait(trait_)) => Some(trait_), 74 })
74 _ => None, 75 .flat_map(|trait_| {
75 }) 76 current_module
76 .flat_map(|trait_| { 77 .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_))
77 current_module 78 .as_ref()
78 .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_)) 79 .map(mod_path_to_ast)
79 .as_ref() 80 .zip(Some(trait_))
80 .map(mod_path_to_ast) 81 });
81 .zip(Some(trait_))
82 });
83 82
84 let mut no_traits_found = true; 83 let mut no_traits_found = true;
85 for (trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) { 84 for (trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) {