diff options
Diffstat (limited to 'crates/ra_assists/src/move_guard_to_arm_body.rs')
-rw-r--r-- | crates/ra_assists/src/move_guard_to_arm_body.rs | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/crates/ra_assists/src/move_guard_to_arm_body.rs b/crates/ra_assists/src/move_guard_to_arm_body.rs new file mode 100644 index 000000000..a8ca19f5d --- /dev/null +++ b/crates/ra_assists/src/move_guard_to_arm_body.rs | |||
@@ -0,0 +1,115 @@ | |||
1 | use hir::db::HirDatabase; | ||
2 | use ra_syntax::{ | ||
3 | TextUnit, | ||
4 | SyntaxElement, | ||
5 | ast::{MatchArm, AstNode, AstToken}, | ||
6 | ast, | ||
7 | }; | ||
8 | |||
9 | use crate::{AssistCtx, Assist, AssistId}; | ||
10 | |||
11 | pub(crate) fn move_guard_to_arm_body(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | ||
12 | let match_arm = ctx.node_at_offset::<MatchArm>()?; | ||
13 | let guard = match_arm.guard()?; | ||
14 | let space_before_guard = guard.syntax().prev_sibling_or_token(); | ||
15 | |||
16 | let guard_conditions = guard.expr()?; | ||
17 | let arm_expr = match_arm.expr()?; | ||
18 | let buf = format!("if {} {{ {} }}", guard_conditions.syntax().text(), arm_expr.syntax().text()); | ||
19 | |||
20 | ctx.add_action(AssistId("move_guard_to_arm_body"), "move guard to arm body", |edit| { | ||
21 | edit.target(guard.syntax().range()); | ||
22 | let offseting_amount = match space_before_guard { | ||
23 | Some(SyntaxElement::Token(tok)) => { | ||
24 | if let Some(_) = ast::Whitespace::cast(tok) { | ||
25 | let ele = space_before_guard.unwrap().range(); | ||
26 | edit.delete(ele); | ||
27 | ele.len() | ||
28 | } else { | ||
29 | TextUnit::from(0) | ||
30 | } | ||
31 | } | ||
32 | _ => TextUnit::from(0), | ||
33 | }; | ||
34 | |||
35 | edit.delete(guard.syntax().range()); | ||
36 | edit.replace_node_and_indent(arm_expr.syntax(), buf); | ||
37 | edit.set_cursor(arm_expr.syntax().range().start() + TextUnit::from(3) - offseting_amount); | ||
38 | }); | ||
39 | ctx.build() | ||
40 | } | ||
41 | |||
42 | #[cfg(test)] | ||
43 | mod tests { | ||
44 | use super::*; | ||
45 | |||
46 | use crate::helpers::{ check_assist, check_assist_target }; | ||
47 | |||
48 | #[test] | ||
49 | fn move_guard_to_arm_body_target() { | ||
50 | check_assist_target( | ||
51 | move_guard_to_arm_body, | ||
52 | r#" | ||
53 | fn f() { | ||
54 | let t = 'a'; | ||
55 | let chars = "abcd"; | ||
56 | match t { | ||
57 | '\r' <|>if chars.clone().next() == Some('\n') => false, | ||
58 | _ => true | ||
59 | } | ||
60 | } | ||
61 | "#, | ||
62 | r#"if chars.clone().next() == Some('\n')"#, | ||
63 | ); | ||
64 | } | ||
65 | |||
66 | #[test] | ||
67 | fn move_guard_to_arm_body_works() { | ||
68 | check_assist( | ||
69 | move_guard_to_arm_body, | ||
70 | r#" | ||
71 | fn f() { | ||
72 | let t = 'a'; | ||
73 | let chars = "abcd"; | ||
74 | match t { | ||
75 | '\r' <|>if chars.clone().next() == Some('\n') => false, | ||
76 | _ => true | ||
77 | } | ||
78 | } | ||
79 | "#, | ||
80 | r#" | ||
81 | fn f() { | ||
82 | let t = 'a'; | ||
83 | let chars = "abcd"; | ||
84 | match t { | ||
85 | '\r' => if chars.clone().next() == Some('\n') { <|>false }, | ||
86 | _ => true | ||
87 | } | ||
88 | } | ||
89 | "#, | ||
90 | ); | ||
91 | } | ||
92 | |||
93 | #[test] | ||
94 | fn move_guard_to_arm_body_works_complex_match() { | ||
95 | check_assist( | ||
96 | move_guard_to_arm_body, | ||
97 | r#" | ||
98 | fn f() { | ||
99 | match x { | ||
100 | <|>y @ 4 | y @ 5 if y > 5 => true, | ||
101 | _ => false | ||
102 | } | ||
103 | } | ||
104 | "#, | ||
105 | r#" | ||
106 | fn f() { | ||
107 | match x { | ||
108 | y @ 4 | y @ 5 => if y > 5 { <|>true }, | ||
109 | _ => false | ||
110 | } | ||
111 | } | ||
112 | "#, | ||
113 | ); | ||
114 | } | ||
115 | } | ||