diff options
Diffstat (limited to 'crates/ra_assists/src/inline_local_variable.rs')
-rw-r--r-- | crates/ra_assists/src/inline_local_variable.rs | 432 |
1 files changed, 386 insertions, 46 deletions
diff --git a/crates/ra_assists/src/inline_local_variable.rs b/crates/ra_assists/src/inline_local_variable.rs index bd3cdb970..950c2910b 100644 --- a/crates/ra_assists/src/inline_local_variable.rs +++ b/crates/ra_assists/src/inline_local_variable.rs | |||
@@ -1,7 +1,11 @@ | |||
1 | use hir::db::HirDatabase; | 1 | use hir::{ |
2 | use hir::source_binder::function_from_child_node; | 2 | db::HirDatabase, |
3 | use ra_syntax::{ast::{self, AstNode}, TextRange}; | 3 | source_binder::function_from_child_node, |
4 | use ra_syntax::ast::{PatKind, ExprKind}; | 4 | }; |
5 | use ra_syntax::{ | ||
6 | ast::{self, AstNode, AstToken, PatKind, ExprKind}, | ||
7 | TextRange, | ||
8 | }; | ||
5 | 9 | ||
6 | use crate::{Assist, AssistCtx, AssistId}; | 10 | use crate::{Assist, AssistCtx, AssistId}; |
7 | use crate::assist_ctx::AssistBuilder; | 11 | use crate::assist_ctx::AssistBuilder; |
@@ -15,61 +19,77 @@ pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Opt | |||
15 | if bind_pat.is_mutable() { | 19 | if bind_pat.is_mutable() { |
16 | return None; | 20 | return None; |
17 | } | 21 | } |
18 | let initializer = let_stmt.initializer()?; | 22 | let initializer_expr = let_stmt.initializer(); |
19 | let wrap_in_parens = match initializer.kind() { | 23 | let delete_range = if let Some(whitespace) = let_stmt |
20 | ExprKind::LambdaExpr(_) | 24 | .syntax() |
21 | | ExprKind::IfExpr(_) | 25 | .next_sibling_or_token() |
22 | | ExprKind::LoopExpr(_) | 26 | .and_then(|it| ast::Whitespace::cast(it.as_token()?)) |
23 | | ExprKind::ForExpr(_) | ||
24 | | ExprKind::WhileExpr(_) | ||
25 | | ExprKind::ContinueExpr(_) | ||
26 | | ExprKind::BreakExpr(_) | ||
27 | | ExprKind::Label(_) | ||
28 | | ExprKind::ReturnExpr(_) | ||
29 | | ExprKind::MatchExpr(_) | ||
30 | | ExprKind::StructLit(_) | ||
31 | | ExprKind::CastExpr(_) | ||
32 | | ExprKind::PrefixExpr(_) | ||
33 | | ExprKind::RangeExpr(_) | ||
34 | | ExprKind::BinExpr(_) => true, | ||
35 | ExprKind::CallExpr(_) | ||
36 | | ExprKind::IndexExpr(_) | ||
37 | | ExprKind::MethodCallExpr(_) | ||
38 | | ExprKind::FieldExpr(_) | ||
39 | | ExprKind::TryExpr(_) | ||
40 | | ExprKind::RefExpr(_) | ||
41 | | ExprKind::Literal(_) | ||
42 | | ExprKind::TupleExpr(_) | ||
43 | | ExprKind::ArrayExpr(_) | ||
44 | | ExprKind::ParenExpr(_) | ||
45 | | ExprKind::PathExpr(_) | ||
46 | | ExprKind::BlockExpr(_) => false, | ||
47 | }; | ||
48 | |||
49 | let delete_range = if let Some(whitespace) = | ||
50 | let_stmt.syntax().next_sibling().and_then(ast::Whitespace::cast) | ||
51 | { | 27 | { |
52 | TextRange::from_to(let_stmt.syntax().range().start(), whitespace.syntax().range().end()) | 28 | TextRange::from_to(let_stmt.syntax().range().start(), whitespace.syntax().range().end()) |
53 | } else { | 29 | } else { |
54 | let_stmt.syntax().range() | 30 | let_stmt.syntax().range() |
55 | }; | 31 | }; |
56 | 32 | ||
57 | let init_str = if wrap_in_parens { | ||
58 | format!("({})", initializer.syntax().text().to_string()) | ||
59 | } else { | ||
60 | initializer.syntax().text().to_string() | ||
61 | }; | ||
62 | let function = function_from_child_node(ctx.db, ctx.frange.file_id, bind_pat.syntax())?; | 33 | let function = function_from_child_node(ctx.db, ctx.frange.file_id, bind_pat.syntax())?; |
63 | let scope = function.scopes(ctx.db); | 34 | let scope = function.scopes(ctx.db); |
64 | let refs = scope.find_all_refs(bind_pat); | 35 | let refs = scope.find_all_refs(bind_pat); |
65 | 36 | ||
37 | let mut wrap_in_parens = vec![true; refs.len()]; | ||
38 | |||
39 | for (i, desc) in refs.iter().enumerate() { | ||
40 | let usage_node = ctx | ||
41 | .covering_node_for_range(desc.range) | ||
42 | .ancestors() | ||
43 | .find_map(|node| ast::PathExpr::cast(node))?; | ||
44 | let usage_parent_option = usage_node.syntax().parent().and_then(ast::Expr::cast); | ||
45 | let usage_parent = match usage_parent_option { | ||
46 | Some(u) => u, | ||
47 | None => { | ||
48 | wrap_in_parens[i] = false; | ||
49 | continue; | ||
50 | } | ||
51 | }; | ||
52 | |||
53 | wrap_in_parens[i] = match (initializer_expr?.kind(), usage_parent.kind()) { | ||
54 | (ExprKind::CallExpr(_), _) | ||
55 | | (ExprKind::IndexExpr(_), _) | ||
56 | | (ExprKind::MethodCallExpr(_), _) | ||
57 | | (ExprKind::FieldExpr(_), _) | ||
58 | | (ExprKind::TryExpr(_), _) | ||
59 | | (ExprKind::RefExpr(_), _) | ||
60 | | (ExprKind::Literal(_), _) | ||
61 | | (ExprKind::TupleExpr(_), _) | ||
62 | | (ExprKind::ArrayExpr(_), _) | ||
63 | | (ExprKind::ParenExpr(_), _) | ||
64 | | (ExprKind::PathExpr(_), _) | ||
65 | | (ExprKind::BlockExpr(_), _) | ||
66 | | (_, ExprKind::CallExpr(_)) | ||
67 | | (_, ExprKind::TupleExpr(_)) | ||
68 | | (_, ExprKind::ArrayExpr(_)) | ||
69 | | (_, ExprKind::ParenExpr(_)) | ||
70 | | (_, ExprKind::ForExpr(_)) | ||
71 | | (_, ExprKind::WhileExpr(_)) | ||
72 | | (_, ExprKind::BreakExpr(_)) | ||
73 | | (_, ExprKind::ReturnExpr(_)) | ||
74 | | (_, ExprKind::MatchExpr(_)) => false, | ||
75 | _ => true, | ||
76 | }; | ||
77 | } | ||
78 | |||
79 | let init_str = initializer_expr?.syntax().text().to_string(); | ||
80 | let init_in_paren = format!("({})", &init_str); | ||
81 | |||
66 | ctx.add_action( | 82 | ctx.add_action( |
67 | AssistId("inline_local_variable"), | 83 | AssistId("inline_local_variable"), |
68 | "inline local variable", | 84 | "inline local variable", |
69 | move |edit: &mut AssistBuilder| { | 85 | move |edit: &mut AssistBuilder| { |
70 | edit.delete(delete_range); | 86 | edit.delete(delete_range); |
71 | for desc in refs { | 87 | for (desc, should_wrap) in refs.iter().zip(wrap_in_parens) { |
72 | edit.replace(desc.range, init_str.clone()) | 88 | if should_wrap { |
89 | edit.replace(desc.range, init_in_paren.clone()) | ||
90 | } else { | ||
91 | edit.replace(desc.range, init_str.clone()) | ||
92 | } | ||
73 | } | 93 | } |
74 | edit.set_cursor(delete_range.start()) | 94 | edit.set_cursor(delete_range.start()) |
75 | }, | 95 | }, |
@@ -147,7 +167,7 @@ fn foo() { | |||
147 | 167 | ||
148 | } | 168 | } |
149 | let b = (1 + 1) * 10; | 169 | let b = (1 + 1) * 10; |
150 | bar((1 + 1)); | 170 | bar(1 + 1); |
151 | }", | 171 | }", |
152 | ); | 172 | ); |
153 | } | 173 | } |
@@ -215,7 +235,7 @@ fn foo() { | |||
215 | 235 | ||
216 | } | 236 | } |
217 | let b = (bar(1) as u64) * 10; | 237 | let b = (bar(1) as u64) * 10; |
218 | bar((bar(1) as u64)); | 238 | bar(bar(1) as u64); |
219 | }", | 239 | }", |
220 | ); | 240 | ); |
221 | } | 241 | } |
@@ -295,4 +315,324 @@ fn foo() { | |||
295 | }", | 315 | }", |
296 | ); | 316 | ); |
297 | } | 317 | } |
318 | |||
319 | #[test] | ||
320 | fn test_call_expr() { | ||
321 | check_assist( | ||
322 | inline_local_varialbe, | ||
323 | " | ||
324 | fn foo() { | ||
325 | let a<|> = bar(10 + 1); | ||
326 | let b = a * 10; | ||
327 | let c = a as usize; | ||
328 | }", | ||
329 | " | ||
330 | fn foo() { | ||
331 | <|>let b = bar(10 + 1) * 10; | ||
332 | let c = bar(10 + 1) as usize; | ||
333 | }", | ||
334 | ); | ||
335 | } | ||
336 | |||
337 | #[test] | ||
338 | fn test_index_expr() { | ||
339 | check_assist( | ||
340 | inline_local_varialbe, | ||
341 | " | ||
342 | fn foo() { | ||
343 | let x = vec![1, 2, 3]; | ||
344 | let a<|> = x[0]; | ||
345 | let b = a * 10; | ||
346 | let c = a as usize; | ||
347 | }", | ||
348 | " | ||
349 | fn foo() { | ||
350 | let x = vec![1, 2, 3]; | ||
351 | <|>let b = x[0] * 10; | ||
352 | let c = x[0] as usize; | ||
353 | }", | ||
354 | ); | ||
355 | } | ||
356 | |||
357 | #[test] | ||
358 | fn test_method_call_expr() { | ||
359 | check_assist( | ||
360 | inline_local_varialbe, | ||
361 | " | ||
362 | fn foo() { | ||
363 | let bar = vec![1]; | ||
364 | let a<|> = bar.len(); | ||
365 | let b = a * 10; | ||
366 | let c = a as usize; | ||
367 | }", | ||
368 | " | ||
369 | fn foo() { | ||
370 | let bar = vec![1]; | ||
371 | <|>let b = bar.len() * 10; | ||
372 | let c = bar.len() as usize; | ||
373 | }", | ||
374 | ); | ||
375 | } | ||
376 | |||
377 | #[test] | ||
378 | fn test_field_expr() { | ||
379 | check_assist( | ||
380 | inline_local_varialbe, | ||
381 | " | ||
382 | struct Bar { | ||
383 | foo: usize | ||
384 | } | ||
385 | |||
386 | fn foo() { | ||
387 | let bar = Bar { foo: 1 }; | ||
388 | let a<|> = bar.foo; | ||
389 | let b = a * 10; | ||
390 | let c = a as usize; | ||
391 | }", | ||
392 | " | ||
393 | struct Bar { | ||
394 | foo: usize | ||
395 | } | ||
396 | |||
397 | fn foo() { | ||
398 | let bar = Bar { foo: 1 }; | ||
399 | <|>let b = bar.foo * 10; | ||
400 | let c = bar.foo as usize; | ||
401 | }", | ||
402 | ); | ||
403 | } | ||
404 | |||
405 | #[test] | ||
406 | fn test_try_expr() { | ||
407 | check_assist( | ||
408 | inline_local_varialbe, | ||
409 | " | ||
410 | fn foo() -> Option<usize> { | ||
411 | let bar = Some(1); | ||
412 | let a<|> = bar?; | ||
413 | let b = a * 10; | ||
414 | let c = a as usize; | ||
415 | None | ||
416 | }", | ||
417 | " | ||
418 | fn foo() -> Option<usize> { | ||
419 | let bar = Some(1); | ||
420 | <|>let b = bar? * 10; | ||
421 | let c = bar? as usize; | ||
422 | None | ||
423 | }", | ||
424 | ); | ||
425 | } | ||
426 | |||
427 | #[test] | ||
428 | fn test_ref_expr() { | ||
429 | check_assist( | ||
430 | inline_local_varialbe, | ||
431 | " | ||
432 | fn foo() { | ||
433 | let bar = 10; | ||
434 | let a<|> = &bar; | ||
435 | let b = a * 10; | ||
436 | }", | ||
437 | " | ||
438 | fn foo() { | ||
439 | let bar = 10; | ||
440 | <|>let b = &bar * 10; | ||
441 | }", | ||
442 | ); | ||
443 | } | ||
444 | |||
445 | #[test] | ||
446 | fn test_tuple_expr() { | ||
447 | check_assist( | ||
448 | inline_local_varialbe, | ||
449 | " | ||
450 | fn foo() { | ||
451 | let a<|> = (10, 20); | ||
452 | let b = a[0]; | ||
453 | }", | ||
454 | " | ||
455 | fn foo() { | ||
456 | <|>let b = (10, 20)[0]; | ||
457 | }", | ||
458 | ); | ||
459 | } | ||
460 | |||
461 | #[test] | ||
462 | fn test_array_expr() { | ||
463 | check_assist( | ||
464 | inline_local_varialbe, | ||
465 | " | ||
466 | fn foo() { | ||
467 | let a<|> = [1, 2, 3]; | ||
468 | let b = a.len(); | ||
469 | }", | ||
470 | " | ||
471 | fn foo() { | ||
472 | <|>let b = [1, 2, 3].len(); | ||
473 | }", | ||
474 | ); | ||
475 | } | ||
476 | |||
477 | #[test] | ||
478 | fn test_paren() { | ||
479 | check_assist( | ||
480 | inline_local_varialbe, | ||
481 | " | ||
482 | fn foo() { | ||
483 | let a<|> = (10 + 20); | ||
484 | let b = a * 10; | ||
485 | let c = a as usize; | ||
486 | }", | ||
487 | " | ||
488 | fn foo() { | ||
489 | <|>let b = (10 + 20) * 10; | ||
490 | let c = (10 + 20) as usize; | ||
491 | }", | ||
492 | ); | ||
493 | } | ||
494 | |||
495 | #[test] | ||
496 | fn test_path_expr() { | ||
497 | check_assist( | ||
498 | inline_local_varialbe, | ||
499 | " | ||
500 | fn foo() { | ||
501 | let d = 10; | ||
502 | let a<|> = d; | ||
503 | let b = a * 10; | ||
504 | let c = a as usize; | ||
505 | }", | ||
506 | " | ||
507 | fn foo() { | ||
508 | let d = 10; | ||
509 | <|>let b = d * 10; | ||
510 | let c = d as usize; | ||
511 | }", | ||
512 | ); | ||
513 | } | ||
514 | |||
515 | #[test] | ||
516 | fn test_block_expr() { | ||
517 | check_assist( | ||
518 | inline_local_varialbe, | ||
519 | " | ||
520 | fn foo() { | ||
521 | let a<|> = { 10 }; | ||
522 | let b = a * 10; | ||
523 | let c = a as usize; | ||
524 | }", | ||
525 | " | ||
526 | fn foo() { | ||
527 | <|>let b = { 10 } * 10; | ||
528 | let c = { 10 } as usize; | ||
529 | }", | ||
530 | ); | ||
531 | } | ||
532 | |||
533 | #[test] | ||
534 | fn test_used_in_different_expr1() { | ||
535 | check_assist( | ||
536 | inline_local_varialbe, | ||
537 | " | ||
538 | fn foo() { | ||
539 | let a<|> = 10 + 20; | ||
540 | let b = a * 10; | ||
541 | let c = (a, 20); | ||
542 | let d = [a, 10]; | ||
543 | let e = (a); | ||
544 | }", | ||
545 | " | ||
546 | fn foo() { | ||
547 | <|>let b = (10 + 20) * 10; | ||
548 | let c = (10 + 20, 20); | ||
549 | let d = [10 + 20, 10]; | ||
550 | let e = (10 + 20); | ||
551 | }", | ||
552 | ); | ||
553 | } | ||
554 | |||
555 | #[test] | ||
556 | fn test_used_in_for_expr() { | ||
557 | check_assist( | ||
558 | inline_local_varialbe, | ||
559 | " | ||
560 | fn foo() { | ||
561 | let a<|> = vec![10, 20]; | ||
562 | for i in a {} | ||
563 | }", | ||
564 | " | ||
565 | fn foo() { | ||
566 | <|>for i in vec![10, 20] {} | ||
567 | }", | ||
568 | ); | ||
569 | } | ||
570 | |||
571 | #[test] | ||
572 | fn test_used_in_while_expr() { | ||
573 | check_assist( | ||
574 | inline_local_varialbe, | ||
575 | " | ||
576 | fn foo() { | ||
577 | let a<|> = 1 > 0; | ||
578 | while a {} | ||
579 | }", | ||
580 | " | ||
581 | fn foo() { | ||
582 | <|>while 1 > 0 {} | ||
583 | }", | ||
584 | ); | ||
585 | } | ||
586 | |||
587 | #[test] | ||
588 | fn test_used_in_break_expr() { | ||
589 | check_assist( | ||
590 | inline_local_varialbe, | ||
591 | " | ||
592 | fn foo() { | ||
593 | let a<|> = 1 + 1; | ||
594 | loop { | ||
595 | break a; | ||
596 | } | ||
597 | }", | ||
598 | " | ||
599 | fn foo() { | ||
600 | <|>loop { | ||
601 | break 1 + 1; | ||
602 | } | ||
603 | }", | ||
604 | ); | ||
605 | } | ||
606 | |||
607 | #[test] | ||
608 | fn test_used_in_return_expr() { | ||
609 | check_assist( | ||
610 | inline_local_varialbe, | ||
611 | " | ||
612 | fn foo() { | ||
613 | let a<|> = 1 > 0; | ||
614 | return a; | ||
615 | }", | ||
616 | " | ||
617 | fn foo() { | ||
618 | <|>return 1 > 0; | ||
619 | }", | ||
620 | ); | ||
621 | } | ||
622 | |||
623 | #[test] | ||
624 | fn test_used_in_match_expr() { | ||
625 | check_assist( | ||
626 | inline_local_varialbe, | ||
627 | " | ||
628 | fn foo() { | ||
629 | let a<|> = 1 > 0; | ||
630 | match a {} | ||
631 | }", | ||
632 | " | ||
633 | fn foo() { | ||
634 | <|>match 1 > 0 {} | ||
635 | }", | ||
636 | ); | ||
637 | } | ||
298 | } | 638 | } |