Skip to content

Commit 4ec6bd6

Browse files
bors[bot]weirane
andauthored
Merge #11017
11017: Support "move if to guard" with an else branch r=Veykril a=weirane Support the assist `move_arm_cond_to_match_guard` when there is an else branch. I have two questions: 1. How to indent the first line of a match arm? `matcharm.indent()` doesn't seem to work. so I hard coded four spaces here: https://github.com/weirane/rust-analyzer/blob/95a0de85d5d659e876e731725475f1c022719f31/crates/ide_assists/src/handlers/move_guard.rs#L162-L163 2. I find a little issue in the original implementation, this code ```rust let y = match 92 { x => { if x == 0 {$0 false } } _ => true, }; ``` will be transformed to ```rust let y = match 92 { x if x == 0 => false _ => true, }; ``` a comma is missing after the `false`. Should I also fix that? Or this can go in a separate PR. Closes #10997. Co-authored-by: Wang Ruochen <[email protected]>
2 parents 661e3f9 + e8d0742 commit 4ec6bd6

File tree

1 file changed

+283
-6
lines changed

1 file changed

+283
-6
lines changed

crates/ide_assists/src/handlers/move_guard.rs

Lines changed: 283 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use syntax::{
2-
ast::{edit::AstNodeEdit, make, AstNode, BlockExpr, Expr, IfExpr, MatchArm},
3-
SyntaxKind::WHITESPACE,
2+
ast::{edit::AstNodeEdit, make, AstNode, BlockExpr, ElseBranch, Expr, IfExpr, MatchArm},
3+
NodeOrToken,
4+
SyntaxKind::{COMMA, WHITESPACE},
45
};
56

67
use crate::{AssistContext, AssistId, AssistKind, Assists};
@@ -118,10 +119,6 @@ pub(crate) fn move_arm_cond_to_match_guard(acc: &mut Assists, ctx: &AssistContex
118119
let cond = if_expr.condition()?;
119120
let then_block = if_expr.then_branch()?;
120121

121-
// Not support if with else branch
122-
if if_expr.else_branch().is_some() {
123-
return None;
124-
}
125122
// Not support moving if let to arm guard
126123
if cond.is_pattern_cond() {
127124
return None;
@@ -149,6 +146,37 @@ pub(crate) fn move_arm_cond_to_match_guard(acc: &mut Assists, ctx: &AssistContex
149146
}
150147

151148
edit.insert(match_pat.syntax().text_range().end(), buf);
149+
150+
// If with only an else branch
151+
if let Some(ElseBranch::Block(else_block)) = if_expr.else_branch() {
152+
let then_arm_end = match_arm.syntax().text_range().end();
153+
if then_block.tail_expr().is_some() && then_only_expr {
154+
// Insert comma for expression if there isn't one
155+
match match_arm.syntax().last_child_or_token() {
156+
Some(NodeOrToken::Token(t)) if t.kind() == COMMA => {}
157+
_ => edit.insert(then_arm_end, ","),
158+
}
159+
}
160+
let else_only_expr = else_block.statements().next().is_none();
161+
let indent_level = match_arm.indent_level();
162+
let spaces = " ".repeat(indent_level.0 as _);
163+
edit.insert(then_arm_end, format!("\n{}{} => ", spaces, match_pat));
164+
match &else_block.tail_expr() {
165+
Some(else_expr) if else_only_expr => {
166+
cov_mark::hit!(move_guard_ifelse_expr_only);
167+
edit.insert(then_arm_end, else_expr.syntax().text());
168+
edit.insert(then_arm_end, ",");
169+
}
170+
_ if replace_node != *if_expr.syntax() => {
171+
cov_mark::hit!(move_guard_ifelse_in_block);
172+
edit.insert(then_arm_end, else_block.dedent(1.into()).syntax().text());
173+
}
174+
_ => {
175+
cov_mark::hit!(move_guard_ifelse_else_block);
176+
edit.insert(then_arm_end, else_block.syntax().text());
177+
}
178+
}
179+
}
152180
},
153181
)
154182
}
@@ -384,6 +412,255 @@ fn main() {
384412
_ => true
385413
}
386414
}
415+
"#,
416+
)
417+
}
418+
419+
#[test]
420+
fn move_arm_cond_to_match_guard_with_else_works() {
421+
check_assist(
422+
move_arm_cond_to_match_guard,
423+
r#"
424+
fn main() {
425+
match 92 {
426+
x => if x > 10 {$0
427+
false
428+
} else {
429+
true
430+
}
431+
_ => true,
432+
}
433+
}
434+
"#,
435+
r#"
436+
fn main() {
437+
match 92 {
438+
x if x > 10 => false,
439+
x => true,
440+
_ => true,
441+
}
442+
}
443+
"#,
444+
)
445+
}
446+
447+
#[test]
448+
fn move_arm_cond_to_match_guard_with_else_block_works() {
449+
cov_mark::check!(move_guard_ifelse_expr_only);
450+
check_assist(
451+
move_arm_cond_to_match_guard,
452+
r#"
453+
fn main() {
454+
match 92 {
455+
x => {
456+
if x > 10 {$0
457+
false
458+
} else {
459+
true
460+
}
461+
}
462+
_ => true
463+
}
464+
}
465+
"#,
466+
r#"
467+
fn main() {
468+
match 92 {
469+
x if x > 10 => false,
470+
x => true,
471+
_ => true
472+
}
473+
}
474+
"#,
475+
)
476+
}
477+
478+
#[test]
479+
fn move_arm_cond_to_match_guard_else_if_empty_body_works() {
480+
check_assist(
481+
move_arm_cond_to_match_guard,
482+
r#"
483+
fn main() {
484+
match 92 {
485+
x => if x > 10 { $0 } else { },
486+
_ => true
487+
}
488+
}
489+
"#,
490+
r#"
491+
fn main() {
492+
match 92 {
493+
x if x > 10 => { },
494+
x => { }
495+
_ => true
496+
}
497+
}
498+
"#,
499+
);
500+
}
501+
502+
#[test]
503+
fn move_arm_cond_to_match_guard_with_else_multiline_works() {
504+
check_assist(
505+
move_arm_cond_to_match_guard,
506+
r#"
507+
fn main() {
508+
match 92 {
509+
x => if x > 10 {
510+
92;$0
511+
false
512+
} else {
513+
true
514+
}
515+
_ => true
516+
}
517+
}
518+
"#,
519+
r#"
520+
fn main() {
521+
match 92 {
522+
x if x > 10 => {
523+
92;
524+
false
525+
}
526+
x => true,
527+
_ => true
528+
}
529+
}
530+
"#,
531+
)
532+
}
533+
534+
#[test]
535+
fn move_arm_cond_to_match_guard_with_else_multiline_else_works() {
536+
cov_mark::check!(move_guard_ifelse_else_block);
537+
check_assist(
538+
move_arm_cond_to_match_guard,
539+
r#"
540+
fn main() {
541+
match 92 {
542+
x => if x > 10 {$0
543+
false
544+
} else {
545+
42;
546+
true
547+
}
548+
_ => true
549+
}
550+
}
551+
"#,
552+
r#"
553+
fn main() {
554+
match 92 {
555+
x if x > 10 => false,
556+
x => {
557+
42;
558+
true
559+
}
560+
_ => true
561+
}
562+
}
563+
"#,
564+
)
565+
}
566+
567+
#[test]
568+
fn move_arm_cond_to_match_guard_with_else_multiline_else_block_works() {
569+
cov_mark::check!(move_guard_ifelse_in_block);
570+
check_assist(
571+
move_arm_cond_to_match_guard,
572+
r#"
573+
fn main() {
574+
match 92 {
575+
x => {
576+
if x > 10 {$0
577+
false
578+
} else {
579+
42;
580+
true
581+
}
582+
}
583+
_ => true
584+
}
585+
}
586+
"#,
587+
r#"
588+
fn main() {
589+
match 92 {
590+
x if x > 10 => false,
591+
x => {
592+
42;
593+
true
594+
}
595+
_ => true
596+
}
597+
}
598+
"#,
599+
)
600+
}
601+
602+
#[test]
603+
fn move_arm_cond_to_match_guard_with_else_last_arm_works() {
604+
check_assist(
605+
move_arm_cond_to_match_guard,
606+
r#"
607+
fn main() {
608+
match 92 {
609+
3 => true,
610+
x => {
611+
if x > 10 {$0
612+
false
613+
} else {
614+
92;
615+
true
616+
}
617+
}
618+
}
619+
}
620+
"#,
621+
r#"
622+
fn main() {
623+
match 92 {
624+
3 => true,
625+
x if x > 10 => false,
626+
x => {
627+
92;
628+
true
629+
}
630+
}
631+
}
632+
"#,
633+
)
634+
}
635+
636+
#[test]
637+
fn move_arm_cond_to_match_guard_with_else_comma_works() {
638+
check_assist(
639+
move_arm_cond_to_match_guard,
640+
r#"
641+
fn main() {
642+
match 92 {
643+
3 => true,
644+
x => if x > 10 {$0
645+
false
646+
} else {
647+
92;
648+
true
649+
},
650+
}
651+
}
652+
"#,
653+
r#"
654+
fn main() {
655+
match 92 {
656+
3 => true,
657+
x if x > 10 => false,
658+
x => {
659+
92;
660+
true
661+
}
662+
}
663+
}
387664
"#,
388665
)
389666
}

0 commit comments

Comments
 (0)