@@ -2,7 +2,7 @@ use hir::db::HirDatabase;
2
2
use ra_syntax:: {
3
3
TextUnit ,
4
4
SyntaxElement ,
5
- ast:: { MatchArm , AstNode , AstToken } ,
5
+ ast:: { MatchArm , AstNode , AstToken , IfExpr } ,
6
6
ast,
7
7
} ;
8
8
@@ -39,6 +39,41 @@ pub(crate) fn move_guard_to_arm_body(mut ctx: AssistCtx<impl HirDatabase>) -> Op
39
39
ctx. build ( )
40
40
}
41
41
42
+ pub ( crate ) fn move_arm_cond_to_match_guard ( mut ctx : AssistCtx < impl HirDatabase > ) -> Option < Assist > {
43
+ let match_arm: & MatchArm = ctx. node_at_offset :: < MatchArm > ( ) ?;
44
+ let last_match_pat = match_arm. pats ( ) . last ( ) ?;
45
+
46
+ let arm_body = match_arm. expr ( ) ?;
47
+ let if_expr: & IfExpr = IfExpr :: cast ( arm_body. syntax ( ) ) ?;
48
+ let cond = if_expr. condition ( ) ?;
49
+ let then_block = if_expr. then_branch ( ) ?;
50
+
51
+ // Not support if with else branch
52
+ if let Some ( _) = if_expr. else_branch ( ) {
53
+ return None ;
54
+ }
55
+
56
+ let buf = format ! ( " if {}" , cond. syntax( ) . text( ) ) ;
57
+
58
+ ctx. add_action (
59
+ AssistId ( "move_arm_cond_to_match_guard" ) ,
60
+ "move condition to match guard" ,
61
+ |edit| {
62
+ edit. target ( last_match_pat. syntax ( ) . range ( ) ) ;
63
+
64
+ if then_block. statements ( ) . next ( ) . is_none ( ) && then_block. expr ( ) . is_some ( ) {
65
+ edit. replace ( if_expr. syntax ( ) . range ( ) , then_block. expr ( ) . unwrap ( ) . syntax ( ) . text ( ) ) ;
66
+ } else {
67
+ edit. replace ( if_expr. syntax ( ) . range ( ) , then_block. syntax ( ) . text ( ) ) ;
68
+ }
69
+
70
+ edit. insert ( last_match_pat. syntax ( ) . range ( ) . end ( ) , buf) ;
71
+ edit. set_cursor ( last_match_pat. syntax ( ) . range ( ) . end ( ) + TextUnit :: from ( 1 ) ) ;
72
+ } ,
73
+ ) ;
74
+ ctx. build ( )
75
+ }
76
+
42
77
#[ cfg( test) ]
43
78
mod tests {
44
79
use super :: * ;
@@ -112,4 +147,118 @@ mod tests {
112
147
"# ,
113
148
) ;
114
149
}
150
+
151
+ #[ test]
152
+ fn move_arm_cond_to_match_guard_works ( ) {
153
+ check_assist (
154
+ move_arm_cond_to_match_guard,
155
+ r#"
156
+ fn f() {
157
+ let t = 'a';
158
+ let chars = "abcd";
159
+ match t {
160
+ '\r' => if chars.clone().next() == Some('\n') { <|>false },
161
+ _ => true
162
+ }
163
+ }
164
+ "# ,
165
+ r#"
166
+ fn f() {
167
+ let t = 'a';
168
+ let chars = "abcd";
169
+ match t {
170
+ '\r' <|>if chars.clone().next() == Some('\n') => false,
171
+ _ => true
172
+ }
173
+ }
174
+ "# ,
175
+ ) ;
176
+ }
177
+
178
+ #[ test]
179
+ fn move_arm_cond_to_match_guard_if_let_works ( ) {
180
+ check_assist (
181
+ move_arm_cond_to_match_guard,
182
+ r#"
183
+ fn f() {
184
+ let t = 'a';
185
+ let chars = "abcd";
186
+ match t {
187
+ '\r' => if let Some(_) = chars.clone().next() { <|>false },
188
+ _ => true
189
+ }
190
+ }
191
+ "# ,
192
+ r#"
193
+ fn f() {
194
+ let t = 'a';
195
+ let chars = "abcd";
196
+ match t {
197
+ '\r' <|>if let Some(_) = chars.clone().next() => false,
198
+ _ => true
199
+ }
200
+ }
201
+ "# ,
202
+ ) ;
203
+ }
204
+
205
+ #[ test]
206
+ fn move_arm_cond_to_match_guard_if_empty_body_works ( ) {
207
+ check_assist (
208
+ move_arm_cond_to_match_guard,
209
+ r#"
210
+ fn f() {
211
+ let t = 'a';
212
+ let chars = "abcd";
213
+ match t {
214
+ '\r' => if let Some(_) = chars.clone().next() { <|> },
215
+ _ => true
216
+ }
217
+ }
218
+ "# ,
219
+ r#"
220
+ fn f() {
221
+ let t = 'a';
222
+ let chars = "abcd";
223
+ match t {
224
+ '\r' <|>if let Some(_) = chars.clone().next() => { },
225
+ _ => true
226
+ }
227
+ }
228
+ "# ,
229
+ ) ;
230
+ }
231
+
232
+ #[ test]
233
+ fn move_arm_cond_to_match_guard_if_multiline_body_works ( ) {
234
+ check_assist (
235
+ move_arm_cond_to_match_guard,
236
+ r#"
237
+ fn f() {
238
+ let mut t = 'a';
239
+ let chars = "abcd";
240
+ match t {
241
+ '\r' => if let Some(_) = chars.clone().next() {
242
+ t = 'e';<|>
243
+ false
244
+ },
245
+ _ => true
246
+ }
247
+ }
248
+ "# ,
249
+ r#"
250
+ fn f() {
251
+ let mut t = 'a';
252
+ let chars = "abcd";
253
+ match t {
254
+ '\r' <|>if let Some(_) = chars.clone().next() => {
255
+ t = 'e';
256
+ false
257
+ },
258
+ _ => true
259
+ }
260
+ }
261
+ "# ,
262
+ ) ;
263
+ }
115
264
}
0 commit comments