Skip to content
179 changes: 179 additions & 0 deletions Configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -1604,6 +1604,185 @@ fn foo() {
}
```

## `match_arm_wrapping`

Controls when to block wrap match arm bodies.

- **Default value**: `"Default"`
- **Possible values**: `"Default"`, `"FitFirstLine"`, `"FitEntireBody"`, `"Always"`, `"Preserve`
- **Stable**: No (tracking issue: #4896)

### Example

#### Original code

```rust
#![rustfmt::skip]

fn main() {
match lorem {
1000 => foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x),
2000 => {
println!("{}", sit)
}
3000 => panic!(),
4000 => {
()
}
5000 => this.a_very_long_function_name(foo, bar, bazz, fizz, another_argument, some_more_arguments, which_dont_fit),
}
}
```

#### `"Default"` (default):

The default block wrapping settings, as described in the Style Guide.

```rust
fn main() {
match lorem {
1000 => {
foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x)
}
2000 => {
println!("{}", sit)
}
3000 => panic!(),
4000 => (),
5000 => this.a_very_long_function_name(
foo,
bar,
bazz,
fizz,
another_argument,
some_more_arguments,
which_dont_fit,
),
}
}
```

#### `"FitFirstLine"`:

Same as the default, except don't block wrap match arms when the opening line of its body can't fit on the same line as the `=>`.

```rust
fn main() {
match lorem {
1000 =>
foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x),
2000 => {
println!("{}", sit)
}
3000 => panic!(),
4000 => (),
5000 => this.a_very_long_function_name(
foo,
bar,
bazz,
fizz,
another_argument,
some_more_arguments,
which_dont_fit,
),
}
}
```

#### `"Always"`:

Always block wrap match arm bodies.

```rust
fn main() {
match lorem {
1000 => {
foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x)
}
2000 => {
println!("{}", sit)
}
3000 => {
panic!()
}
4000 => {
()
}
5000 => {
this.a_very_long_function_name(
foo,
bar,
bazz,
fizz,
another_argument,
some_more_arguments,
which_dont_fit,
)
}
}
}
```

#### `"Preserve"`:

Preserve block wrapping on match arm bodies if the developer originally had the body wrapped.

```rust
fn main() {
match lorem {
1000 => {
foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x)
}
2000 => {
println!("{}", sit)
}
3000 => panic!(),
4000 => {
()
}
5000 => this.a_very_long_function_name(
foo,
bar,
bazz,
fizz,
another_argument,
some_more_arguments,
which_dont_fit,
),
}
}
```

#### `"FitEntireBody"`:

Same as default, except block wrap the match arm if the entire body cannot fit on the same line as the `=>`.

```rust
fn main() {
match lorem {
1000 => {
foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x)
}
2000 => {
println!("{}", sit)
}
3000 => panic!(),
4000 => (),
5000 => {
this.a_very_long_function_name(
foo,
bar,
bazz,
fizz,
another_argument,
some_more_arguments,
which_dont_fit,
)
}
}
}
```

## `match_block_trailing_comma`

Put a trailing comma after a block based match arm (non-block arms are not affected)
Expand Down
24 changes: 22 additions & 2 deletions src/config/config_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ macro_rules! create_config {
| "chain_width" => self.0.set_heuristics(),
"license_template_path" => self.0.set_license_template(),
"merge_imports" => self.0.set_merge_imports(),
"match_arm_blocks" => self.0.set_match_arm_blocks(),
&_ => (),
}
}
Expand Down Expand Up @@ -166,6 +167,7 @@ macro_rules! create_config {
self.set_license_template();
self.set_ignore(dir);
self.set_merge_imports();
self.set_match_arm_blocks();
self
}

Expand Down Expand Up @@ -249,14 +251,16 @@ macro_rules! create_config {
| "chain_width" => self.set_heuristics(),
"license_template_path" => self.set_license_template(),
"merge_imports" => self.set_merge_imports(),
"match_arm_blocks" => self.set_match_arm_blocks(),
&_ => (),
}
}

#[allow(unreachable_pub)]
pub fn is_hidden_option(name: &str) -> bool {
const HIDE_OPTIONS: [&str; 5] =
["verbose", "verbose_diff", "file_lines", "width_heuristics", "merge_imports"];
const HIDE_OPTIONS: [&str; 6] =
["verbose", "verbose_diff", "file_lines", "width_heuristics", "merge_imports",
"match_arm_blocks"];
HIDE_OPTIONS.contains(&name)
}

Expand Down Expand Up @@ -421,6 +425,22 @@ macro_rules! create_config {
}
}

fn set_match_arm_blocks(&mut self) {
if self.was_set().match_arm_blocks() {
eprintln!(
"Warning: the `match_arm_blocks` option is deprecated. \
Use `match_arm_wrapping` instead"
);
if !self.was_set().match_arm_wrapping() {
self.match_arm_wrapping.2 = if self.match_arm_blocks() {
MatchArmWrapping::Default
} else {
MatchArmWrapping::FitFirstLine
};
}
}
}

#[allow(unreachable_pub)]
/// Returns `true` if the config key was explicitly set and is the default value.
pub fn is_default(&self, key: &str) -> bool {
Expand Down
73 changes: 71 additions & 2 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,9 @@ create_config! {
"Align struct fields if their diffs fits within threshold";
enum_discrim_align_threshold: usize, 0, false,
"Align enum variants discrims, if their diffs fit within threshold";
match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \
the same line with the pattern of arms";
match_arm_wrapping: MatchArmWrapping, MatchArmWrapping::Default, false,
"Wrap the body of match arms according to the given options";
match_arm_blocks: bool, true, false, "(deprecated: use match_arm_wrapping instead)";
match_arm_leading_pipes: MatchArmLeadingPipe, MatchArmLeadingPipe::Never, true,
"Determines whether leading pipes are emitted on match arms";
force_multiline_blocks: bool, false, false,
Expand Down Expand Up @@ -426,6 +427,11 @@ mod test {
"Merge imports";
merge_imports: bool, false, false, "(deprecated: use imports_granularity instead)";

// match_arm_blocks deprecation
match_arm_blocks: bool, true, false, "(deprecated: use match_arm_wrapping instead)";
match_arm_wrapping: MatchArmWrapping, MatchArmWrapping::Default, false,
"Wrap the body of match arms according to the given options";

// Width Heuristics
use_small_heuristics: Heuristics, Heuristics::Default, true,
"Whether to use different formatting for items and \
Expand Down Expand Up @@ -590,6 +596,7 @@ combine_control_expr = true
overflow_delimited_expr = false
struct_field_align_threshold = 0
enum_discrim_align_threshold = 0
match_arm_wrapping = "Default"
match_arm_blocks = true
match_arm_leading_pipes = "Never"
force_multiline_blocks = false
Expand Down Expand Up @@ -723,6 +730,68 @@ make_backup = false
}
}

#[cfg(test)]
mod deprecated_option_match_arm_blocks {
use super::*;

#[test]
fn test_old_option_set() {
if !crate::is_nightly_channel!() {
return;
}
// Old option defaults to true - set it to false
let toml = r#"
unstable_features = true
match_arm_blocks = false
"#;
let config = Config::from_toml(toml, Path::new("")).unwrap();
assert_eq!(config.match_arm_wrapping(), MatchArmWrapping::FitFirstLine);
}

#[test]
fn test_both_set() {
if !crate::is_nightly_channel!() {
return;
}
let toml = r#"
unstable_features = true
match_arm_blocks = false
match_arm_wrapping = "Default"
"#;
let config = Config::from_toml(toml, Path::new("")).unwrap();
assert_eq!(config.match_arm_wrapping(), MatchArmWrapping::Default);
}

#[test]
fn test_new_overridden() {
if !crate::is_nightly_channel!() {
return;
}
let toml = r#"
unstable_features = true
merge_imports = false
"#;
let mut config = Config::from_toml(toml, Path::new("")).unwrap();
config.override_value("match_arm_wrapping", "Default");
assert_eq!(config.match_arm_wrapping(), MatchArmWrapping::Default);
}

#[test]
fn test_old_overridden() {
if !crate::is_nightly_channel!() {
return;
}
let toml = r#"
unstable_features = true
match_arm_wrapping = "FitFirstLine"
"#;
let mut config = Config::from_toml(toml, Path::new("")).unwrap();
config.override_value("match_arm_blocks", "false");
// no effect: the new option always takes precedence
assert_eq!(config.match_arm_wrapping(), MatchArmWrapping::FitFirstLine);
}
}

#[cfg(test)]
mod use_small_heuristics {
use super::*;
Expand Down
17 changes: 17 additions & 0 deletions src/config/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,3 +442,20 @@ pub enum MatchArmLeadingPipe {
/// Preserve any existing leading pipes
Preserve,
}

/// Controls wrapping for match arm bodies
#[config_type]
pub enum MatchArmWrapping {
/// Follow the Style Guide Prescription
Default,
/// Same as Default, except don't block wrap match arms when the opening line of its body
/// can't fit on the same line as the `=>`.
FitFirstLine,
/// Always block wrap match arms
Always,
/// Preserve the block wrapping on match arms
Preserve,
/// Same as Default, except wrap the match arm if the entire body cannot fit on the same line
/// as the `=>`.
FitEntireBody,
}
Loading