diff options
Diffstat (limited to 'crates/assists/src/handlers/inline_local_variable.rs')
-rw-r--r-- | crates/assists/src/handlers/inline_local_variable.rs | 724 |
1 files changed, 0 insertions, 724 deletions
diff --git a/crates/assists/src/handlers/inline_local_variable.rs b/crates/assists/src/handlers/inline_local_variable.rs deleted file mode 100644 index 0e63a60e8..000000000 --- a/crates/assists/src/handlers/inline_local_variable.rs +++ /dev/null | |||
@@ -1,724 +0,0 @@ | |||
1 | use ide_db::{ | ||
2 | defs::Definition, | ||
3 | search::{FileReference, ReferenceKind}, | ||
4 | }; | ||
5 | use syntax::{ | ||
6 | ast::{self, AstNode, AstToken}, | ||
7 | TextRange, | ||
8 | }; | ||
9 | use test_utils::mark; | ||
10 | |||
11 | use crate::{ | ||
12 | assist_context::{AssistContext, Assists}, | ||
13 | AssistId, AssistKind, | ||
14 | }; | ||
15 | |||
16 | // Assist: inline_local_variable | ||
17 | // | ||
18 | // Inlines local variable. | ||
19 | // | ||
20 | // ``` | ||
21 | // fn main() { | ||
22 | // let x$0 = 1 + 2; | ||
23 | // x * 4; | ||
24 | // } | ||
25 | // ``` | ||
26 | // -> | ||
27 | // ``` | ||
28 | // fn main() { | ||
29 | // (1 + 2) * 4; | ||
30 | // } | ||
31 | // ``` | ||
32 | pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | ||
33 | let let_stmt = ctx.find_node_at_offset::<ast::LetStmt>()?; | ||
34 | let bind_pat = match let_stmt.pat()? { | ||
35 | ast::Pat::IdentPat(pat) => pat, | ||
36 | _ => return None, | ||
37 | }; | ||
38 | if bind_pat.mut_token().is_some() { | ||
39 | mark::hit!(test_not_inline_mut_variable); | ||
40 | return None; | ||
41 | } | ||
42 | if !bind_pat.syntax().text_range().contains_inclusive(ctx.offset()) { | ||
43 | mark::hit!(not_applicable_outside_of_bind_pat); | ||
44 | return None; | ||
45 | } | ||
46 | let initializer_expr = let_stmt.initializer()?; | ||
47 | |||
48 | let def = ctx.sema.to_def(&bind_pat)?; | ||
49 | let def = Definition::Local(def); | ||
50 | let usages = def.usages(&ctx.sema).all(); | ||
51 | if usages.is_empty() { | ||
52 | mark::hit!(test_not_applicable_if_variable_unused); | ||
53 | return None; | ||
54 | }; | ||
55 | |||
56 | let delete_range = if let Some(whitespace) = let_stmt | ||
57 | .syntax() | ||
58 | .next_sibling_or_token() | ||
59 | .and_then(|it| ast::Whitespace::cast(it.as_token()?.clone())) | ||
60 | { | ||
61 | TextRange::new( | ||
62 | let_stmt.syntax().text_range().start(), | ||
63 | whitespace.syntax().text_range().end(), | ||
64 | ) | ||
65 | } else { | ||
66 | let_stmt.syntax().text_range() | ||
67 | }; | ||
68 | |||
69 | let wrap_in_parens = usages | ||
70 | .references | ||
71 | .values() | ||
72 | .flatten() | ||
73 | .map(|&FileReference { range, .. }| { | ||
74 | let usage_node = | ||
75 | ctx.covering_node_for_range(range).ancestors().find_map(ast::PathExpr::cast)?; | ||
76 | let usage_parent_option = usage_node.syntax().parent().and_then(ast::Expr::cast); | ||
77 | let usage_parent = match usage_parent_option { | ||
78 | Some(u) => u, | ||
79 | None => return Ok(false), | ||
80 | }; | ||
81 | |||
82 | Ok(!matches!( | ||
83 | (&initializer_expr, usage_parent), | ||
84 | (ast::Expr::CallExpr(_), _) | ||
85 | | (ast::Expr::IndexExpr(_), _) | ||
86 | | (ast::Expr::MethodCallExpr(_), _) | ||
87 | | (ast::Expr::FieldExpr(_), _) | ||
88 | | (ast::Expr::TryExpr(_), _) | ||
89 | | (ast::Expr::RefExpr(_), _) | ||
90 | | (ast::Expr::Literal(_), _) | ||
91 | | (ast::Expr::TupleExpr(_), _) | ||
92 | | (ast::Expr::ArrayExpr(_), _) | ||
93 | | (ast::Expr::ParenExpr(_), _) | ||
94 | | (ast::Expr::PathExpr(_), _) | ||
95 | | (ast::Expr::BlockExpr(_), _) | ||
96 | | (ast::Expr::EffectExpr(_), _) | ||
97 | | (_, ast::Expr::CallExpr(_)) | ||
98 | | (_, ast::Expr::TupleExpr(_)) | ||
99 | | (_, ast::Expr::ArrayExpr(_)) | ||
100 | | (_, ast::Expr::ParenExpr(_)) | ||
101 | | (_, ast::Expr::ForExpr(_)) | ||
102 | | (_, ast::Expr::WhileExpr(_)) | ||
103 | | (_, ast::Expr::BreakExpr(_)) | ||
104 | | (_, ast::Expr::ReturnExpr(_)) | ||
105 | | (_, ast::Expr::MatchExpr(_)) | ||
106 | )) | ||
107 | }) | ||
108 | .collect::<Result<Vec<_>, _>>()?; | ||
109 | |||
110 | let init_str = initializer_expr.syntax().text().to_string(); | ||
111 | let init_in_paren = format!("({})", &init_str); | ||
112 | |||
113 | let target = bind_pat.syntax().text_range(); | ||
114 | acc.add( | ||
115 | AssistId("inline_local_variable", AssistKind::RefactorInline), | ||
116 | "Inline variable", | ||
117 | target, | ||
118 | move |builder| { | ||
119 | builder.delete(delete_range); | ||
120 | for (reference, should_wrap) in usages.references.values().flatten().zip(wrap_in_parens) | ||
121 | { | ||
122 | let replacement = | ||
123 | if should_wrap { init_in_paren.clone() } else { init_str.clone() }; | ||
124 | match reference.kind { | ||
125 | ReferenceKind::FieldShorthandForLocal => { | ||
126 | mark::hit!(inline_field_shorthand); | ||
127 | builder.insert(reference.range.end(), format!(": {}", replacement)) | ||
128 | } | ||
129 | _ => builder.replace(reference.range, replacement), | ||
130 | } | ||
131 | } | ||
132 | }, | ||
133 | ) | ||
134 | } | ||
135 | |||
136 | #[cfg(test)] | ||
137 | mod tests { | ||
138 | use test_utils::mark; | ||
139 | |||
140 | use crate::tests::{check_assist, check_assist_not_applicable}; | ||
141 | |||
142 | use super::*; | ||
143 | |||
144 | #[test] | ||
145 | fn test_inline_let_bind_literal_expr() { | ||
146 | check_assist( | ||
147 | inline_local_variable, | ||
148 | r" | ||
149 | fn bar(a: usize) {} | ||
150 | fn foo() { | ||
151 | let a$0 = 1; | ||
152 | a + 1; | ||
153 | if a > 10 { | ||
154 | } | ||
155 | |||
156 | while a > 10 { | ||
157 | |||
158 | } | ||
159 | let b = a * 10; | ||
160 | bar(a); | ||
161 | }", | ||
162 | r" | ||
163 | fn bar(a: usize) {} | ||
164 | fn foo() { | ||
165 | 1 + 1; | ||
166 | if 1 > 10 { | ||
167 | } | ||
168 | |||
169 | while 1 > 10 { | ||
170 | |||
171 | } | ||
172 | let b = 1 * 10; | ||
173 | bar(1); | ||
174 | }", | ||
175 | ); | ||
176 | } | ||
177 | |||
178 | #[test] | ||
179 | fn test_inline_let_bind_bin_expr() { | ||
180 | check_assist( | ||
181 | inline_local_variable, | ||
182 | r" | ||
183 | fn bar(a: usize) {} | ||
184 | fn foo() { | ||
185 | let a$0 = 1 + 1; | ||
186 | a + 1; | ||
187 | if a > 10 { | ||
188 | } | ||
189 | |||
190 | while a > 10 { | ||
191 | |||
192 | } | ||
193 | let b = a * 10; | ||
194 | bar(a); | ||
195 | }", | ||
196 | r" | ||
197 | fn bar(a: usize) {} | ||
198 | fn foo() { | ||
199 | (1 + 1) + 1; | ||
200 | if (1 + 1) > 10 { | ||
201 | } | ||
202 | |||
203 | while (1 + 1) > 10 { | ||
204 | |||
205 | } | ||
206 | let b = (1 + 1) * 10; | ||
207 | bar(1 + 1); | ||
208 | }", | ||
209 | ); | ||
210 | } | ||
211 | |||
212 | #[test] | ||
213 | fn test_inline_let_bind_function_call_expr() { | ||
214 | check_assist( | ||
215 | inline_local_variable, | ||
216 | r" | ||
217 | fn bar(a: usize) {} | ||
218 | fn foo() { | ||
219 | let a$0 = bar(1); | ||
220 | a + 1; | ||
221 | if a > 10 { | ||
222 | } | ||
223 | |||
224 | while a > 10 { | ||
225 | |||
226 | } | ||
227 | let b = a * 10; | ||
228 | bar(a); | ||
229 | }", | ||
230 | r" | ||
231 | fn bar(a: usize) {} | ||
232 | fn foo() { | ||
233 | bar(1) + 1; | ||
234 | if bar(1) > 10 { | ||
235 | } | ||
236 | |||
237 | while bar(1) > 10 { | ||
238 | |||
239 | } | ||
240 | let b = bar(1) * 10; | ||
241 | bar(bar(1)); | ||
242 | }", | ||
243 | ); | ||
244 | } | ||
245 | |||
246 | #[test] | ||
247 | fn test_inline_let_bind_cast_expr() { | ||
248 | check_assist( | ||
249 | inline_local_variable, | ||
250 | r" | ||
251 | fn bar(a: usize): usize { a } | ||
252 | fn foo() { | ||
253 | let a$0 = bar(1) as u64; | ||
254 | a + 1; | ||
255 | if a > 10 { | ||
256 | } | ||
257 | |||
258 | while a > 10 { | ||
259 | |||
260 | } | ||
261 | let b = a * 10; | ||
262 | bar(a); | ||
263 | }", | ||
264 | r" | ||
265 | fn bar(a: usize): usize { a } | ||
266 | fn foo() { | ||
267 | (bar(1) as u64) + 1; | ||
268 | if (bar(1) as u64) > 10 { | ||
269 | } | ||
270 | |||
271 | while (bar(1) as u64) > 10 { | ||
272 | |||
273 | } | ||
274 | let b = (bar(1) as u64) * 10; | ||
275 | bar(bar(1) as u64); | ||
276 | }", | ||
277 | ); | ||
278 | } | ||
279 | |||
280 | #[test] | ||
281 | fn test_inline_let_bind_block_expr() { | ||
282 | check_assist( | ||
283 | inline_local_variable, | ||
284 | r" | ||
285 | fn foo() { | ||
286 | let a$0 = { 10 + 1 }; | ||
287 | a + 1; | ||
288 | if a > 10 { | ||
289 | } | ||
290 | |||
291 | while a > 10 { | ||
292 | |||
293 | } | ||
294 | let b = a * 10; | ||
295 | bar(a); | ||
296 | }", | ||
297 | r" | ||
298 | fn foo() { | ||
299 | { 10 + 1 } + 1; | ||
300 | if { 10 + 1 } > 10 { | ||
301 | } | ||
302 | |||
303 | while { 10 + 1 } > 10 { | ||
304 | |||
305 | } | ||
306 | let b = { 10 + 1 } * 10; | ||
307 | bar({ 10 + 1 }); | ||
308 | }", | ||
309 | ); | ||
310 | } | ||
311 | |||
312 | #[test] | ||
313 | fn test_inline_let_bind_paren_expr() { | ||
314 | check_assist( | ||
315 | inline_local_variable, | ||
316 | r" | ||
317 | fn foo() { | ||
318 | let a$0 = ( 10 + 1 ); | ||
319 | a + 1; | ||
320 | if a > 10 { | ||
321 | } | ||
322 | |||
323 | while a > 10 { | ||
324 | |||
325 | } | ||
326 | let b = a * 10; | ||
327 | bar(a); | ||
328 | }", | ||
329 | r" | ||
330 | fn foo() { | ||
331 | ( 10 + 1 ) + 1; | ||
332 | if ( 10 + 1 ) > 10 { | ||
333 | } | ||
334 | |||
335 | while ( 10 + 1 ) > 10 { | ||
336 | |||
337 | } | ||
338 | let b = ( 10 + 1 ) * 10; | ||
339 | bar(( 10 + 1 )); | ||
340 | }", | ||
341 | ); | ||
342 | } | ||
343 | |||
344 | #[test] | ||
345 | fn test_not_inline_mut_variable() { | ||
346 | mark::check!(test_not_inline_mut_variable); | ||
347 | check_assist_not_applicable( | ||
348 | inline_local_variable, | ||
349 | r" | ||
350 | fn foo() { | ||
351 | let mut a$0 = 1 + 1; | ||
352 | a + 1; | ||
353 | }", | ||
354 | ); | ||
355 | } | ||
356 | |||
357 | #[test] | ||
358 | fn test_call_expr() { | ||
359 | check_assist( | ||
360 | inline_local_variable, | ||
361 | r" | ||
362 | fn foo() { | ||
363 | let a$0 = bar(10 + 1); | ||
364 | let b = a * 10; | ||
365 | let c = a as usize; | ||
366 | }", | ||
367 | r" | ||
368 | fn foo() { | ||
369 | let b = bar(10 + 1) * 10; | ||
370 | let c = bar(10 + 1) as usize; | ||
371 | }", | ||
372 | ); | ||
373 | } | ||
374 | |||
375 | #[test] | ||
376 | fn test_index_expr() { | ||
377 | check_assist( | ||
378 | inline_local_variable, | ||
379 | r" | ||
380 | fn foo() { | ||
381 | let x = vec![1, 2, 3]; | ||
382 | let a$0 = x[0]; | ||
383 | let b = a * 10; | ||
384 | let c = a as usize; | ||
385 | }", | ||
386 | r" | ||
387 | fn foo() { | ||
388 | let x = vec![1, 2, 3]; | ||
389 | let b = x[0] * 10; | ||
390 | let c = x[0] as usize; | ||
391 | }", | ||
392 | ); | ||
393 | } | ||
394 | |||
395 | #[test] | ||
396 | fn test_method_call_expr() { | ||
397 | check_assist( | ||
398 | inline_local_variable, | ||
399 | r" | ||
400 | fn foo() { | ||
401 | let bar = vec![1]; | ||
402 | let a$0 = bar.len(); | ||
403 | let b = a * 10; | ||
404 | let c = a as usize; | ||
405 | }", | ||
406 | r" | ||
407 | fn foo() { | ||
408 | let bar = vec![1]; | ||
409 | let b = bar.len() * 10; | ||
410 | let c = bar.len() as usize; | ||
411 | }", | ||
412 | ); | ||
413 | } | ||
414 | |||
415 | #[test] | ||
416 | fn test_field_expr() { | ||
417 | check_assist( | ||
418 | inline_local_variable, | ||
419 | r" | ||
420 | struct Bar { | ||
421 | foo: usize | ||
422 | } | ||
423 | |||
424 | fn foo() { | ||
425 | let bar = Bar { foo: 1 }; | ||
426 | let a$0 = bar.foo; | ||
427 | let b = a * 10; | ||
428 | let c = a as usize; | ||
429 | }", | ||
430 | r" | ||
431 | struct Bar { | ||
432 | foo: usize | ||
433 | } | ||
434 | |||
435 | fn foo() { | ||
436 | let bar = Bar { foo: 1 }; | ||
437 | let b = bar.foo * 10; | ||
438 | let c = bar.foo as usize; | ||
439 | }", | ||
440 | ); | ||
441 | } | ||
442 | |||
443 | #[test] | ||
444 | fn test_try_expr() { | ||
445 | check_assist( | ||
446 | inline_local_variable, | ||
447 | r" | ||
448 | fn foo() -> Option<usize> { | ||
449 | let bar = Some(1); | ||
450 | let a$0 = bar?; | ||
451 | let b = a * 10; | ||
452 | let c = a as usize; | ||
453 | None | ||
454 | }", | ||
455 | r" | ||
456 | fn foo() -> Option<usize> { | ||
457 | let bar = Some(1); | ||
458 | let b = bar? * 10; | ||
459 | let c = bar? as usize; | ||
460 | None | ||
461 | }", | ||
462 | ); | ||
463 | } | ||
464 | |||
465 | #[test] | ||
466 | fn test_ref_expr() { | ||
467 | check_assist( | ||
468 | inline_local_variable, | ||
469 | r" | ||
470 | fn foo() { | ||
471 | let bar = 10; | ||
472 | let a$0 = &bar; | ||
473 | let b = a * 10; | ||
474 | }", | ||
475 | r" | ||
476 | fn foo() { | ||
477 | let bar = 10; | ||
478 | let b = &bar * 10; | ||
479 | }", | ||
480 | ); | ||
481 | } | ||
482 | |||
483 | #[test] | ||
484 | fn test_tuple_expr() { | ||
485 | check_assist( | ||
486 | inline_local_variable, | ||
487 | r" | ||
488 | fn foo() { | ||
489 | let a$0 = (10, 20); | ||
490 | let b = a[0]; | ||
491 | }", | ||
492 | r" | ||
493 | fn foo() { | ||
494 | let b = (10, 20)[0]; | ||
495 | }", | ||
496 | ); | ||
497 | } | ||
498 | |||
499 | #[test] | ||
500 | fn test_array_expr() { | ||
501 | check_assist( | ||
502 | inline_local_variable, | ||
503 | r" | ||
504 | fn foo() { | ||
505 | let a$0 = [1, 2, 3]; | ||
506 | let b = a.len(); | ||
507 | }", | ||
508 | r" | ||
509 | fn foo() { | ||
510 | let b = [1, 2, 3].len(); | ||
511 | }", | ||
512 | ); | ||
513 | } | ||
514 | |||
515 | #[test] | ||
516 | fn test_paren() { | ||
517 | check_assist( | ||
518 | inline_local_variable, | ||
519 | r" | ||
520 | fn foo() { | ||
521 | let a$0 = (10 + 20); | ||
522 | let b = a * 10; | ||
523 | let c = a as usize; | ||
524 | }", | ||
525 | r" | ||
526 | fn foo() { | ||
527 | let b = (10 + 20) * 10; | ||
528 | let c = (10 + 20) as usize; | ||
529 | }", | ||
530 | ); | ||
531 | } | ||
532 | |||
533 | #[test] | ||
534 | fn test_path_expr() { | ||
535 | check_assist( | ||
536 | inline_local_variable, | ||
537 | r" | ||
538 | fn foo() { | ||
539 | let d = 10; | ||
540 | let a$0 = d; | ||
541 | let b = a * 10; | ||
542 | let c = a as usize; | ||
543 | }", | ||
544 | r" | ||
545 | fn foo() { | ||
546 | let d = 10; | ||
547 | let b = d * 10; | ||
548 | let c = d as usize; | ||
549 | }", | ||
550 | ); | ||
551 | } | ||
552 | |||
553 | #[test] | ||
554 | fn test_block_expr() { | ||
555 | check_assist( | ||
556 | inline_local_variable, | ||
557 | r" | ||
558 | fn foo() { | ||
559 | let a$0 = { 10 }; | ||
560 | let b = a * 10; | ||
561 | let c = a as usize; | ||
562 | }", | ||
563 | r" | ||
564 | fn foo() { | ||
565 | let b = { 10 } * 10; | ||
566 | let c = { 10 } as usize; | ||
567 | }", | ||
568 | ); | ||
569 | } | ||
570 | |||
571 | #[test] | ||
572 | fn test_used_in_different_expr1() { | ||
573 | check_assist( | ||
574 | inline_local_variable, | ||
575 | r" | ||
576 | fn foo() { | ||
577 | let a$0 = 10 + 20; | ||
578 | let b = a * 10; | ||
579 | let c = (a, 20); | ||
580 | let d = [a, 10]; | ||
581 | let e = (a); | ||
582 | }", | ||
583 | r" | ||
584 | fn foo() { | ||
585 | let b = (10 + 20) * 10; | ||
586 | let c = (10 + 20, 20); | ||
587 | let d = [10 + 20, 10]; | ||
588 | let e = (10 + 20); | ||
589 | }", | ||
590 | ); | ||
591 | } | ||
592 | |||
593 | #[test] | ||
594 | fn test_used_in_for_expr() { | ||
595 | check_assist( | ||
596 | inline_local_variable, | ||
597 | r" | ||
598 | fn foo() { | ||
599 | let a$0 = vec![10, 20]; | ||
600 | for i in a {} | ||
601 | }", | ||
602 | r" | ||
603 | fn foo() { | ||
604 | for i in vec![10, 20] {} | ||
605 | }", | ||
606 | ); | ||
607 | } | ||
608 | |||
609 | #[test] | ||
610 | fn test_used_in_while_expr() { | ||
611 | check_assist( | ||
612 | inline_local_variable, | ||
613 | r" | ||
614 | fn foo() { | ||
615 | let a$0 = 1 > 0; | ||
616 | while a {} | ||
617 | }", | ||
618 | r" | ||
619 | fn foo() { | ||
620 | while 1 > 0 {} | ||
621 | }", | ||
622 | ); | ||
623 | } | ||
624 | |||
625 | #[test] | ||
626 | fn test_used_in_break_expr() { | ||
627 | check_assist( | ||
628 | inline_local_variable, | ||
629 | r" | ||
630 | fn foo() { | ||
631 | let a$0 = 1 + 1; | ||
632 | loop { | ||
633 | break a; | ||
634 | } | ||
635 | }", | ||
636 | r" | ||
637 | fn foo() { | ||
638 | loop { | ||
639 | break 1 + 1; | ||
640 | } | ||
641 | }", | ||
642 | ); | ||
643 | } | ||
644 | |||
645 | #[test] | ||
646 | fn test_used_in_return_expr() { | ||
647 | check_assist( | ||
648 | inline_local_variable, | ||
649 | r" | ||
650 | fn foo() { | ||
651 | let a$0 = 1 > 0; | ||
652 | return a; | ||
653 | }", | ||
654 | r" | ||
655 | fn foo() { | ||
656 | return 1 > 0; | ||
657 | }", | ||
658 | ); | ||
659 | } | ||
660 | |||
661 | #[test] | ||
662 | fn test_used_in_match_expr() { | ||
663 | check_assist( | ||
664 | inline_local_variable, | ||
665 | r" | ||
666 | fn foo() { | ||
667 | let a$0 = 1 > 0; | ||
668 | match a {} | ||
669 | }", | ||
670 | r" | ||
671 | fn foo() { | ||
672 | match 1 > 0 {} | ||
673 | }", | ||
674 | ); | ||
675 | } | ||
676 | |||
677 | #[test] | ||
678 | fn inline_field_shorthand() { | ||
679 | mark::check!(inline_field_shorthand); | ||
680 | check_assist( | ||
681 | inline_local_variable, | ||
682 | r" | ||
683 | struct S { foo: i32} | ||
684 | fn main() { | ||
685 | let $0foo = 92; | ||
686 | S { foo } | ||
687 | } | ||
688 | ", | ||
689 | r" | ||
690 | struct S { foo: i32} | ||
691 | fn main() { | ||
692 | S { foo: 92 } | ||
693 | } | ||
694 | ", | ||
695 | ); | ||
696 | } | ||
697 | |||
698 | #[test] | ||
699 | fn test_not_applicable_if_variable_unused() { | ||
700 | mark::check!(test_not_applicable_if_variable_unused); | ||
701 | check_assist_not_applicable( | ||
702 | inline_local_variable, | ||
703 | r" | ||
704 | fn foo() { | ||
705 | let $0a = 0; | ||
706 | } | ||
707 | ", | ||
708 | ) | ||
709 | } | ||
710 | |||
711 | #[test] | ||
712 | fn not_applicable_outside_of_bind_pat() { | ||
713 | mark::check!(not_applicable_outside_of_bind_pat); | ||
714 | check_assist_not_applicable( | ||
715 | inline_local_variable, | ||
716 | r" | ||
717 | fn main() { | ||
718 | let x = $01 + 2; | ||
719 | x * 4; | ||
720 | } | ||
721 | ", | ||
722 | ) | ||
723 | } | ||
724 | } | ||