aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-05-01 18:28:07 +0100
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-05-01 18:28:07 +0100
commit817a38538f69d5383942476a6066ca98d6f7d1cb (patch)
treea0ede4dddc09d68e47ab68512798cfcafafc7b13
parent71c13528cdcad9930ded24054daf6bb1678835e7 (diff)
parentd1c21b85cf7c8ca55bf0f83f2359d9018e321705 (diff)
Merge #1223
1223: Move guard to arm body assist r=matklad a=unrealhoang This is my attempt at #1206 Co-authored-by: Unreal Hoang <[email protected]>
-rw-r--r--crates/ra_assists/src/lib.rs2
-rw-r--r--crates/ra_assists/src/move_guard_to_arm_body.rs115
-rw-r--r--docs/user/features.md18
3 files changed, 135 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..a8ca19f5d
--- /dev/null
+++ b/crates/ra_assists/src/move_guard_to_arm_body.rs
@@ -0,0 +1,115 @@
1use hir::db::HirDatabase;
2use ra_syntax::{
3 TextUnit,
4 SyntaxElement,
5 ast::{MatchArm, AstNode, AstToken},
6 ast,
7};
8
9use crate::{AssistCtx, Assist, AssistId};
10
11pub(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)]
43mod 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}
diff --git a/docs/user/features.md b/docs/user/features.md
index cbfc491b2..a714574fb 100644
--- a/docs/user/features.md
+++ b/docs/user/features.md
@@ -388,6 +388,24 @@ fn foo() {
388} 388}
389``` 389```
390 390
391- Move guard expression to match arm body
392```rust
393//before:
394fn f() {
395 match x {
396 <|>y @ 4 | y @ 5 if y > 5 => true,
397 _ => false
398 }
399}
400//after:
401fn f() {
402 match x {
403 y @ 4 | y @ 5 => if y > 5 { <|>true },
404 _ => false
405 }
406}
407```
408
391### Magic Completions 409### Magic Completions
392 410
393In addition to usual reference completion, rust-analyzer provides some ✨magic✨ 411In addition to usual reference completion, rust-analyzer provides some ✨magic✨