aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/lib.rs2
-rw-r--r--crates/ra_assists/src/move_guard_to_arm_body.rs99
2 files changed, 101 insertions, 0 deletions
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index 4c330c907..a2998ae59 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -101,6 +101,7 @@ mod split_import;
101mod remove_dbg; 101mod remove_dbg;
102pub mod auto_import; 102pub mod auto_import;
103mod add_missing_impl_members; 103mod add_missing_impl_members;
104mod move_guard_to_arm_body;
104 105
105fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assist>] { 106fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assist>] {
106 &[ 107 &[
@@ -120,6 +121,7 @@ fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assis
120 add_missing_impl_members::add_missing_impl_members, 121 add_missing_impl_members::add_missing_impl_members,
121 add_missing_impl_members::add_missing_default_members, 122 add_missing_impl_members::add_missing_default_members,
122 inline_local_variable::inline_local_varialbe, 123 inline_local_variable::inline_local_varialbe,
124 move_guard_to_arm_body::move_guard_to_arm_body,
123 ] 125 ]
124} 126}
125 127
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 @@
1use hir::{
2 db::HirDatabase,
3};
4use ra_syntax::{
5 TextUnit,
6 SyntaxElement,
7 ast::{MatchArm, AstNode, AstToken},
8 ast,
9};
10
11use crate::{AssistCtx, Assist, AssistId};
12
13pub(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)]
50mod 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}