Skip to content

Commit 190f37a

Browse files
Merge #9600
9600: fix: Single-line and nested blocks in the `unwrap_block` assist r=Veykril a=patrick-gu Fixes #8411 Rework the system for stripping whitespace and braces in the unwrap_block assist to allow correct unwrapping of blocks such as: ```rust { $0 0 } ``` into ```rust 0 ``` and nested blocks, such as: ```rust $0{ { 3 } } ``` into ```rust { 3 } ``` This is done by creating the `update_expr_string_with_pat` function (along with `update_expr_string` and `update_expr_string_without_newline`), which strips whitespace and braces in a way that ensures that only whitespace and a maximum of one brace are removed from the start and end of the expression string. I have also created several tests to ensure that this functionality works correctly. Co-authored-by: patrick-gu <[email protected]>
2 parents 95d8533 + 6c591a9 commit 190f37a

File tree

1 file changed

+112
-16
lines changed

1 file changed

+112
-16
lines changed

crates/ide_assists/src/handlers/unwrap_block.rs

Lines changed: 112 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,7 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
3939

4040
if matches!(parent.kind(), SyntaxKind::BLOCK_EXPR | SyntaxKind::EXPR_STMT) {
4141
return acc.add(assist_id, assist_label, target, |builder| {
42-
builder.replace(
43-
block.syntax().text_range(),
44-
update_expr_string(block.to_string(), &[' ', '{', '\n']),
45-
);
42+
builder.replace(block.syntax().text_range(), update_expr_string(block.to_string()));
4643
});
4744
}
4845

@@ -72,7 +69,7 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
7269
edit.delete(range_to_del_else_if);
7370
edit.replace(
7471
target,
75-
update_expr_string(then_branch.to_string(), &[' ', '{']),
72+
update_expr_string_without_newline(then_branch.to_string()),
7673
);
7774
});
7875
}
@@ -84,7 +81,7 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
8481
);
8582

8683
edit.delete(range_to_del);
87-
edit.replace(target, update_expr_string(block.to_string(), &[' ', '{']));
84+
edit.replace(target, update_expr_string_without_newline(block.to_string()));
8885
});
8986
}
9087
}
@@ -93,20 +90,31 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
9390

9491
let unwrapped = unwrap_trivial_block(block);
9592
acc.add(assist_id, assist_label, target, |builder| {
96-
builder.replace(
97-
parent.syntax().text_range(),
98-
update_expr_string(unwrapped.to_string(), &[' ', '{', '\n']),
99-
);
93+
builder.replace(parent.syntax().text_range(), update_expr_string(unwrapped.to_string()));
10094
})
10195
}
10296

103-
fn update_expr_string(expr_str: String, trim_start_pat: &[char]) -> String {
104-
let expr_string = expr_str.trim_start_matches(trim_start_pat);
105-
let mut expr_string_lines: Vec<&str> = expr_string.lines().collect();
106-
expr_string_lines.pop(); // Delete last line
97+
fn update_expr_string(expr_string: String) -> String {
98+
update_expr_string_with_pat(expr_string, &[' ', '\n'])
99+
}
100+
101+
fn update_expr_string_without_newline(expr_string: String) -> String {
102+
update_expr_string_with_pat(expr_string, &[' '])
103+
}
104+
105+
fn update_expr_string_with_pat(expr_str: String, whitespace_pat: &[char]) -> String {
106+
// Remove leading whitespace, index [1..] to remove the leading '{',
107+
// then continue to remove leading whitespace.
108+
let expr_str =
109+
expr_str.trim_start_matches(whitespace_pat)[1..].trim_start_matches(whitespace_pat);
107110

108-
expr_string_lines
109-
.into_iter()
111+
// Remove trailing whitespace, index [..expr_str.len() - 1] to remove the trailing '}',
112+
// then continue to remove trailing whitespace.
113+
let expr_str = expr_str.trim_end_matches(whitespace_pat);
114+
let expr_str = expr_str[..expr_str.len() - 1].trim_end_matches(whitespace_pat);
115+
116+
expr_str
117+
.lines()
110118
.map(|line| line.replacen(" ", "", 1)) // Delete indentation
111119
.collect::<Vec<String>>()
112120
.join("\n")
@@ -576,6 +584,94 @@ fn main() {
576584
}
577585
}
578586
}
587+
"#,
588+
);
589+
}
590+
591+
#[test]
592+
fn simple_single_line() {
593+
check_assist(
594+
unwrap_block,
595+
r#"
596+
fn main() {
597+
{$0 0 }
598+
}
599+
"#,
600+
r#"
601+
fn main() {
602+
0
603+
}
604+
"#,
605+
);
606+
}
607+
608+
#[test]
609+
fn simple_nested_block() {
610+
check_assist(
611+
unwrap_block,
612+
r#"
613+
fn main() {
614+
$0{
615+
{
616+
3
617+
}
618+
}
619+
}
620+
"#,
621+
r#"
622+
fn main() {
623+
{
624+
3
625+
}
626+
}
627+
"#,
628+
);
629+
}
630+
631+
#[test]
632+
fn nested_single_line() {
633+
check_assist(
634+
unwrap_block,
635+
r#"
636+
fn main() {
637+
{$0 { println!("foo"); } }
638+
}
639+
"#,
640+
r#"
641+
fn main() {
642+
{ println!("foo"); }
643+
}
644+
"#,
645+
);
646+
647+
check_assist(
648+
unwrap_block,
649+
r#"
650+
fn main() {
651+
{$0 { 0 } }
652+
}
653+
"#,
654+
r#"
655+
fn main() {
656+
{ 0 }
657+
}
658+
"#,
659+
);
660+
}
661+
662+
#[test]
663+
fn simple_if_single_line() {
664+
check_assist(
665+
unwrap_block,
666+
r#"
667+
fn main() {
668+
if true {$0 /* foo */ foo() } else { bar() /* bar */}
669+
}
670+
"#,
671+
r#"
672+
fn main() {
673+
/* foo */ foo()
674+
}
579675
"#,
580676
);
581677
}

0 commit comments

Comments
 (0)