Skip to main content

ide_assists/handlers/
move_guard.rs

1use itertools::{Itertools, chain};
2use syntax::{
3    SyntaxKind::WHITESPACE,
4    TextRange,
5    ast::{
6        AstNode, BlockExpr, ElseBranch, Expr, IfExpr, MatchArm, Pat, edit::AstNodeEdit,
7        prec::ExprPrecedence, syntax_factory::SyntaxFactory,
8    },
9    syntax_editor::Element,
10};
11
12use crate::{AssistContext, AssistId, Assists};
13
14// Assist: move_guard_to_arm_body
15//
16// Moves match guard into match arm body.
17//
18// ```
19// enum Action { Move { distance: u32 }, Stop }
20//
21// fn handle(action: Action) {
22//     match action {
23//         Action::Move { distance } $0if distance > 10 => foo(),
24//         _ => (),
25//     }
26// }
27// ```
28// ->
29// ```
30// enum Action { Move { distance: u32 }, Stop }
31//
32// fn handle(action: Action) {
33//     match action {
34//         Action::Move { distance } => if distance > 10 {
35//             foo()
36//         },
37//         _ => (),
38//     }
39// }
40// ```
41pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -> Option<()> {
42    let match_arm = ctx.find_node_at_offset::<MatchArm>()?;
43    let guard = match_arm.guard()?;
44    if ctx.offset() > guard.syntax().text_range().end() {
45        cov_mark::hit!(move_guard_inapplicable_in_arm_body);
46        return None;
47    }
48    let rest_arms = rest_arms(&match_arm, ctx.selection_trimmed())?;
49    let space_before_delete = chain(
50        guard.syntax().prev_sibling_or_token(),
51        rest_arms.iter().filter_map(|it| it.syntax().prev_sibling_or_token()),
52    );
53    let space_after_arrow = match_arm.fat_arrow_token()?.next_sibling_or_token();
54
55    let arm_expr = match_arm.expr()?;
56    let make = SyntaxFactory::without_mappings();
57    let if_branch = chain([&match_arm], &rest_arms)
58        .rfold(None, |else_branch, arm| {
59            if let Some(guard) = arm.guard() {
60                let then_branch = crate::utils::wrap_block(&arm.expr()?, &make);
61                let guard_condition = guard.condition()?.reset_indent();
62                Some(make.expr_if(guard_condition, then_branch, else_branch).into())
63            } else {
64                arm.expr().map(|it| crate::utils::wrap_block(&it, &make).into())
65            }
66        })?
67        .indent(arm_expr.indent_level());
68    let ElseBranch::IfExpr(if_expr) = if_branch else { return None };
69
70    let target = guard.syntax().text_range();
71    acc.add(
72        AssistId::refactor_rewrite("move_guard_to_arm_body"),
73        "Move guard to arm body",
74        target,
75        |builder| {
76            let editor = builder.make_editor(match_arm.syntax());
77            for element in space_before_delete {
78                if element.kind() == WHITESPACE {
79                    editor.delete(element);
80                }
81            }
82            for rest_arm in &rest_arms {
83                editor.delete(rest_arm.syntax());
84            }
85            if let Some(element) = space_after_arrow
86                && element.kind() == WHITESPACE
87            {
88                editor.replace(element, make.whitespace(" "));
89            }
90
91            editor.delete(guard.syntax());
92            editor.replace(arm_expr.syntax(), if_expr.syntax());
93            builder.add_file_edits(ctx.vfs_file_id(), editor);
94        },
95    )
96}
97
98// Assist: move_arm_cond_to_match_guard
99//
100// Moves if expression from match arm body into a guard.
101//
102// ```
103// enum Action { Move { distance: u32 }, Stop }
104//
105// fn handle(action: Action) {
106//     match action {
107//         Action::Move { distance } => $0if distance > 10 { foo() },
108//         _ => (),
109//     }
110// }
111// ```
112// ->
113// ```
114// enum Action { Move { distance: u32 }, Stop }
115//
116// fn handle(action: Action) {
117//     match action {
118//         Action::Move { distance } if distance > 10 => foo(),
119//         _ => (),
120//     }
121// }
122// ```
123pub(crate) fn move_arm_cond_to_match_guard(
124    acc: &mut Assists,
125    ctx: &AssistContext<'_, '_>,
126) -> Option<()> {
127    let match_arm: MatchArm = ctx.find_node_at_offset::<MatchArm>()?;
128    let match_pat = match_arm.pat()?;
129    let arm_body = match_arm.expr()?;
130    let arm_guard = match_arm.guard().and_then(|it| it.condition());
131
132    let mut replace_node = None;
133    let if_expr: IfExpr = IfExpr::cast(arm_body.syntax().clone()).or_else(|| {
134        let block_expr = BlockExpr::cast(arm_body.syntax().clone())?;
135        if block_expr.statements().next().is_some() {
136            cov_mark::hit!(move_guard_non_naked_if);
137            return None;
138        }
139        if let Expr::IfExpr(e) = block_expr.tail_expr()? {
140            replace_node = Some(block_expr.syntax().clone());
141            Some(e)
142        } else {
143            None
144        }
145    })?;
146    if ctx.offset() > if_expr.then_branch()?.syntax().text_range().start() {
147        return None;
148    }
149
150    let replace_node = replace_node.unwrap_or_else(|| if_expr.syntax().clone());
151    let needs_dedent = replace_node != *if_expr.syntax();
152    let (conds_blocks, tail) = parse_if_chain(if_expr)?;
153
154    acc.add(
155        AssistId::refactor_rewrite("move_arm_cond_to_match_guard"),
156        "Move condition to match guard",
157        replace_node.text_range(),
158        |builder| {
159            let editor = builder.make_editor(match_arm.syntax());
160            let make = editor.make();
161            let mut replace_arms = vec![];
162
163            // Dedent if if_expr is in a BlockExpr
164            let dedent = if needs_dedent {
165                cov_mark::hit!(move_guard_ifelse_in_block);
166                1
167            } else {
168                cov_mark::hit!(move_guard_ifelse_else_block);
169                0
170            };
171            let indent_level = match_arm.indent_level();
172            let make_guard = |cond: Option<Expr>| {
173                let condition = match (arm_guard.clone(), cond) {
174                    (None, None) => return None,
175                    (None, Some(it)) | (Some(it), None) => it,
176                    (Some(lhs), Some(rhs)) => {
177                        let op_expr = |expr: Expr| {
178                            if expr.precedence().needs_parentheses_in(ExprPrecedence::LAnd) {
179                                make.expr_paren(expr).into()
180                            } else {
181                                expr
182                            }
183                        };
184                        let op = syntax::ast::BinaryOp::LogicOp(syntax::ast::LogicOp::And);
185                        let expr_bin = make.expr_bin(op_expr(lhs), op, op_expr(rhs));
186                        expr_bin.into()
187                    }
188                };
189                Some(make.match_guard(condition))
190            };
191
192            for (cond, block) in conds_blocks {
193                let only_expr = block.statements().next().is_none();
194                let expr = match block.tail_expr() {
195                    Some(then_expr) if only_expr => then_expr,
196                    _ => block.dedent(dedent.into()).into(),
197                };
198                let new_arm = make.match_arm(match_pat.clone(), make_guard(Some(cond)), expr);
199                replace_arms.push(new_arm);
200            }
201            if let Some(block) = tail {
202                cov_mark::hit!(move_guard_ifelse_else_tail);
203                let only_expr = block.statements().next().is_none();
204                let expr = match block.tail_expr() {
205                    Some(expr) if only_expr => {
206                        cov_mark::hit!(move_guard_ifelse_expr_only);
207                        expr
208                    }
209                    _ => block.dedent(dedent.into()).into(),
210                };
211                let new_arm = make.match_arm(match_pat, make_guard(None), expr);
212                replace_arms.push(new_arm);
213            } else {
214                // There's no else branch. Add a pattern without guard, unless the following match
215                // arm is `_ => ...`
216                cov_mark::hit!(move_guard_ifelse_notail);
217                match match_arm.syntax().next_sibling().and_then(MatchArm::cast) {
218                    Some(next_arm)
219                        if matches!(next_arm.pat(), Some(Pat::WildcardPat(_)))
220                            && next_arm.guard().is_none() =>
221                    {
222                        cov_mark::hit!(move_guard_ifelse_has_wildcard);
223                    }
224                    _ => {
225                        let block_expr = make.expr_empty_block().into();
226                        replace_arms.push(make.match_arm(match_pat, make_guard(None), block_expr));
227                    }
228                }
229            }
230
231            let newline = make.whitespace(&format!("\n{indent_level}"));
232            let replace_arms = replace_arms.iter().map(|it| it.syntax().syntax_element());
233            let replace_arms = Itertools::intersperse(replace_arms, newline.syntax_element());
234            editor.replace_with_many(match_arm.syntax(), replace_arms.collect());
235
236            builder.add_file_edits(ctx.vfs_file_id(), editor);
237        },
238    )
239}
240
241fn rest_arms(match_arm: &MatchArm, selection: TextRange) -> Option<Vec<MatchArm>> {
242    match_arm
243        .parent_match()
244        .match_arm_list()?
245        .arms()
246        .skip_while(|it| it != match_arm)
247        .skip(1)
248        .take_while(move |it| {
249            selection.is_empty() || crate::utils::is_selected(it, selection, false)
250        })
251        .take_while(move |it| {
252            it.pat()
253                .zip(match_arm.pat())
254                .is_some_and(|(a, b)| a.syntax().text() == b.syntax().text())
255        })
256        .collect::<Vec<_>>()
257        .into()
258}
259
260// Parses an if-else-if chain to get the conditions and the then branches until we encounter an else
261// branch or the end.
262fn parse_if_chain(if_expr: IfExpr) -> Option<(Vec<(Expr, BlockExpr)>, Option<BlockExpr>)> {
263    let mut conds_blocks = Vec::new();
264    let mut curr_if = if_expr;
265    let tail = loop {
266        let cond = curr_if.condition()?;
267        conds_blocks.push((cond, curr_if.then_branch()?));
268        match curr_if.else_branch() {
269            Some(ElseBranch::IfExpr(e)) => {
270                curr_if = e;
271            }
272            Some(ElseBranch::Block(b)) => {
273                break Some(b);
274            }
275            None => break None,
276        }
277    };
278    Some((conds_blocks, tail))
279}
280
281#[cfg(test)]
282mod tests {
283    use super::*;
284
285    use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
286
287    #[test]
288    fn move_guard_to_arm_body_range() {
289        cov_mark::check!(move_guard_inapplicable_in_arm_body);
290        check_assist_not_applicable(
291            move_guard_to_arm_body,
292            r#"
293fn main() {
294    match 92 {
295        x if x > 10 => $0false,
296        _ => true
297    }
298}
299"#,
300        );
301    }
302
303    #[test]
304    fn move_non_naked_arm_cond_to_guard() {
305        cov_mark::check!(move_guard_non_naked_if);
306        check_assist_not_applicable(
307            move_arm_cond_to_match_guard,
308            r#"
309fn main() {
310    match 92 {
311        _ => {
312            let cond = true;
313            $0if cond {
314                foo()
315            }
316        },
317        _ => true
318    }
319}
320"#,
321        );
322        check_assist_not_applicable(
323            move_arm_cond_to_match_guard,
324            r#"
325fn main() {
326    match 92 {
327        _ => {
328            let cond = true;
329            $0if cond {
330                foo()
331            } else {
332                bar()
333            }
334        },
335        _ => true
336    }
337}
338"#,
339        );
340    }
341
342    #[test]
343    fn move_guard_to_arm_body_target() {
344        check_assist_target(
345            move_guard_to_arm_body,
346            r#"
347fn main() {
348    match 92 {
349        x $0if x > 10 => false,
350        _ => true
351    }
352}
353"#,
354            r#"if x > 10"#,
355        );
356    }
357
358    #[test]
359    fn move_guard_to_arm_body_works() {
360        check_assist(
361            move_guard_to_arm_body,
362            r#"
363fn main() {
364    match 92 {
365        x $0if x > 10 => false,
366        _ => true
367    }
368}
369"#,
370            r#"
371fn main() {
372    match 92 {
373        x => if x > 10 {
374            false
375        },
376        _ => true
377    }
378}
379"#,
380        );
381    }
382
383    #[test]
384    fn move_multiple_guard_to_arm_body_works() {
385        check_assist(
386            move_guard_to_arm_body,
387            r#"
388fn main() {
389    match 92 {
390        x @ 0..30 $0if x % 3 == 0 => false,
391        x @ 0..30 if x % 2 == 0 => true,
392        _ => false
393    }
394}
395"#,
396            r#"
397fn main() {
398    match 92 {
399        x @ 0..30 => if x % 3 == 0 {
400            false
401        } else if x % 2 == 0 {
402            true
403        },
404        _ => false
405    }
406}
407"#,
408        );
409
410        check_assist(
411            move_guard_to_arm_body,
412            r#"
413fn main() {
414    match 92 {
415        x @ 0..30 $0if x % 3 == 0 => false,
416        x @ 0..30 if x % 2 == 0 => true,
417        x @ 0..30 => false,
418        _ => true
419    }
420}
421"#,
422            r#"
423fn main() {
424    match 92 {
425        x @ 0..30 => if x % 3 == 0 {
426            false
427        } else if x % 2 == 0 {
428            true
429        } else {
430            false
431        },
432        _ => true
433    }
434}
435"#,
436        );
437
438        check_assist(
439            move_guard_to_arm_body,
440            r#"
441fn main() {
442    match 92 {
443        x @ 0..30 if x % 3 == 0 => false,
444        x @ 0..30 $0if x % 2 == 0$0 => true,
445        x @ 0..30 => false,
446        _ => true
447    }
448}
449"#,
450            r#"
451fn main() {
452    match 92 {
453        x @ 0..30 if x % 3 == 0 => false,
454        x @ 0..30 => if x % 2 == 0 {
455            true
456        },
457        x @ 0..30 => false,
458        _ => true
459    }
460}
461"#,
462        );
463
464        check_assist(
465            move_guard_to_arm_body,
466            r#"
467fn main() {
468    match 92 {
469        x @ 0..30 $0if x % 3 == 0 => false,
470        x @ 0..30 $0if x % 2 == 0 => true,
471        x @ 0..30 => false,
472        _ => true
473    }
474}
475"#,
476            r#"
477fn main() {
478    match 92 {
479        x @ 0..30 => if x % 3 == 0 {
480            false
481        } else if x % 2 == 0 {
482            true
483        },
484        x @ 0..30 => false,
485        _ => true
486    }
487}
488"#,
489        );
490    }
491
492    #[test]
493    fn move_guard_to_block_arm_body_works() {
494        check_assist(
495            move_guard_to_arm_body,
496            r#"
497fn main() {
498    match 92 {
499        x $0if x > 10 => {
500            let _ = true;
501            false
502        },
503        _ => true
504    }
505}
506"#,
507            r#"
508fn main() {
509    match 92 {
510        x => if x > 10 {
511            let _ = true;
512            false
513        },
514        _ => true
515    }
516}
517"#,
518        );
519    }
520
521    #[test]
522    fn move_let_guard_to_arm_body_works() {
523        check_assist(
524            move_guard_to_arm_body,
525            r#"
526fn main() {
527    match 92 {
528        x $0if (let 1 = x) => false,
529        _ => true
530    }
531}
532"#,
533            r#"
534fn main() {
535    match 92 {
536        x => if (let 1 = x) {
537            false
538        },
539        _ => true
540    }
541}
542"#,
543        );
544    }
545
546    #[test]
547    fn move_multiline_guard_to_arm_body_works() {
548        check_assist(
549            move_guard_to_arm_body,
550            r#"
551fn main() {
552    match 92 {
553        x $0if true
554            && true
555            && true =>
556        {
557            {
558                false
559            }
560        },
561        _ => true
562    }
563}
564"#,
565            r#"
566fn main() {
567    match 92 {
568        x => if true
569            && true
570            && true
571        {
572            {
573                false
574            }
575        },
576        _ => true
577    }
578}
579"#,
580        );
581    }
582
583    #[test]
584    fn move_guard_to_arm_body_works_complex_match() {
585        check_assist(
586            move_guard_to_arm_body,
587            r#"
588fn main() {
589    match 92 {
590        $0x @ 4 | x @ 5    if x > 5 => true,
591        _ => false
592    }
593}
594"#,
595            r#"
596fn main() {
597    match 92 {
598        x @ 4 | x @ 5 => if x > 5 {
599            true
600        },
601        _ => false
602    }
603}
604"#,
605        );
606    }
607
608    #[test]
609    fn move_arm_cond_to_match_guard_works() {
610        check_assist(
611            move_arm_cond_to_match_guard,
612            r#"
613fn main() {
614    match 92 {
615        x => if x > 10$0 { false },
616        _ => true
617    }
618}
619"#,
620            r#"
621fn main() {
622    match 92 {
623        x if x > 10 => false,
624        _ => true
625    }
626}
627"#,
628        );
629    }
630
631    #[test]
632    fn move_arm_cond_in_block_to_match_guard_works() {
633        cov_mark::check!(move_guard_ifelse_has_wildcard);
634        check_assist(
635            move_arm_cond_to_match_guard,
636            r#"
637fn main() {
638    match 92 {
639        x => {
640            $0if x > 10 {
641                false
642            }
643        },
644        _ => true
645    }
646}
647"#,
648            r#"
649fn main() {
650    match 92 {
651        x if x > 10 => false,
652        _ => true
653    }
654}
655"#,
656        );
657    }
658
659    #[test]
660    fn move_arm_cond_in_block_to_match_guard_no_wildcard_works() {
661        cov_mark::check_count!(move_guard_ifelse_has_wildcard, 0);
662        check_assist(
663            move_arm_cond_to_match_guard,
664            r#"
665fn main() {
666    match 92 {
667        x => {
668            $0if x > 10 {
669                false
670            }
671        }
672    }
673}
674"#,
675            r#"
676fn main() {
677    match 92 {
678        x if x > 10 => false,
679        x => {}
680    }
681}
682"#,
683        );
684    }
685
686    #[test]
687    fn move_arm_cond_in_block_to_match_guard_wildcard_guard_works() {
688        cov_mark::check_count!(move_guard_ifelse_has_wildcard, 0);
689        check_assist(
690            move_arm_cond_to_match_guard,
691            r#"
692fn main() {
693    match 92 {
694        x => {
695            $0if x > 10 {
696                false
697            }
698        }
699        _ if x > 10 => true,
700    }
701}
702"#,
703            r#"
704fn main() {
705    match 92 {
706        x if x > 10 => false,
707        x => {}
708        _ if x > 10 => true,
709    }
710}
711"#,
712        );
713    }
714
715    #[test]
716    fn move_arm_cond_in_block_to_match_guard_add_comma_works() {
717        check_assist(
718            move_arm_cond_to_match_guard,
719            r#"
720fn main() {
721    match 92 {
722        x => {
723            $0if x > 10 {
724                false
725            }
726        }
727        _ => true
728    }
729}
730"#,
731            r#"
732fn main() {
733    match 92 {
734        x if x > 10 => false,
735        _ => true
736    }
737}
738"#,
739        );
740    }
741
742    #[test]
743    fn move_arm_cond_to_match_guard_if_let_works() {
744        check_assist(
745            move_arm_cond_to_match_guard,
746            r#"
747fn main() {
748    match 92 {
749        x => if let 62 = x $0&& true { false },
750        _ => true
751    }
752}
753"#,
754            r#"
755fn main() {
756    match 92 {
757        x if let 62 = x && true => false,
758        _ => true
759    }
760}
761"#,
762        );
763    }
764
765    #[test]
766    fn move_arm_cond_to_match_guard_if_empty_body_works() {
767        check_assist(
768            move_arm_cond_to_match_guard,
769            r#"
770fn main() {
771    match 92 {
772        x => if x $0> 10 {  },
773        _ => true
774    }
775}
776"#,
777            r#"
778fn main() {
779    match 92 {
780        x if x > 10 => {  }
781        _ => true
782    }
783}
784"#,
785        );
786    }
787
788    #[test]
789    fn move_arm_cond_to_match_guard_if_multiline_body_works() {
790        check_assist(
791            move_arm_cond_to_match_guard,
792            r#"
793fn main() {
794    match 92 {
795        x => if$0 x > 10 {
796            92;
797            false
798        },
799        _ => true
800    }
801}
802"#,
803            r#"
804fn main() {
805    match 92 {
806        x if x > 10 => {
807            92;
808            false
809        }
810        _ => true
811    }
812}
813"#,
814        );
815    }
816
817    #[test]
818    fn move_arm_cond_in_block_to_match_guard_if_multiline_body_works() {
819        check_assist(
820            move_arm_cond_to_match_guard,
821            r#"
822fn main() {
823    match 92 {
824        x => {
825            if x > $010 {
826                92;
827                false
828            }
829        }
830        _ => true
831    }
832}
833"#,
834            r#"
835fn main() {
836    match 92 {
837        x if x > 10 => {
838            92;
839            false
840        }
841        _ => true
842    }
843}
844"#,
845        )
846    }
847
848    #[test]
849    fn move_arm_cond_to_match_guard_with_else_works() {
850        check_assist(
851            move_arm_cond_to_match_guard,
852            r#"
853fn main() {
854    match 92 {
855        x => if x > $010 {
856            false
857        } else {
858            true
859        }
860        _ => true,
861    }
862}
863"#,
864            r#"
865fn main() {
866    match 92 {
867        x if x > 10 => false,
868        x => true,
869        _ => true,
870    }
871}
872"#,
873        )
874    }
875
876    #[test]
877    fn move_arm_cond_to_match_guard_with_else_block_works() {
878        cov_mark::check!(move_guard_ifelse_expr_only);
879        check_assist(
880            move_arm_cond_to_match_guard,
881            r#"
882fn main() {
883    match 92 {
884        x => {
885            if x $0> 10 {
886                false
887            } else {
888                true
889            }
890        }
891        _ => true
892    }
893}
894"#,
895            r#"
896fn main() {
897    match 92 {
898        x if x > 10 => false,
899        x => true,
900        _ => true
901    }
902}
903"#,
904        )
905    }
906
907    #[test]
908    fn move_arm_cond_to_match_guard_else_if_empty_body_works() {
909        check_assist(
910            move_arm_cond_to_match_guard,
911            r#"
912fn main() {
913    match 92 {
914        x => if x > $010 {  } else { },
915        _ => true
916    }
917}
918"#,
919            r#"
920fn main() {
921    match 92 {
922        x if x > 10 => {  }
923        x => { }
924        _ => true
925    }
926}
927"#,
928        );
929    }
930
931    #[test]
932    fn move_arm_cond_to_match_guard_with_else_multiline_works() {
933        check_assist(
934            move_arm_cond_to_match_guard,
935            r#"
936fn main() {
937    match 92 {
938        x => if$0 x > 10 {
939            92;
940            false
941        } else {
942            true
943        }
944        _ => true
945    }
946}
947"#,
948            r#"
949fn main() {
950    match 92 {
951        x if x > 10 => {
952            92;
953            false
954        }
955        x => true,
956        _ => true
957    }
958}
959"#,
960        )
961    }
962
963    #[test]
964    fn move_arm_cond_to_match_guard_with_else_multiline_else_works() {
965        cov_mark::check!(move_guard_ifelse_else_block);
966        check_assist(
967            move_arm_cond_to_match_guard,
968            r#"
969fn main() {
970    match 92 {
971        x => if x $0> 10 {
972            false
973        } else {
974            42;
975            true
976        }
977        _ => true
978    }
979}
980"#,
981            r#"
982fn main() {
983    match 92 {
984        x if x > 10 => false,
985        x => {
986            42;
987            true
988        }
989        _ => true
990    }
991}
992"#,
993        )
994    }
995
996    #[test]
997    fn move_arm_cond_to_match_guard_with_else_multiline_else_block_works() {
998        cov_mark::check!(move_guard_ifelse_in_block);
999        check_assist(
1000            move_arm_cond_to_match_guard,
1001            r#"
1002fn main() {
1003    match 92 {
1004        x => {
1005            if x > $010 {
1006                false
1007            } else {
1008                42;
1009                true
1010            }
1011        }
1012        _ => true
1013    }
1014}
1015"#,
1016            r#"
1017fn main() {
1018    match 92 {
1019        x if x > 10 => false,
1020        x => {
1021            42;
1022            true
1023        }
1024        _ => true
1025    }
1026}
1027"#,
1028        )
1029    }
1030
1031    #[test]
1032    fn move_arm_cond_to_match_guard_with_else_last_arm_works() {
1033        check_assist(
1034            move_arm_cond_to_match_guard,
1035            r#"
1036fn main() {
1037    match 92 {
1038        3 => true,
1039        x => {
1040            if x > $010 {
1041                false
1042            } else {
1043                92;
1044                true
1045            }
1046        }
1047    }
1048}
1049"#,
1050            r#"
1051fn main() {
1052    match 92 {
1053        3 => true,
1054        x if x > 10 => false,
1055        x => {
1056            92;
1057            true
1058        }
1059    }
1060}
1061"#,
1062        )
1063    }
1064
1065    #[test]
1066    fn move_arm_cond_to_match_guard_with_else_comma_works() {
1067        check_assist(
1068            move_arm_cond_to_match_guard,
1069            r#"
1070fn main() {
1071    match 92 {
1072        3 => true,
1073        x => if x > $010 {
1074            false
1075        } else {
1076            92;
1077            true
1078        },
1079    }
1080}
1081"#,
1082            r#"
1083fn main() {
1084    match 92 {
1085        3 => true,
1086        x if x > 10 => false,
1087        x => {
1088            92;
1089            true
1090        }
1091    }
1092}
1093"#,
1094        )
1095    }
1096
1097    #[test]
1098    fn move_arm_cond_to_match_guard_elseif() {
1099        check_assist(
1100            move_arm_cond_to_match_guard,
1101            r#"
1102fn main() {
1103    match 92 {
1104        3 => true,
1105        x => if x $0> 10 {
1106            false
1107        } else if x > 5 {
1108            true
1109        } else if x > 4 {
1110            false
1111        } else {
1112            true
1113        },
1114    }
1115}
1116"#,
1117            r#"
1118fn main() {
1119    match 92 {
1120        3 => true,
1121        x if x > 10 => false,
1122        x if x > 5 => true,
1123        x if x > 4 => false,
1124        x => true,
1125    }
1126}
1127"#,
1128        )
1129    }
1130
1131    #[test]
1132    fn move_arm_cond_to_match_guard_elseif_in_block() {
1133        cov_mark::check!(move_guard_ifelse_in_block);
1134        check_assist(
1135            move_arm_cond_to_match_guard,
1136            r#"
1137fn main() {
1138    match 92 {
1139        3 => true,
1140        x => {
1141            if x > $010 {
1142                false
1143            } else if x > 5 {
1144                true
1145            } else if x > 4 {
1146                false
1147            } else {
1148                true
1149            }
1150        }
1151    }
1152}
1153"#,
1154            r#"
1155fn main() {
1156    match 92 {
1157        3 => true,
1158        x if x > 10 => false,
1159        x if x > 5 => true,
1160        x if x > 4 => false,
1161        x => true,
1162    }
1163}
1164"#,
1165        )
1166    }
1167
1168    #[test]
1169    fn move_arm_cond_to_match_guard_elseif_chain() {
1170        cov_mark::check!(move_guard_ifelse_else_tail);
1171        check_assist(
1172            move_arm_cond_to_match_guard,
1173            r#"
1174fn main() {
1175    match 92 {
1176        3 => 0,
1177        x => if x $0> 10 {
1178            1
1179        } else if x > 5 {
1180            2
1181        } else if x > 3 {
1182            42;
1183            3
1184        } else {
1185            4
1186        },
1187    }
1188}
1189"#,
1190            r#"
1191fn main() {
1192    match 92 {
1193        3 => 0,
1194        x if x > 10 => 1,
1195        x if x > 5 => 2,
1196        x if x > 3 => {
1197            42;
1198            3
1199        }
1200        x => 4,
1201    }
1202}
1203"#,
1204        )
1205    }
1206
1207    #[test]
1208    fn move_arm_cond_to_match_guard_elseif_iflet() {
1209        check_assist(
1210            move_arm_cond_to_match_guard,
1211            r#"
1212fn main() {
1213    match 92 {
1214        3 => 0,
1215        x => if x $0> 10 {
1216            1
1217        } else if x > 5 {
1218            2
1219        } else if let 4 = 4 {
1220            42;
1221            3
1222        } else {
1223            4
1224        },
1225    }
1226}"#,
1227            r#"
1228fn main() {
1229    match 92 {
1230        3 => 0,
1231        x if x > 10 => 1,
1232        x if x > 5 => 2,
1233        x if let 4 = 4 => {
1234            42;
1235            3
1236        }
1237        x => 4,
1238    }
1239}"#,
1240        );
1241    }
1242
1243    #[test]
1244    fn move_arm_cond_to_match_guard_elseif_notail() {
1245        cov_mark::check!(move_guard_ifelse_notail);
1246        check_assist(
1247            move_arm_cond_to_match_guard,
1248            r#"
1249fn main() {
1250    match 92 {
1251        3 => 0,
1252        x => if x > $010 {
1253            1
1254        } else if x > 5 {
1255            2
1256        } else if x > 4 {
1257            42;
1258            3
1259        },
1260    }
1261}
1262"#,
1263            r#"
1264fn main() {
1265    match 92 {
1266        3 => 0,
1267        x if x > 10 => 1,
1268        x if x > 5 => 2,
1269        x if x > 4 => {
1270            42;
1271            3
1272        }
1273        x => {}
1274    }
1275}
1276"#,
1277        )
1278    }
1279
1280    #[test]
1281    fn move_arm_cond_to_match_guard_elseif_exist_guard() {
1282        check_assist(
1283            move_arm_cond_to_match_guard,
1284            r#"
1285fn main() {
1286    let cond = true;
1287    match 92 {
1288        3 => true,
1289        x if cond => if x $0> 10 {
1290            false
1291        } else if x > 5 {
1292            true
1293        } else if x > 4 || x < -2 {
1294            false
1295        } else {
1296            true
1297        },
1298    }
1299}
1300"#,
1301            r#"
1302fn main() {
1303    let cond = true;
1304    match 92 {
1305        3 => true,
1306        x if cond && x > 10 => false,
1307        x if cond && x > 5 => true,
1308        x if cond && (x > 4 || x < -2) => false,
1309        x if cond => true,
1310    }
1311}
1312"#,
1313        )
1314    }
1315}