diff options
Diffstat (limited to 'crates/ra_assists/src/lib.rs')
-rw-r--r-- | crates/ra_assists/src/lib.rs | 158 |
1 files changed, 6 insertions, 152 deletions
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index ad8438b6c..8285e93a4 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -12,9 +12,8 @@ mod doc_tests; | |||
12 | pub mod ast_transform; | 12 | pub mod ast_transform; |
13 | 13 | ||
14 | use either::Either; | 14 | use either::Either; |
15 | use hir::ModuleDef; | ||
16 | use ra_db::FileRange; | 15 | use ra_db::FileRange; |
17 | use ra_ide_db::{imports_locator::ImportsLocatorIde, RootDatabase}; | 16 | use ra_ide_db::RootDatabase; |
18 | use ra_syntax::{TextRange, TextUnit}; | 17 | use ra_syntax::{TextRange, TextUnit}; |
19 | use ra_text_edit::TextEdit; | 18 | use ra_text_edit::TextEdit; |
20 | 19 | ||
@@ -73,50 +72,6 @@ pub fn applicable_assists(db: &RootDatabase, range: FileRange) -> Vec<AssistLabe | |||
73 | }) | 72 | }) |
74 | } | 73 | } |
75 | 74 | ||
76 | /// A functionality for locating imports for the given name. | ||
77 | /// | ||
78 | /// Currently has to be a trait with the real implementation provided by the ra_ide_api crate, | ||
79 | /// due to the search functionality located there. | ||
80 | /// Later, this trait should be removed completely and the search functionality moved to a separate crate, | ||
81 | /// accessible from the ra_assists crate. | ||
82 | pub trait ImportsLocator { | ||
83 | /// Finds all imports for the given name and the module that contains this name. | ||
84 | fn find_imports(&mut self, name_to_import: &str) -> Vec<ModuleDef>; | ||
85 | } | ||
86 | |||
87 | impl ImportsLocator for ImportsLocatorIde<'_> { | ||
88 | fn find_imports(&mut self, name_to_import: &str) -> Vec<ModuleDef> { | ||
89 | self.find_imports(name_to_import) | ||
90 | } | ||
91 | } | ||
92 | |||
93 | /// Return all the assists applicable at the given position | ||
94 | /// and additional assists that need the imports locator functionality to work. | ||
95 | /// | ||
96 | /// Assists are returned in the "resolved" state, that is with edit fully | ||
97 | /// computed. | ||
98 | pub fn assists_with_imports_locator(db: &RootDatabase, range: FileRange) -> Vec<ResolvedAssist> { | ||
99 | let mut imports_locator = ImportsLocatorIde::new(db); | ||
100 | AssistCtx::with_ctx(db, range, true, |ctx| { | ||
101 | let mut assists = assists::all() | ||
102 | .iter() | ||
103 | .map(|f| f(ctx.clone())) | ||
104 | .chain( | ||
105 | assists::all_with_imports_locator() | ||
106 | .iter() | ||
107 | .map(|f| f(ctx.clone(), &mut imports_locator)), | ||
108 | ) | ||
109 | .filter_map(std::convert::identity) | ||
110 | .map(|a| match a { | ||
111 | Assist::Resolved { assist } => assist, | ||
112 | Assist::Unresolved { .. } => unreachable!(), | ||
113 | }) | ||
114 | .collect(); | ||
115 | sort_assists(&mut assists); | ||
116 | assists | ||
117 | }) | ||
118 | } | ||
119 | |||
120 | /// Return all the assists applicable at the given position. | 75 | /// Return all the assists applicable at the given position. |
121 | /// | 76 | /// |
122 | /// Assists are returned in the "resolved" state, that is with edit fully | 77 | /// Assists are returned in the "resolved" state, that is with edit fully |
@@ -147,7 +102,7 @@ fn sort_assists(assists: &mut Vec<ResolvedAssist>) { | |||
147 | } | 102 | } |
148 | 103 | ||
149 | mod assists { | 104 | mod assists { |
150 | use crate::{Assist, AssistCtx, ImportsLocator}; | 105 | use crate::{Assist, AssistCtx}; |
151 | 106 | ||
152 | mod add_derive; | 107 | mod add_derive; |
153 | mod add_explicit_type; | 108 | mod add_explicit_type; |
@@ -206,72 +161,19 @@ mod assists { | |||
206 | raw_string::make_usual_string, | 161 | raw_string::make_usual_string, |
207 | raw_string::remove_hash, | 162 | raw_string::remove_hash, |
208 | early_return::convert_to_guarded_return, | 163 | early_return::convert_to_guarded_return, |
164 | auto_import::auto_import, | ||
209 | ] | 165 | ] |
210 | } | 166 | } |
211 | |||
212 | pub(crate) fn all_with_imports_locator<'a, F: ImportsLocator>( | ||
213 | ) -> &'a [fn(AssistCtx, &mut F) -> Option<Assist>] { | ||
214 | &[auto_import::auto_import] | ||
215 | } | ||
216 | } | 167 | } |
217 | 168 | ||
218 | #[cfg(test)] | 169 | #[cfg(test)] |
219 | mod helpers { | 170 | mod helpers { |
220 | use hir::db::DefDatabase; | 171 | use ra_db::{fixture::WithFixture, FileRange}; |
221 | use ra_db::{fixture::WithFixture, FileId, FileRange}; | 172 | use ra_ide_db::RootDatabase; |
222 | use ra_syntax::TextRange; | 173 | use ra_syntax::TextRange; |
223 | use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range}; | 174 | use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range}; |
224 | 175 | ||
225 | use crate::{Assist, AssistCtx, ImportsLocator}; | 176 | use crate::{Assist, AssistCtx}; |
226 | use ra_ide_db::RootDatabase; | ||
227 | use std::sync::Arc; | ||
228 | |||
229 | // FIXME remove the `ModuleDefId` reexport from `ra_hir` when this gets removed. | ||
230 | pub(crate) struct TestImportsLocator { | ||
231 | db: Arc<RootDatabase>, | ||
232 | test_file_id: FileId, | ||
233 | } | ||
234 | |||
235 | impl TestImportsLocator { | ||
236 | pub(crate) fn new(db: Arc<RootDatabase>, test_file_id: FileId) -> Self { | ||
237 | TestImportsLocator { db, test_file_id } | ||
238 | } | ||
239 | } | ||
240 | |||
241 | impl ImportsLocator for TestImportsLocator { | ||
242 | fn find_imports(&mut self, name_to_import: &str) -> Vec<hir::ModuleDef> { | ||
243 | let crate_def_map = self.db.crate_def_map(self.db.test_crate()); | ||
244 | let mut findings = Vec::new(); | ||
245 | |||
246 | let mut module_ids_to_process = | ||
247 | crate_def_map.modules_for_file(self.test_file_id).collect::<Vec<_>>(); | ||
248 | |||
249 | while !module_ids_to_process.is_empty() { | ||
250 | let mut more_ids_to_process = Vec::new(); | ||
251 | for local_module_id in module_ids_to_process.drain(..) { | ||
252 | for (name, namespace_data) in | ||
253 | crate_def_map[local_module_id].scope.entries_without_primitives() | ||
254 | { | ||
255 | let found_a_match = &name.to_string() == name_to_import; | ||
256 | vec![namespace_data.types, namespace_data.values] | ||
257 | .into_iter() | ||
258 | .filter_map(std::convert::identity) | ||
259 | .for_each(|(module_def_id, _)| { | ||
260 | if found_a_match { | ||
261 | findings.push(module_def_id.into()); | ||
262 | } | ||
263 | if let hir::ModuleDefId::ModuleId(module_id) = module_def_id { | ||
264 | more_ids_to_process.push(module_id.local_id); | ||
265 | } | ||
266 | }); | ||
267 | } | ||
268 | } | ||
269 | module_ids_to_process = more_ids_to_process; | ||
270 | } | ||
271 | |||
272 | findings | ||
273 | } | ||
274 | } | ||
275 | 177 | ||
276 | pub(crate) fn check_assist(assist: fn(AssistCtx) -> Option<Assist>, before: &str, after: &str) { | 178 | pub(crate) fn check_assist(assist: fn(AssistCtx) -> Option<Assist>, before: &str, after: &str) { |
277 | let (before_cursor_pos, before) = extract_offset(before); | 179 | let (before_cursor_pos, before) = extract_offset(before); |
@@ -297,38 +199,6 @@ mod helpers { | |||
297 | assert_eq_text!(after, &actual); | 199 | assert_eq_text!(after, &actual); |
298 | } | 200 | } |
299 | 201 | ||
300 | pub(crate) fn check_assist_with_imports_locator<F: ImportsLocator>( | ||
301 | assist: fn(AssistCtx, &mut F) -> Option<Assist>, | ||
302 | imports_locator_provider: fn(db: Arc<RootDatabase>, file_id: FileId) -> F, | ||
303 | before: &str, | ||
304 | after: &str, | ||
305 | ) { | ||
306 | let (before_cursor_pos, before) = extract_offset(before); | ||
307 | let (db, file_id) = RootDatabase::with_single_file(&before); | ||
308 | let db = Arc::new(db); | ||
309 | let mut imports_locator = imports_locator_provider(Arc::clone(&db), file_id); | ||
310 | let frange = | ||
311 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; | ||
312 | let assist = | ||
313 | AssistCtx::with_ctx(db.as_ref(), frange, true, |ctx| assist(ctx, &mut imports_locator)) | ||
314 | .expect("code action is not applicable"); | ||
315 | let action = match assist { | ||
316 | Assist::Unresolved { .. } => unreachable!(), | ||
317 | Assist::Resolved { assist } => assist.get_first_action(), | ||
318 | }; | ||
319 | |||
320 | let actual = action.edit.apply(&before); | ||
321 | let actual_cursor_pos = match action.cursor_position { | ||
322 | None => action | ||
323 | .edit | ||
324 | .apply_to_offset(before_cursor_pos) | ||
325 | .expect("cursor position is affected by the edit"), | ||
326 | Some(off) => off, | ||
327 | }; | ||
328 | let actual = add_cursor(&actual, actual_cursor_pos); | ||
329 | assert_eq_text!(after, &actual); | ||
330 | } | ||
331 | |||
332 | pub(crate) fn check_assist_range( | 202 | pub(crate) fn check_assist_range( |
333 | assist: fn(AssistCtx) -> Option<Assist>, | 203 | assist: fn(AssistCtx) -> Option<Assist>, |
334 | before: &str, | 204 | before: &str, |
@@ -402,22 +272,6 @@ mod helpers { | |||
402 | assert!(assist.is_none()); | 272 | assert!(assist.is_none()); |
403 | } | 273 | } |
404 | 274 | ||
405 | pub(crate) fn check_assist_with_imports_locator_not_applicable<F: ImportsLocator>( | ||
406 | assist: fn(AssistCtx, &mut F) -> Option<Assist>, | ||
407 | imports_locator_provider: fn(db: Arc<RootDatabase>, file_id: FileId) -> F, | ||
408 | before: &str, | ||
409 | ) { | ||
410 | let (before_cursor_pos, before) = extract_offset(before); | ||
411 | let (db, file_id) = RootDatabase::with_single_file(&before); | ||
412 | let db = Arc::new(db); | ||
413 | let mut imports_locator = imports_locator_provider(Arc::clone(&db), file_id); | ||
414 | let frange = | ||
415 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; | ||
416 | let assist = | ||
417 | AssistCtx::with_ctx(db.as_ref(), frange, true, |ctx| assist(ctx, &mut imports_locator)); | ||
418 | assert!(assist.is_none()); | ||
419 | } | ||
420 | |||
421 | pub(crate) fn check_assist_range_not_applicable( | 275 | pub(crate) fn check_assist_range_not_applicable( |
422 | assist: fn(AssistCtx) -> Option<Assist>, | 276 | assist: fn(AssistCtx) -> Option<Assist>, |
423 | before: &str, | 277 | before: &str, |