diff options
-rw-r--r-- | crates/ra_assists/src/handlers/introduce_variable.rs | 60 | ||||
-rw-r--r-- | crates/ra_assists/src/lib.rs | 114 | ||||
-rw-r--r-- | crates/test_utils/src/lib.rs | 1 |
3 files changed, 74 insertions, 101 deletions
diff --git a/crates/ra_assists/src/handlers/introduce_variable.rs b/crates/ra_assists/src/handlers/introduce_variable.rs index 7312ce687..b453c51fb 100644 --- a/crates/ra_assists/src/handlers/introduce_variable.rs +++ b/crates/ra_assists/src/handlers/introduce_variable.rs | |||
@@ -136,15 +136,13 @@ fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> { | |||
136 | mod tests { | 136 | mod tests { |
137 | use test_utils::covers; | 137 | use test_utils::covers; |
138 | 138 | ||
139 | use crate::helpers::{ | 139 | use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; |
140 | check_assist_range, check_assist_range_not_applicable, check_assist_range_target, | ||
141 | }; | ||
142 | 140 | ||
143 | use super::*; | 141 | use super::*; |
144 | 142 | ||
145 | #[test] | 143 | #[test] |
146 | fn test_introduce_var_simple() { | 144 | fn test_introduce_var_simple() { |
147 | check_assist_range( | 145 | check_assist( |
148 | introduce_variable, | 146 | introduce_variable, |
149 | " | 147 | " |
150 | fn foo() { | 148 | fn foo() { |
@@ -161,16 +159,13 @@ fn foo() { | |||
161 | #[test] | 159 | #[test] |
162 | fn introduce_var_in_comment_is_not_applicable() { | 160 | fn introduce_var_in_comment_is_not_applicable() { |
163 | covers!(introduce_var_in_comment_is_not_applicable); | 161 | covers!(introduce_var_in_comment_is_not_applicable); |
164 | check_assist_range_not_applicable( | 162 | check_assist_not_applicable(introduce_variable, "fn main() { 1 + /* <|>comment<|> */ 1; }"); |
165 | introduce_variable, | ||
166 | "fn main() { 1 + /* <|>comment<|> */ 1; }", | ||
167 | ); | ||
168 | } | 163 | } |
169 | 164 | ||
170 | #[test] | 165 | #[test] |
171 | fn test_introduce_var_expr_stmt() { | 166 | fn test_introduce_var_expr_stmt() { |
172 | covers!(test_introduce_var_expr_stmt); | 167 | covers!(test_introduce_var_expr_stmt); |
173 | check_assist_range( | 168 | check_assist( |
174 | introduce_variable, | 169 | introduce_variable, |
175 | " | 170 | " |
176 | fn foo() { | 171 | fn foo() { |
@@ -181,7 +176,7 @@ fn foo() { | |||
181 | let <|>var_name = 1 + 1; | 176 | let <|>var_name = 1 + 1; |
182 | }", | 177 | }", |
183 | ); | 178 | ); |
184 | check_assist_range( | 179 | check_assist( |
185 | introduce_variable, | 180 | introduce_variable, |
186 | " | 181 | " |
187 | fn foo() { | 182 | fn foo() { |
@@ -198,7 +193,7 @@ fn foo() { | |||
198 | 193 | ||
199 | #[test] | 194 | #[test] |
200 | fn test_introduce_var_part_of_expr_stmt() { | 195 | fn test_introduce_var_part_of_expr_stmt() { |
201 | check_assist_range( | 196 | check_assist( |
202 | introduce_variable, | 197 | introduce_variable, |
203 | " | 198 | " |
204 | fn foo() { | 199 | fn foo() { |
@@ -215,7 +210,7 @@ fn foo() { | |||
215 | #[test] | 210 | #[test] |
216 | fn test_introduce_var_last_expr() { | 211 | fn test_introduce_var_last_expr() { |
217 | covers!(test_introduce_var_last_expr); | 212 | covers!(test_introduce_var_last_expr); |
218 | check_assist_range( | 213 | check_assist( |
219 | introduce_variable, | 214 | introduce_variable, |
220 | " | 215 | " |
221 | fn foo() { | 216 | fn foo() { |
@@ -227,7 +222,7 @@ fn foo() { | |||
227 | bar(var_name) | 222 | bar(var_name) |
228 | }", | 223 | }", |
229 | ); | 224 | ); |
230 | check_assist_range( | 225 | check_assist( |
231 | introduce_variable, | 226 | introduce_variable, |
232 | " | 227 | " |
233 | fn foo() { | 228 | fn foo() { |
@@ -243,7 +238,7 @@ fn foo() { | |||
243 | 238 | ||
244 | #[test] | 239 | #[test] |
245 | fn test_introduce_var_in_match_arm_no_block() { | 240 | fn test_introduce_var_in_match_arm_no_block() { |
246 | check_assist_range( | 241 | check_assist( |
247 | introduce_variable, | 242 | introduce_variable, |
248 | " | 243 | " |
249 | fn main() { | 244 | fn main() { |
@@ -268,7 +263,7 @@ fn main() { | |||
268 | 263 | ||
269 | #[test] | 264 | #[test] |
270 | fn test_introduce_var_in_match_arm_with_block() { | 265 | fn test_introduce_var_in_match_arm_with_block() { |
271 | check_assist_range( | 266 | check_assist( |
272 | introduce_variable, | 267 | introduce_variable, |
273 | " | 268 | " |
274 | fn main() { | 269 | fn main() { |
@@ -300,7 +295,7 @@ fn main() { | |||
300 | 295 | ||
301 | #[test] | 296 | #[test] |
302 | fn test_introduce_var_in_closure_no_block() { | 297 | fn test_introduce_var_in_closure_no_block() { |
303 | check_assist_range( | 298 | check_assist( |
304 | introduce_variable, | 299 | introduce_variable, |
305 | " | 300 | " |
306 | fn main() { | 301 | fn main() { |
@@ -317,7 +312,7 @@ fn main() { | |||
317 | 312 | ||
318 | #[test] | 313 | #[test] |
319 | fn test_introduce_var_in_closure_with_block() { | 314 | fn test_introduce_var_in_closure_with_block() { |
320 | check_assist_range( | 315 | check_assist( |
321 | introduce_variable, | 316 | introduce_variable, |
322 | " | 317 | " |
323 | fn main() { | 318 | fn main() { |
@@ -334,7 +329,7 @@ fn main() { | |||
334 | 329 | ||
335 | #[test] | 330 | #[test] |
336 | fn test_introduce_var_path_simple() { | 331 | fn test_introduce_var_path_simple() { |
337 | check_assist_range( | 332 | check_assist( |
338 | introduce_variable, | 333 | introduce_variable, |
339 | " | 334 | " |
340 | fn main() { | 335 | fn main() { |
@@ -352,7 +347,7 @@ fn main() { | |||
352 | 347 | ||
353 | #[test] | 348 | #[test] |
354 | fn test_introduce_var_path_method() { | 349 | fn test_introduce_var_path_method() { |
355 | check_assist_range( | 350 | check_assist( |
356 | introduce_variable, | 351 | introduce_variable, |
357 | " | 352 | " |
358 | fn main() { | 353 | fn main() { |
@@ -370,7 +365,7 @@ fn main() { | |||
370 | 365 | ||
371 | #[test] | 366 | #[test] |
372 | fn test_introduce_var_return() { | 367 | fn test_introduce_var_return() { |
373 | check_assist_range( | 368 | check_assist( |
374 | introduce_variable, | 369 | introduce_variable, |
375 | " | 370 | " |
376 | fn foo() -> u32 { | 371 | fn foo() -> u32 { |
@@ -388,7 +383,7 @@ fn foo() -> u32 { | |||
388 | 383 | ||
389 | #[test] | 384 | #[test] |
390 | fn test_introduce_var_does_not_add_extra_whitespace() { | 385 | fn test_introduce_var_does_not_add_extra_whitespace() { |
391 | check_assist_range( | 386 | check_assist( |
392 | introduce_variable, | 387 | introduce_variable, |
393 | " | 388 | " |
394 | fn foo() -> u32 { | 389 | fn foo() -> u32 { |
@@ -407,7 +402,7 @@ fn foo() -> u32 { | |||
407 | ", | 402 | ", |
408 | ); | 403 | ); |
409 | 404 | ||
410 | check_assist_range( | 405 | check_assist( |
411 | introduce_variable, | 406 | introduce_variable, |
412 | " | 407 | " |
413 | fn foo() -> u32 { | 408 | fn foo() -> u32 { |
@@ -424,7 +419,7 @@ fn foo() -> u32 { | |||
424 | ", | 419 | ", |
425 | ); | 420 | ); |
426 | 421 | ||
427 | check_assist_range( | 422 | check_assist( |
428 | introduce_variable, | 423 | introduce_variable, |
429 | " | 424 | " |
430 | fn foo() -> u32 { | 425 | fn foo() -> u32 { |
@@ -452,7 +447,7 @@ fn foo() -> u32 { | |||
452 | 447 | ||
453 | #[test] | 448 | #[test] |
454 | fn test_introduce_var_break() { | 449 | fn test_introduce_var_break() { |
455 | check_assist_range( | 450 | check_assist( |
456 | introduce_variable, | 451 | introduce_variable, |
457 | " | 452 | " |
458 | fn main() { | 453 | fn main() { |
@@ -474,7 +469,7 @@ fn main() { | |||
474 | 469 | ||
475 | #[test] | 470 | #[test] |
476 | fn test_introduce_var_for_cast() { | 471 | fn test_introduce_var_for_cast() { |
477 | check_assist_range( | 472 | check_assist( |
478 | introduce_variable, | 473 | introduce_variable, |
479 | " | 474 | " |
480 | fn main() { | 475 | fn main() { |
@@ -492,27 +487,20 @@ fn main() { | |||
492 | 487 | ||
493 | #[test] | 488 | #[test] |
494 | fn test_introduce_var_for_return_not_applicable() { | 489 | fn test_introduce_var_for_return_not_applicable() { |
495 | check_assist_range_not_applicable(introduce_variable, "fn foo() { <|>return<|>; } "); | 490 | check_assist_not_applicable(introduce_variable, "fn foo() { <|>return<|>; } "); |
496 | } | 491 | } |
497 | 492 | ||
498 | #[test] | 493 | #[test] |
499 | fn test_introduce_var_for_break_not_applicable() { | 494 | fn test_introduce_var_for_break_not_applicable() { |
500 | check_assist_range_not_applicable( | 495 | check_assist_not_applicable(introduce_variable, "fn main() { loop { <|>break<|>; }; }"); |
501 | introduce_variable, | ||
502 | "fn main() { loop { <|>break<|>; }; }", | ||
503 | ); | ||
504 | } | 496 | } |
505 | 497 | ||
506 | // FIXME: This is not quite correct, but good enough(tm) for the sorting heuristic | 498 | // FIXME: This is not quite correct, but good enough(tm) for the sorting heuristic |
507 | #[test] | 499 | #[test] |
508 | fn introduce_var_target() { | 500 | fn introduce_var_target() { |
509 | check_assist_range_target( | 501 | check_assist_target(introduce_variable, "fn foo() -> u32 { <|>return 2 + 2<|>; }", "2 + 2"); |
510 | introduce_variable, | ||
511 | "fn foo() -> u32 { <|>return 2 + 2<|>; }", | ||
512 | "2 + 2", | ||
513 | ); | ||
514 | 502 | ||
515 | check_assist_range_target( | 503 | check_assist_target( |
516 | introduce_variable, | 504 | introduce_variable, |
517 | " | 505 | " |
518 | fn main() { | 506 | fn main() { |
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index d7998b0d1..79fe43aa4 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -162,7 +162,7 @@ mod helpers { | |||
162 | use ra_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}; | 162 | use ra_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}; |
163 | use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase}; | 163 | use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase}; |
164 | use ra_syntax::TextRange; | 164 | use ra_syntax::TextRange; |
165 | use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range}; | 165 | use test_utils::{add_cursor, assert_eq_text, extract_range_or_offset, RangeOrOffset}; |
166 | 166 | ||
167 | use crate::{AssistCtx, AssistHandler}; | 167 | use crate::{AssistCtx, AssistHandler}; |
168 | 168 | ||
@@ -176,81 +176,65 @@ mod helpers { | |||
176 | } | 176 | } |
177 | 177 | ||
178 | pub(crate) fn check_assist(assist: AssistHandler, before: &str, after: &str) { | 178 | pub(crate) fn check_assist(assist: AssistHandler, before: &str, after: &str) { |
179 | let (before_cursor_pos, before) = extract_offset(before); | 179 | check(assist, before, ExpectedResult::After(after)); |
180 | let (db, file_id) = with_single_file(&before); | ||
181 | let frange = | ||
182 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; | ||
183 | let assist = | ||
184 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); | ||
185 | let action = assist.0[0].action.clone().unwrap(); | ||
186 | |||
187 | let actual = action.edit.apply(&before); | ||
188 | let actual_cursor_pos = match action.cursor_position { | ||
189 | None => action | ||
190 | .edit | ||
191 | .apply_to_offset(before_cursor_pos) | ||
192 | .expect("cursor position is affected by the edit"), | ||
193 | Some(off) => off, | ||
194 | }; | ||
195 | let actual = add_cursor(&actual, actual_cursor_pos); | ||
196 | assert_eq_text!(after, &actual); | ||
197 | } | ||
198 | |||
199 | pub(crate) fn check_assist_range(assist: AssistHandler, before: &str, after: &str) { | ||
200 | let (range, before) = extract_range(before); | ||
201 | let (db, file_id) = with_single_file(&before); | ||
202 | let frange = FileRange { file_id, range }; | ||
203 | let assist = | ||
204 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); | ||
205 | let action = assist.0[0].action.clone().unwrap(); | ||
206 | |||
207 | let mut actual = action.edit.apply(&before); | ||
208 | if let Some(pos) = action.cursor_position { | ||
209 | actual = add_cursor(&actual, pos); | ||
210 | } | ||
211 | assert_eq_text!(after, &actual); | ||
212 | } | 180 | } |
213 | 181 | ||
182 | // FIXME: instead of having a separate function here, maybe use | ||
183 | // `extract_ranges` and mark the target as `<target> </target>` in the | ||
184 | // fixuture? | ||
214 | pub(crate) fn check_assist_target(assist: AssistHandler, before: &str, target: &str) { | 185 | pub(crate) fn check_assist_target(assist: AssistHandler, before: &str, target: &str) { |
215 | let (before_cursor_pos, before) = extract_offset(before); | 186 | check(assist, before, ExpectedResult::Target(target)); |
216 | let (db, file_id) = with_single_file(&before); | ||
217 | let frange = | ||
218 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; | ||
219 | let assist = | ||
220 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); | ||
221 | let action = assist.0[0].action.clone().unwrap(); | ||
222 | |||
223 | let range = action.target.expect("expected target on action"); | ||
224 | assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); | ||
225 | } | 187 | } |
226 | 188 | ||
227 | pub(crate) fn check_assist_range_target(assist: AssistHandler, before: &str, target: &str) { | 189 | pub(crate) fn check_assist_not_applicable(assist: AssistHandler, before: &str) { |
228 | let (range, before) = extract_range(before); | 190 | check(assist, before, ExpectedResult::NotApplicable); |
229 | let (db, file_id) = with_single_file(&before); | ||
230 | let frange = FileRange { file_id, range }; | ||
231 | let assist = | ||
232 | assist(AssistCtx::new(&db, frange, true)).expect("code action is not applicable"); | ||
233 | let action = assist.0[0].action.clone().unwrap(); | ||
234 | |||
235 | let range = action.target.expect("expected target on action"); | ||
236 | assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); | ||
237 | } | 191 | } |
238 | 192 | ||
239 | pub(crate) fn check_assist_not_applicable(assist: AssistHandler, before: &str) { | 193 | enum ExpectedResult<'a> { |
240 | let (before_cursor_pos, before) = extract_offset(before); | 194 | NotApplicable, |
241 | let (db, file_id) = with_single_file(&before); | 195 | After(&'a str), |
242 | let frange = | 196 | Target(&'a str), |
243 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; | ||
244 | let assist = assist(AssistCtx::new(&db, frange, true)); | ||
245 | assert!(assist.is_none()); | ||
246 | } | 197 | } |
247 | 198 | ||
248 | pub(crate) fn check_assist_range_not_applicable(assist: AssistHandler, before: &str) { | 199 | fn check(assist: AssistHandler, before: &str, expected: ExpectedResult) { |
249 | let (range, before) = extract_range(before); | 200 | let (range_or_offset, before) = extract_range_or_offset(before); |
201 | let range: TextRange = range_or_offset.into(); | ||
202 | |||
250 | let (db, file_id) = with_single_file(&before); | 203 | let (db, file_id) = with_single_file(&before); |
251 | let frange = FileRange { file_id, range }; | 204 | let frange = FileRange { file_id, range }; |
252 | let assist = assist(AssistCtx::new(&db, frange, true)); | 205 | let assist_ctx = AssistCtx::new(&db, frange, true); |
253 | assert!(assist.is_none()); | 206 | |
207 | match (assist(assist_ctx), expected) { | ||
208 | (Some(assist), ExpectedResult::After(after)) => { | ||
209 | let action = assist.0[0].action.clone().unwrap(); | ||
210 | |||
211 | let mut actual = action.edit.apply(&before); | ||
212 | match action.cursor_position { | ||
213 | None => { | ||
214 | if let RangeOrOffset::Offset(before_cursor_pos) = range_or_offset { | ||
215 | let off = action | ||
216 | .edit | ||
217 | .apply_to_offset(before_cursor_pos) | ||
218 | .expect("cursor position is affected by the edit"); | ||
219 | actual = add_cursor(&actual, off) | ||
220 | } | ||
221 | } | ||
222 | Some(off) => actual = add_cursor(&actual, off), | ||
223 | }; | ||
224 | |||
225 | assert_eq_text!(after, &actual); | ||
226 | } | ||
227 | (Some(assist), ExpectedResult::Target(target)) => { | ||
228 | let action = assist.0[0].action.clone().unwrap(); | ||
229 | let range = action.target.expect("expected target on action"); | ||
230 | assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target); | ||
231 | } | ||
232 | (Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"), | ||
233 | (None, ExpectedResult::After(_)) | (None, ExpectedResult::Target(_)) => { | ||
234 | panic!("code action is not applicable") | ||
235 | } | ||
236 | (None, ExpectedResult::NotApplicable) => (), | ||
237 | }; | ||
254 | } | 238 | } |
255 | } | 239 | } |
256 | 240 | ||
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index e6e8d7110..69deddcb5 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs | |||
@@ -83,6 +83,7 @@ fn try_extract_range(text: &str) -> Option<(TextRange, String)> { | |||
83 | Some((TextRange::from_to(start, end), text)) | 83 | Some((TextRange::from_to(start, end), text)) |
84 | } | 84 | } |
85 | 85 | ||
86 | #[derive(Clone, Copy)] | ||
86 | pub enum RangeOrOffset { | 87 | pub enum RangeOrOffset { |
87 | Range(TextRange), | 88 | Range(TextRange), |
88 | Offset(TextUnit), | 89 | Offset(TextUnit), |