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