aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists')
-rw-r--r--crates/ra_assists/src/handlers/introduce_variable.rs60
-rw-r--r--crates/ra_assists/src/lib.rs114
2 files changed, 73 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)> {
136mod tests { 136mod 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 "
150fn foo() { 148fn 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 "
176fn foo() { 171fn 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 "
187fn foo() { 182fn 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 "
204fn foo() { 199fn 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 "
221fn foo() { 216fn 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 "
233fn foo() { 228fn 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 "
249fn main() { 244fn 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 "
274fn main() { 269fn 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 "
306fn main() { 301fn 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 "
323fn main() { 318fn 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 "
340fn main() { 335fn 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 "
358fn main() { 353fn 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 "
376fn foo() -> u32 { 371fn 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 "
394fn foo() -> u32 { 389fn 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 "
413fn foo() -> u32 { 408fn 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 "
430fn foo() -> u32 { 425fn 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 "
458fn main() { 453fn 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 "
480fn main() { 475fn 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 "
518fn main() { 506fn 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