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