@@ -8,7 +8,7 @@ use ide_db::{
8
8
ty_filter:: TryEnum ,
9
9
} ;
10
10
use syntax:: {
11
- AstNode , T , TextRange ,
11
+ AstNode , Edition , T , TextRange ,
12
12
ast:: { self , HasName , edit:: IndentLevel , edit_in_place:: Indent , syntax_factory:: SyntaxFactory } ,
13
13
} ;
14
14
@@ -187,7 +187,7 @@ fn make_else_arm(
187
187
188
188
// Assist: replace_match_with_if_let
189
189
//
190
- // Replaces a binary `match` with a wildcard pattern and no guards with an `if let` expression.
190
+ // Replaces a binary `match` with a wildcard pattern with an `if let` expression.
191
191
//
192
192
// ```
193
193
// enum Action { Move { distance: u32 }, Stop }
@@ -225,18 +225,24 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
225
225
226
226
let mut arms = match_arm_list. arms ( ) ;
227
227
let ( first_arm, second_arm) = ( arms. next ( ) ?, arms. next ( ) ?) ;
228
- if arms. next ( ) . is_some ( ) || first_arm. guard ( ) . is_some ( ) || second_arm. guard ( ) . is_some ( ) {
228
+ if arms. next ( ) . is_some ( ) || second_arm. guard ( ) . is_some ( ) {
229
+ return None ;
230
+ }
231
+ if first_arm. guard ( ) . is_some ( ) && ctx. edition ( ) < Edition :: Edition2024 {
229
232
return None ;
230
233
}
231
234
232
- let ( if_let_pat, then_expr, else_expr) = pick_pattern_and_expr_order (
235
+ let ( if_let_pat, guard , then_expr, else_expr) = pick_pattern_and_expr_order (
233
236
& ctx. sema ,
234
237
first_arm. pat ( ) ?,
235
238
second_arm. pat ( ) ?,
236
239
first_arm. expr ( ) ?,
237
240
second_arm. expr ( ) ?,
241
+ first_arm. guard ( ) ,
242
+ second_arm. guard ( ) ,
238
243
) ?;
239
244
let scrutinee = match_expr. expr ( ) ?;
245
+ let guard = guard. and_then ( |it| it. condition ( ) ) ;
240
246
241
247
let let_ = match & if_let_pat {
242
248
ast:: Pat :: LiteralPat ( p)
@@ -277,6 +283,11 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
277
283
}
278
284
_ => make. expr_let ( if_let_pat, scrutinee) . into ( ) ,
279
285
} ;
286
+ let condition = if let Some ( guard) = guard {
287
+ make. expr_bin ( condition, ast:: BinaryOp :: LogicOp ( ast:: LogicOp :: And ) , guard) . into ( )
288
+ } else {
289
+ condition
290
+ } ;
280
291
let then_expr = then_expr. clone_for_update ( ) ;
281
292
then_expr. reindent_to ( IndentLevel :: single ( ) ) ;
282
293
let then_block = make_block_expr ( then_expr) ;
@@ -303,18 +314,23 @@ fn pick_pattern_and_expr_order(
303
314
pat2 : ast:: Pat ,
304
315
expr : ast:: Expr ,
305
316
expr2 : ast:: Expr ,
306
- ) -> Option < ( ast:: Pat , ast:: Expr , ast:: Expr ) > {
317
+ guard : Option < ast:: MatchGuard > ,
318
+ guard2 : Option < ast:: MatchGuard > ,
319
+ ) -> Option < ( ast:: Pat , Option < ast:: MatchGuard > , ast:: Expr , ast:: Expr ) > {
320
+ if guard. is_some ( ) && guard2. is_some ( ) {
321
+ return None ;
322
+ }
307
323
let res = match ( pat, pat2) {
308
324
( ast:: Pat :: WildcardPat ( _) , _) => return None ,
309
- ( pat, ast:: Pat :: WildcardPat ( _) ) => ( pat, expr, expr2) ,
310
- ( pat, _) if is_empty_expr ( & expr2) => ( pat, expr, expr2) ,
311
- ( _, pat) if is_empty_expr ( & expr) => ( pat, expr2, expr) ,
325
+ ( pat, ast:: Pat :: WildcardPat ( _) ) => ( pat, guard , expr, expr2) ,
326
+ ( pat, _) if is_empty_expr ( & expr2) => ( pat, guard , expr, expr2) ,
327
+ ( _, pat) if is_empty_expr ( & expr) => ( pat, guard , expr2, expr) ,
312
328
( pat, pat2) => match ( binds_name ( sema, & pat) , binds_name ( sema, & pat2) ) {
313
329
( true , true ) => return None ,
314
- ( true , false ) => ( pat, expr, expr2) ,
315
- ( false , true ) => ( pat2, expr2, expr) ,
316
- _ if is_sad_pat ( sema, & pat) => ( pat2, expr2, expr) ,
317
- ( false , false ) => ( pat, expr, expr2) ,
330
+ ( true , false ) => ( pat, guard , expr, expr2) ,
331
+ ( false , true ) => ( pat2, guard2 , expr2, expr) ,
332
+ _ if is_sad_pat ( sema, & pat) => ( pat2, guard2 , expr2, expr) ,
333
+ ( false , false ) => ( pat, guard , expr, expr2) ,
318
334
} ,
319
335
} ;
320
336
Some ( res)
@@ -1849,6 +1865,30 @@ fn main() {
1849
1865
code()
1850
1866
}
1851
1867
}
1868
+ "# ,
1869
+ )
1870
+ }
1871
+
1872
+ #[ test]
1873
+ fn test_replace_match_with_if_let_chain ( ) {
1874
+ check_assist (
1875
+ replace_match_with_if_let,
1876
+ r#"
1877
+ fn main() {
1878
+ match$0 Some(0) {
1879
+ Some(n) if n % 2 == 0 && n != 6 => (),
1880
+ _ => code(),
1881
+ }
1882
+ }
1883
+ "# ,
1884
+ r#"
1885
+ fn main() {
1886
+ if let Some(n) = Some(0) && n % 2 == 0 && n != 6 {
1887
+ ()
1888
+ } else {
1889
+ code()
1890
+ }
1891
+ }
1852
1892
"# ,
1853
1893
)
1854
1894
}
0 commit comments