diff options
Diffstat (limited to 'crates/ra_assists/src/lib.rs')
-rw-r--r-- | crates/ra_assists/src/lib.rs | 95 |
1 files changed, 29 insertions, 66 deletions
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index ab77b46a9..38599d4f1 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -7,15 +7,16 @@ | |||
7 | 7 | ||
8 | mod assist_ctx; | 8 | mod assist_ctx; |
9 | mod marks; | 9 | mod marks; |
10 | #[cfg(test)] | ||
11 | mod doc_tests; | ||
10 | 12 | ||
11 | use hir::db::HirDatabase; | 13 | use hir::db::HirDatabase; |
12 | use itertools::Itertools; | ||
13 | use ra_db::FileRange; | 14 | use ra_db::FileRange; |
14 | use ra_syntax::{TextRange, TextUnit}; | 15 | use ra_syntax::{TextRange, TextUnit}; |
15 | use ra_text_edit::TextEdit; | 16 | use ra_text_edit::TextEdit; |
16 | 17 | ||
17 | pub(crate) use crate::assist_ctx::{Assist, AssistCtx}; | 18 | pub(crate) use crate::assist_ctx::{Assist, AssistCtx}; |
18 | pub use crate::assists::auto_import::auto_import_text_edit; | 19 | pub use crate::assists::add_import::auto_import_text_edit; |
19 | 20 | ||
20 | /// Unique identifier of the assist, should not be shown to the user | 21 | /// Unique identifier of the assist, should not be shown to the user |
21 | /// directly. | 22 | /// directly. |
@@ -36,7 +37,7 @@ pub struct AssistAction { | |||
36 | pub target: Option<TextRange>, | 37 | pub target: Option<TextRange>, |
37 | } | 38 | } |
38 | 39 | ||
39 | /// Return all the assists eapplicable at the given position. | 40 | /// Return all the assists applicable at the given position. |
40 | /// | 41 | /// |
41 | /// Assists are returned in the "unresolved" state, that is only labels are | 42 | /// Assists are returned in the "unresolved" state, that is only labels are |
42 | /// returned, without actual edits. | 43 | /// returned, without actual edits. |
@@ -49,10 +50,10 @@ where | |||
49 | .iter() | 50 | .iter() |
50 | .filter_map(|f| f(ctx.clone())) | 51 | .filter_map(|f| f(ctx.clone())) |
51 | .map(|a| match a { | 52 | .map(|a| match a { |
52 | Assist::Unresolved(labels) => labels, | 53 | Assist::Unresolved { label } => label, |
53 | Assist::Resolved(..) => unreachable!(), | 54 | Assist::Resolved { .. } => unreachable!(), |
54 | }) | 55 | }) |
55 | .concat() | 56 | .collect() |
56 | }) | 57 | }) |
57 | } | 58 | } |
58 | 59 | ||
@@ -71,10 +72,10 @@ where | |||
71 | .iter() | 72 | .iter() |
72 | .filter_map(|f| f(ctx.clone())) | 73 | .filter_map(|f| f(ctx.clone())) |
73 | .map(|a| match a { | 74 | .map(|a| match a { |
74 | Assist::Resolved(labels_actions) => labels_actions, | 75 | Assist::Resolved { label, action } => (label, action), |
75 | Assist::Unresolved(..) => unreachable!(), | 76 | Assist::Unresolved { .. } => unreachable!(), |
76 | }) | 77 | }) |
77 | .concat(); | 78 | .collect::<Vec<_>>(); |
78 | a.sort_by(|a, b| match (a.1.target, b.1.target) { | 79 | a.sort_by(|a, b| match (a.1.target, b.1.target) { |
79 | (Some(a), Some(b)) => a.len().cmp(&b.len()), | 80 | (Some(a), Some(b)) => a.len().cmp(&b.len()), |
80 | (Some(_), None) => Ordering::Less, | 81 | (Some(_), None) => Ordering::Less, |
@@ -95,6 +96,7 @@ mod assists { | |||
95 | mod apply_demorgan; | 96 | mod apply_demorgan; |
96 | mod flip_comma; | 97 | mod flip_comma; |
97 | mod flip_binexpr; | 98 | mod flip_binexpr; |
99 | mod flip_trait_bound; | ||
98 | mod change_visibility; | 100 | mod change_visibility; |
99 | mod fill_match_arms; | 101 | mod fill_match_arms; |
100 | mod merge_match_arms; | 102 | mod merge_match_arms; |
@@ -104,7 +106,7 @@ mod assists { | |||
104 | mod replace_if_let_with_match; | 106 | mod replace_if_let_with_match; |
105 | mod split_import; | 107 | mod split_import; |
106 | mod remove_dbg; | 108 | mod remove_dbg; |
107 | pub(crate) mod auto_import; | 109 | pub(crate) mod add_import; |
108 | mod add_missing_impl_members; | 110 | mod add_missing_impl_members; |
109 | mod move_guard; | 111 | mod move_guard; |
110 | mod move_bounds; | 112 | mod move_bounds; |
@@ -121,11 +123,12 @@ mod assists { | |||
121 | merge_match_arms::merge_match_arms, | 123 | merge_match_arms::merge_match_arms, |
122 | flip_comma::flip_comma, | 124 | flip_comma::flip_comma, |
123 | flip_binexpr::flip_binexpr, | 125 | flip_binexpr::flip_binexpr, |
126 | flip_trait_bound::flip_trait_bound, | ||
124 | introduce_variable::introduce_variable, | 127 | introduce_variable::introduce_variable, |
125 | replace_if_let_with_match::replace_if_let_with_match, | 128 | replace_if_let_with_match::replace_if_let_with_match, |
126 | split_import::split_import, | 129 | split_import::split_import, |
127 | remove_dbg::remove_dbg, | 130 | remove_dbg::remove_dbg, |
128 | auto_import::auto_import, | 131 | add_import::add_import, |
129 | add_missing_impl_members::add_missing_impl_members, | 132 | add_missing_impl_members::add_missing_impl_members, |
130 | add_missing_impl_members::add_missing_default_members, | 133 | add_missing_impl_members::add_missing_default_members, |
131 | inline_local_variable::inline_local_varialbe, | 134 | inline_local_variable::inline_local_varialbe, |
@@ -155,51 +158,17 @@ mod helpers { | |||
155 | before: &str, | 158 | before: &str, |
156 | after: &str, | 159 | after: &str, |
157 | ) { | 160 | ) { |
158 | check_assist_nth_action(assist, before, after, 0) | ||
159 | } | ||
160 | |||
161 | pub(crate) fn check_assist_range( | ||
162 | assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, | ||
163 | before: &str, | ||
164 | after: &str, | ||
165 | ) { | ||
166 | check_assist_range_nth_action(assist, before, after, 0) | ||
167 | } | ||
168 | |||
169 | pub(crate) fn check_assist_target( | ||
170 | assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, | ||
171 | before: &str, | ||
172 | target: &str, | ||
173 | ) { | ||
174 | check_assist_target_nth_action(assist, before, target, 0) | ||
175 | } | ||
176 | |||
177 | pub(crate) fn check_assist_range_target( | ||
178 | assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, | ||
179 | before: &str, | ||
180 | target: &str, | ||
181 | ) { | ||
182 | check_assist_range_target_nth_action(assist, before, target, 0) | ||
183 | } | ||
184 | |||
185 | pub(crate) fn check_assist_nth_action( | ||
186 | assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, | ||
187 | before: &str, | ||
188 | after: &str, | ||
189 | index: usize, | ||
190 | ) { | ||
191 | let (before_cursor_pos, before) = extract_offset(before); | 161 | let (before_cursor_pos, before) = extract_offset(before); |
192 | let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); | 162 | let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); |
193 | let frange = | 163 | let frange = |
194 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; | 164 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; |
195 | let assist = | 165 | let assist = |
196 | AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable"); | 166 | AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable"); |
197 | let labels_actions = match assist { | 167 | let action = match assist { |
198 | Assist::Unresolved(_) => unreachable!(), | 168 | Assist::Unresolved { .. } => unreachable!(), |
199 | Assist::Resolved(labels_actions) => labels_actions, | 169 | Assist::Resolved { action, .. } => action, |
200 | }; | 170 | }; |
201 | 171 | ||
202 | let (_, action) = labels_actions.get(index).expect("expect assist action at index"); | ||
203 | let actual = action.edit.apply(&before); | 172 | let actual = action.edit.apply(&before); |
204 | let actual_cursor_pos = match action.cursor_position { | 173 | let actual_cursor_pos = match action.cursor_position { |
205 | None => action | 174 | None => action |
@@ -212,23 +181,21 @@ mod helpers { | |||
212 | assert_eq_text!(after, &actual); | 181 | assert_eq_text!(after, &actual); |
213 | } | 182 | } |
214 | 183 | ||
215 | pub(crate) fn check_assist_range_nth_action( | 184 | pub(crate) fn check_assist_range( |
216 | assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, | 185 | assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, |
217 | before: &str, | 186 | before: &str, |
218 | after: &str, | 187 | after: &str, |
219 | index: usize, | ||
220 | ) { | 188 | ) { |
221 | let (range, before) = extract_range(before); | 189 | let (range, before) = extract_range(before); |
222 | let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); | 190 | let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); |
223 | let frange = FileRange { file_id, range }; | 191 | let frange = FileRange { file_id, range }; |
224 | let assist = | 192 | let assist = |
225 | AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable"); | 193 | AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable"); |
226 | let labels_actions = match assist { | 194 | let action = match assist { |
227 | Assist::Unresolved(_) => unreachable!(), | 195 | Assist::Unresolved { .. } => unreachable!(), |
228 | Assist::Resolved(labels_actions) => labels_actions, | 196 | Assist::Resolved { action, .. } => action, |
229 | }; | 197 | }; |
230 | 198 | ||
231 | let (_, action) = labels_actions.get(index).expect("expect assist action at index"); | ||
232 | let mut actual = action.edit.apply(&before); | 199 | let mut actual = action.edit.apply(&before); |
233 | if let Some(pos) = action.cursor_position { | 200 | if let Some(pos) = action.cursor_position { |
234 | actual = add_cursor(&actual, pos); | 201 | actual = add_cursor(&actual, pos); |
@@ -236,11 +203,10 @@ mod helpers { | |||
236 | assert_eq_text!(after, &actual); | 203 | assert_eq_text!(after, &actual); |
237 | } | 204 | } |
238 | 205 | ||
239 | pub(crate) fn check_assist_target_nth_action( | 206 | pub(crate) fn check_assist_target( |
240 | assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, | 207 | assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, |
241 | before: &str, | 208 | before: &str, |
242 | target: &str, | 209 | target: &str, |
243 | index: usize, | ||
244 | ) { | 210 | ) { |
245 | let (before_cursor_pos, before) = extract_offset(before); | 211 | let (before_cursor_pos, before) = extract_offset(before); |
246 | let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); | 212 | let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); |
@@ -248,33 +214,30 @@ mod helpers { | |||
248 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; | 214 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; |
249 | let assist = | 215 | let assist = |
250 | AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable"); | 216 | AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable"); |
251 | let labels_actions = match assist { | 217 | let action = match assist { |
252 | Assist::Unresolved(_) => unreachable!(), | 218 | Assist::Unresolved { .. } => unreachable!(), |
253 | Assist::Resolved(labels_actions) => labels_actions, | 219 | Assist::Resolved { action, .. } => action, |
254 | }; | 220 | }; |
255 | 221 | ||
256 | let (_, action) = labels_actions.get(index).expect("expect assist action at index"); | ||
257 | let range = action.target.expect("expected target on action"); | 222 | let range = action.target.expect("expected target on action"); |
258 | assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); | 223 | assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); |
259 | } | 224 | } |
260 | 225 | ||
261 | pub(crate) fn check_assist_range_target_nth_action( | 226 | pub(crate) fn check_assist_range_target( |
262 | assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, | 227 | assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>, |
263 | before: &str, | 228 | before: &str, |
264 | target: &str, | 229 | target: &str, |
265 | index: usize, | ||
266 | ) { | 230 | ) { |
267 | let (range, before) = extract_range(before); | 231 | let (range, before) = extract_range(before); |
268 | let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); | 232 | let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); |
269 | let frange = FileRange { file_id, range }; | 233 | let frange = FileRange { file_id, range }; |
270 | let assist = | 234 | let assist = |
271 | AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable"); | 235 | AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable"); |
272 | let labels_actions = match assist { | 236 | let action = match assist { |
273 | Assist::Unresolved(_) => unreachable!(), | 237 | Assist::Unresolved { .. } => unreachable!(), |
274 | Assist::Resolved(labels_actions) => labels_actions, | 238 | Assist::Resolved { action, .. } => action, |
275 | }; | 239 | }; |
276 | 240 | ||
277 | let (_, action) = labels_actions.get(index).expect("expect assist action at index"); | ||
278 | let range = action.target.expect("expected target on action"); | 241 | let range = action.target.expect("expected target on action"); |
279 | assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); | 242 | assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); |
280 | } | 243 | } |