Skip to content

Commit 85d2403

Browse files
committed
feat: add match_arm_indent option
Allows to disable the indentation of match arms. Related issue: #2937
1 parent ee329d3 commit 85d2403

File tree

8 files changed

+139
-8
lines changed

8 files changed

+139
-8
lines changed

Configurations.md

+37-1
Original file line numberDiff line numberDiff line change
@@ -1862,6 +1862,42 @@ fn foo() {
18621862
}
18631863
```
18641864

1865+
## `match_arm_indent`
1866+
1867+
Controls whether match arms are indented. If disabled, the match patterns will be located on the indentation level as the match statement itself. This means match blocks will only be indented once, not twice.
1868+
1869+
- **Default value**: `true`
1870+
- **Possible values**: `true`, `false`
1871+
- **Stable**: No (TODO tracking issue)
1872+
1873+
#### `true` (default):
1874+
1875+
```rust
1876+
fn main() {
1877+
match value {
1878+
Enum::A => {
1879+
let mut work = first();
1880+
work += second();
1881+
}
1882+
Enum::B => short_work(),
1883+
}
1884+
}
1885+
```
1886+
1887+
#### `false`:
1888+
1889+
```rust
1890+
fn main() {
1891+
match value {
1892+
Enum::A => {
1893+
let mut work = first();
1894+
work += second();
1895+
}
1896+
Enum::B => short_work(),
1897+
}
1898+
}
1899+
```
1900+
18651901
## `match_block_trailing_comma`
18661902

18671903
Put a trailing comma after a block based match arm (non-block arms are not affected)
@@ -2475,7 +2511,7 @@ required_version=">=1.0.0, <2.0.0"
24752511

24762512
The width threshold for an array element to be considered "short".
24772513

2478-
The layout of an array is dependent on the length of each of its elements.
2514+
The layout of an array is dependent on the length of each of its elements.
24792515
If the length of every element in an array is below this threshold (all elements are "short") then the array can be formatted in the mixed/compressed style, but if any one element has a length that exceeds this threshold then the array elements will have to be formatted vertically.
24802516

24812517
- **Default value**: `10`

src/config/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ create_config! {
131131
on the same line with the pattern of arms";
132132
match_arm_leading_pipes: MatchArmLeadingPipeConfig, true,
133133
"Determines whether leading pipes are emitted on match arms";
134+
match_arm_indent: MatchArmIndent, false,
135+
"Determines whether match arms are indented";
134136
force_multiline_blocks: ForceMultilineBlocks, false,
135137
"Force multiline closure bodies and match arms to be wrapped in a block";
136138
fn_args_layout: FnArgsLayout, true,
@@ -803,6 +805,7 @@ struct_field_align_threshold = 0
803805
enum_discrim_align_threshold = 0
804806
match_arm_blocks = true
805807
match_arm_leading_pipes = "Never"
808+
match_arm_indent = true
806809
force_multiline_blocks = false
807810
fn_params_layout = "Tall"
808811
brace_style = "SameLineWhere"
@@ -894,6 +897,7 @@ struct_field_align_threshold = 0
894897
enum_discrim_align_threshold = 0
895898
match_arm_blocks = true
896899
match_arm_leading_pipes = "Never"
900+
match_arm_indent = true
897901
force_multiline_blocks = false
898902
fn_params_layout = "Tall"
899903
brace_style = "SameLineWhere"

src/config/options.rs

+1
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,7 @@ config_option_with_style_edition_default!(
665665
EnumDiscrimAlignThreshold, usize, _ => 0;
666666
MatchArmBlocks, bool, _ => true;
667667
MatchArmLeadingPipeConfig, MatchArmLeadingPipe, _ => MatchArmLeadingPipe::Never;
668+
MatchArmIndent, bool, _ => true;
668669
ForceMultilineBlocks, bool, _ => false;
669670
FnArgsLayout, Density, _ => Density::Tall;
670671
FnParamsLayout, Density, _ => Density::Tall;

src/matches.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -100,17 +100,22 @@ pub(crate) fn rewrite_match(
100100
_ => " ",
101101
};
102102

103-
let nested_indent_str = shape
104-
.indent
105-
.block_indent(context.config)
106-
.to_string(context.config);
103+
let nested_indent = if context.config.match_arm_indent() {
104+
shape.indent.block_indent(context.config)
105+
} else {
106+
shape.indent
107+
};
108+
let nested_indent_str = nested_indent.to_string(context.config);
109+
107110
// Inner attributes.
108111
let inner_attrs = &inner_attributes(attrs);
109112
let inner_attrs_str = if inner_attrs.is_empty() {
110113
String::new()
111114
} else {
112115
let shape = if context.config.style_edition() <= StyleEdition::Edition2021 {
113116
shape
117+
} else if !context.config.match_arm_indent() {
118+
shape
114119
} else {
115120
shape.block_indent(context.config.tab_spaces())
116121
};
@@ -204,9 +209,12 @@ fn rewrite_match_arms(
204209
span: Span,
205210
open_brace_pos: BytePos,
206211
) -> RewriteResult {
207-
let arm_shape = shape
208-
.block_indent(context.config.tab_spaces())
209-
.with_max_width(context.config);
212+
let arm_shape = if context.config.match_arm_indent() {
213+
shape.block_indent(context.config.tab_spaces())
214+
} else {
215+
shape
216+
}
217+
.with_max_width(context.config);
210218

211219
let arm_len = arms.len();
212220
let is_last_iter = repeat(false)

tests/source/match-unindent.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// rustfmt-match_arm_indent: false
2+
// Unindent the match arms
3+
4+
fn foo() {
5+
match x {
6+
a => {
7+
"line1";
8+
"line2"
9+
}
10+
ThisIsA::Guard if true => {
11+
"line1";
12+
"line2"
13+
}
14+
ThisIsA::ReallyLongPattern(ThatWillForce::TheGuard, ToWrapOnto::TheFollowingLine) if true => {
15+
"line1";
16+
"line2"
17+
}
18+
}
19+
}

tests/target/match-noindent-tab.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// rustfmt-match_arm_indent: false
2+
// rustfmt-hard_tabs: true
3+
// rustfmt-tab_spaces: 8
4+
5+
// Large-indentation style, brought to you by the Linux kernel
6+
fn foo() {
7+
match value {
8+
0 => {
9+
"one";
10+
"two";
11+
}
12+
1 | 2 | 3 => {
13+
"line1";
14+
"line2";
15+
}
16+
100..1000 => oneline(),
17+
18+
_ => {
19+
// catch-all
20+
todo!();
21+
}
22+
}
23+
}

tests/target/match-noindent.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// rustfmt-match_arm_indent: false
2+
// Don't indent the match arms
3+
4+
fn foo() {
5+
match value {
6+
0 => {
7+
"one";
8+
"two";
9+
}
10+
1 | 2 | 3 => {
11+
"line1";
12+
"line2";
13+
}
14+
100..1000 => oneline(),
15+
16+
_ => {
17+
// catch-all
18+
todo!();
19+
}
20+
}
21+
}

tests/target/match-unindent.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// rustfmt-match_arm_indent: false
2+
// Unindent the match arms
3+
4+
fn foo() {
5+
match x {
6+
a => {
7+
"line1";
8+
"line2"
9+
}
10+
ThisIsA::Guard if true => {
11+
"line1";
12+
"line2"
13+
}
14+
ThisIsA::ReallyLongPattern(ThatWillForce::TheGuard, ToWrapOnto::TheFollowingLine) if true => {
15+
"line1";
16+
"line2"
17+
}
18+
}
19+
}

0 commit comments

Comments
 (0)