diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-03-24 08:43:58 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-03-24 08:43:58 +0000 |
commit | d5f77f3b6db604191c8b6856279a7bb5e0390375 (patch) | |
tree | c9afbe6d9c1c40bea7dedc05dded93aa6c7c146b /crates/ra_assists | |
parent | f9494f114798f66b5f2174cf518a2951a82571d3 (diff) | |
parent | dd3b64124b086cf68c3f8b1e838601b5770a9795 (diff) |
Merge #3685
3685: Auto import macros r=SomeoneToIgnore a=SomeoneToIgnore
If I got it right, assists test infra does not support multiple crates snippets (https://github.com/rust-analyzer/rust-analyzer/blob/2720e2374be951bb762ff2815dd67c7ffe3419b7/crates/ra_hir_def/src/nameres/tests.rs#L491) hence no tests added for the macro import.
Co-authored-by: Kirill Bulatov <[email protected]>
Diffstat (limited to 'crates/ra_assists')
-rw-r--r-- | crates/ra_assists/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_assists/src/handlers/auto_import.rs | 49 | ||||
-rw-r--r-- | crates/ra_assists/src/handlers/fill_match_arms.rs | 4 | ||||
-rw-r--r-- | crates/ra_assists/src/lib.rs | 29 |
4 files changed, 65 insertions, 18 deletions
diff --git a/crates/ra_assists/Cargo.toml b/crates/ra_assists/Cargo.toml index 707746ad5..a87f4052a 100644 --- a/crates/ra_assists/Cargo.toml +++ b/crates/ra_assists/Cargo.toml | |||
@@ -12,6 +12,7 @@ format-buf = "1.0.0" | |||
12 | join_to_string = "0.1.3" | 12 | join_to_string = "0.1.3" |
13 | rustc-hash = "1.1.0" | 13 | rustc-hash = "1.1.0" |
14 | itertools = "0.9.0" | 14 | itertools = "0.9.0" |
15 | either = "1.5.3" | ||
15 | 16 | ||
16 | ra_syntax = { path = "../ra_syntax" } | 17 | ra_syntax = { path = "../ra_syntax" } |
17 | ra_text_edit = { path = "../ra_text_edit" } | 18 | ra_text_edit = { path = "../ra_text_edit" } |
diff --git a/crates/ra_assists/src/handlers/auto_import.rs b/crates/ra_assists/src/handlers/auto_import.rs index bb280f633..99682e023 100644 --- a/crates/ra_assists/src/handlers/auto_import.rs +++ b/crates/ra_assists/src/handlers/auto_import.rs | |||
@@ -17,6 +17,7 @@ use crate::{ | |||
17 | utils::insert_use_statement, | 17 | utils::insert_use_statement, |
18 | AssistId, | 18 | AssistId, |
19 | }; | 19 | }; |
20 | use either::Either; | ||
20 | 21 | ||
21 | // Assist: auto_import | 22 | // Assist: auto_import |
22 | // | 23 | // |
@@ -58,6 +59,7 @@ pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> { | |||
58 | group.finish() | 59 | group.finish() |
59 | } | 60 | } |
60 | 61 | ||
62 | #[derive(Debug)] | ||
61 | struct AutoImportAssets { | 63 | struct AutoImportAssets { |
62 | import_candidate: ImportCandidate, | 64 | import_candidate: ImportCandidate, |
63 | module_with_name_to_import: Module, | 65 | module_with_name_to_import: Module, |
@@ -127,14 +129,14 @@ impl AutoImportAssets { | |||
127 | ImportsLocator::new(db) | 129 | ImportsLocator::new(db) |
128 | .find_imports(&self.get_search_query()) | 130 | .find_imports(&self.get_search_query()) |
129 | .into_iter() | 131 | .into_iter() |
130 | .filter_map(|module_def| match &self.import_candidate { | 132 | .filter_map(|candidate| match &self.import_candidate { |
131 | ImportCandidate::TraitAssocItem(assoc_item_type, _) => { | 133 | ImportCandidate::TraitAssocItem(assoc_item_type, _) => { |
132 | let located_assoc_item = match module_def { | 134 | let located_assoc_item = match candidate { |
133 | ModuleDef::Function(located_function) => located_function | 135 | Either::Left(ModuleDef::Function(located_function)) => located_function |
134 | .as_assoc_item(db) | 136 | .as_assoc_item(db) |
135 | .map(|assoc| assoc.container(db)) | 137 | .map(|assoc| assoc.container(db)) |
136 | .and_then(Self::assoc_to_trait), | 138 | .and_then(Self::assoc_to_trait), |
137 | ModuleDef::Const(located_const) => located_const | 139 | Either::Left(ModuleDef::Const(located_const)) => located_const |
138 | .as_assoc_item(db) | 140 | .as_assoc_item(db) |
139 | .map(|assoc| assoc.container(db)) | 141 | .map(|assoc| assoc.container(db)) |
140 | .and_then(Self::assoc_to_trait), | 142 | .and_then(Self::assoc_to_trait), |
@@ -153,10 +155,11 @@ impl AutoImportAssets { | |||
153 | |_, assoc| Self::assoc_to_trait(assoc.container(db)), | 155 | |_, assoc| Self::assoc_to_trait(assoc.container(db)), |
154 | ) | 156 | ) |
155 | .map(ModuleDef::from) | 157 | .map(ModuleDef::from) |
158 | .map(Either::Left) | ||
156 | } | 159 | } |
157 | ImportCandidate::TraitMethod(function_callee, _) => { | 160 | ImportCandidate::TraitMethod(function_callee, _) => { |
158 | let located_assoc_item = | 161 | let located_assoc_item = |
159 | if let ModuleDef::Function(located_function) = module_def { | 162 | if let Either::Left(ModuleDef::Function(located_function)) = candidate { |
160 | located_function | 163 | located_function |
161 | .as_assoc_item(db) | 164 | .as_assoc_item(db) |
162 | .map(|assoc| assoc.container(db)) | 165 | .map(|assoc| assoc.container(db)) |
@@ -179,10 +182,18 @@ impl AutoImportAssets { | |||
179 | }, | 182 | }, |
180 | ) | 183 | ) |
181 | .map(ModuleDef::from) | 184 | .map(ModuleDef::from) |
185 | .map(Either::Left) | ||
186 | } | ||
187 | _ => Some(candidate), | ||
188 | }) | ||
189 | .filter_map(|candidate| match candidate { | ||
190 | Either::Left(module_def) => { | ||
191 | self.module_with_name_to_import.find_use_path(db, module_def) | ||
192 | } | ||
193 | Either::Right(macro_def) => { | ||
194 | self.module_with_name_to_import.find_use_path(db, macro_def) | ||
182 | } | 195 | } |
183 | _ => Some(module_def), | ||
184 | }) | 196 | }) |
185 | .filter_map(|module_def| self.module_with_name_to_import.find_use_path(db, module_def)) | ||
186 | .filter(|use_path| !use_path.segments.is_empty()) | 197 | .filter(|use_path| !use_path.segments.is_empty()) |
187 | .take(20) | 198 | .take(20) |
188 | .collect::<BTreeSet<_>>() | 199 | .collect::<BTreeSet<_>>() |
@@ -440,6 +451,30 @@ mod tests { | |||
440 | } | 451 | } |
441 | 452 | ||
442 | #[test] | 453 | #[test] |
454 | fn macro_import() { | ||
455 | check_assist( | ||
456 | auto_import, | ||
457 | r" | ||
458 | //- /lib.rs crate:crate_with_macro | ||
459 | #[macro_export] | ||
460 | macro_rules! foo { | ||
461 | () => () | ||
462 | } | ||
463 | |||
464 | //- /main.rs crate:main deps:crate_with_macro | ||
465 | fn main() { | ||
466 | foo<|> | ||
467 | }", | ||
468 | r"use crate_with_macro::foo; | ||
469 | |||
470 | fn main() { | ||
471 | foo<|> | ||
472 | } | ||
473 | ", | ||
474 | ); | ||
475 | } | ||
476 | |||
477 | #[test] | ||
443 | fn auto_import_target() { | 478 | fn auto_import_target() { |
444 | check_assist_target( | 479 | check_assist_target( |
445 | auto_import, | 480 | auto_import, |
diff --git a/crates/ra_assists/src/handlers/fill_match_arms.rs b/crates/ra_assists/src/handlers/fill_match_arms.rs index 7463b2af7..88b4c8926 100644 --- a/crates/ra_assists/src/handlers/fill_match_arms.rs +++ b/crates/ra_assists/src/handlers/fill_match_arms.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | use std::iter; | 3 | use std::iter; |
4 | 4 | ||
5 | use hir::{Adt, HasSource, Semantics}; | 5 | use hir::{Adt, HasSource, ModuleDef, Semantics}; |
6 | use itertools::Itertools; | 6 | use itertools::Itertools; |
7 | use ra_ide_db::RootDatabase; | 7 | use ra_ide_db::RootDatabase; |
8 | 8 | ||
@@ -154,7 +154,7 @@ fn resolve_tuple_of_enum_def( | |||
154 | } | 154 | } |
155 | 155 | ||
156 | fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::EnumVariant) -> Option<ast::Pat> { | 156 | fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::EnumVariant) -> Option<ast::Pat> { |
157 | let path = crate::ast_transform::path_to_ast(module.find_use_path(db, var.into())?); | 157 | let path = crate::ast_transform::path_to_ast(module.find_use_path(db, ModuleDef::from(var))?); |
158 | 158 | ||
159 | // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though | 159 | // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though |
160 | let pat: ast::Pat = match var.source(db).value.kind() { | 160 | let pat: ast::Pat = match var.source(db).value.kind() { |
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index b8704ea7d..bcc9b3f10 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -165,7 +165,6 @@ mod helpers { | |||
165 | 165 | ||
166 | use ra_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}; | 166 | use ra_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}; |
167 | use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase}; | 167 | use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase}; |
168 | use ra_syntax::TextRange; | ||
169 | use test_utils::{add_cursor, assert_eq_text, extract_range_or_offset, RangeOrOffset}; | 168 | use test_utils::{add_cursor, assert_eq_text, extract_range_or_offset, RangeOrOffset}; |
170 | 169 | ||
171 | use crate::{AssistCtx, AssistHandler}; | 170 | use crate::{AssistCtx, AssistHandler}; |
@@ -175,8 +174,7 @@ mod helpers { | |||
175 | let (mut db, file_id) = RootDatabase::with_single_file(text); | 174 | let (mut db, file_id) = RootDatabase::with_single_file(text); |
176 | // FIXME: ideally, this should be done by the above `RootDatabase::with_single_file`, | 175 | // FIXME: ideally, this should be done by the above `RootDatabase::with_single_file`, |
177 | // but it looks like this might need specialization? :( | 176 | // but it looks like this might need specialization? :( |
178 | let local_roots = vec![db.file_source_root(file_id)]; | 177 | db.set_local_roots(Arc::new(vec![db.file_source_root(file_id)])); |
179 | db.set_local_roots(Arc::new(local_roots)); | ||
180 | (db, file_id) | 178 | (db, file_id) |
181 | } | 179 | } |
182 | 180 | ||
@@ -206,11 +204,24 @@ mod helpers { | |||
206 | } | 204 | } |
207 | 205 | ||
208 | fn check(assist: AssistHandler, before: &str, expected: ExpectedResult) { | 206 | fn check(assist: AssistHandler, before: &str, expected: ExpectedResult) { |
209 | let (range_or_offset, before) = extract_range_or_offset(before); | 207 | let (text_without_caret, file_with_caret_id, range_or_offset, db) = |
210 | let range: TextRange = range_or_offset.into(); | 208 | if before.contains("//-") { |
209 | let (mut db, position) = RootDatabase::with_position(before); | ||
210 | db.set_local_roots(Arc::new(vec![db.file_source_root(position.file_id)])); | ||
211 | ( | ||
212 | db.file_text(position.file_id).as_ref().to_owned(), | ||
213 | position.file_id, | ||
214 | RangeOrOffset::Offset(position.offset), | ||
215 | db, | ||
216 | ) | ||
217 | } else { | ||
218 | let (range_or_offset, text_without_caret) = extract_range_or_offset(before); | ||
219 | let (db, file_id) = with_single_file(&text_without_caret); | ||
220 | (text_without_caret, file_id, range_or_offset, db) | ||
221 | }; | ||
222 | |||
223 | let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() }; | ||
211 | 224 | ||
212 | let (db, file_id) = with_single_file(&before); | ||
213 | let frange = FileRange { file_id, range }; | ||
214 | let sema = Semantics::new(&db); | 225 | let sema = Semantics::new(&db); |
215 | let assist_ctx = AssistCtx::new(&sema, frange, true); | 226 | let assist_ctx = AssistCtx::new(&sema, frange, true); |
216 | 227 | ||
@@ -218,7 +229,7 @@ mod helpers { | |||
218 | (Some(assist), ExpectedResult::After(after)) => { | 229 | (Some(assist), ExpectedResult::After(after)) => { |
219 | let action = assist.0[0].action.clone().unwrap(); | 230 | let action = assist.0[0].action.clone().unwrap(); |
220 | 231 | ||
221 | let mut actual = action.edit.apply(&before); | 232 | let mut actual = action.edit.apply(&text_without_caret); |
222 | match action.cursor_position { | 233 | match action.cursor_position { |
223 | None => { | 234 | None => { |
224 | if let RangeOrOffset::Offset(before_cursor_pos) = range_or_offset { | 235 | if let RangeOrOffset::Offset(before_cursor_pos) = range_or_offset { |
@@ -237,7 +248,7 @@ mod helpers { | |||
237 | (Some(assist), ExpectedResult::Target(target)) => { | 248 | (Some(assist), ExpectedResult::Target(target)) => { |
238 | let action = assist.0[0].action.clone().unwrap(); | 249 | let action = assist.0[0].action.clone().unwrap(); |
239 | let range = action.target.expect("expected target on action"); | 250 | let range = action.target.expect("expected target on action"); |
240 | assert_eq_text!(&before[range], target); | 251 | assert_eq_text!(&text_without_caret[range], target); |
241 | } | 252 | } |
242 | (Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"), | 253 | (Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"), |
243 | (None, ExpectedResult::After(_)) | (None, ExpectedResult::Target(_)) => { | 254 | (None, ExpectedResult::After(_)) | (None, ExpectedResult::Target(_)) => { |