diff options
Diffstat (limited to 'crates/ra_assists')
-rw-r--r-- | crates/ra_assists/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_assists/src/move_guard_to_arm_body.rs | 99 |
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; | |||
101 | mod remove_dbg; | 101 | mod remove_dbg; |
102 | pub mod auto_import; | 102 | pub mod auto_import; |
103 | mod add_missing_impl_members; | 103 | mod add_missing_impl_members; |
104 | mod move_guard_to_arm_body; | ||
104 | 105 | ||
105 | fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assist>] { | 106 | fn 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 @@ | |||
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 | } | ||