From 6b83062fef326f5625f9e380522164fc4d9d16a2 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 20 Apr 2020 21:47:09 -0500 Subject: [PATCH 1/3] feat: support configurability of leading pipe --- rustfmt-core/rustfmt-lib/src/config.rs | 3 +++ .../rustfmt-lib/src/config/options.rs | 11 +++++++++ rustfmt-core/rustfmt-lib/src/matches.rs | 24 +++++++++++++++---- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/rustfmt-core/rustfmt-lib/src/config.rs b/rustfmt-core/rustfmt-lib/src/config.rs index 17c654a7ecf..6e7169e12c0 100644 --- a/rustfmt-core/rustfmt-lib/src/config.rs +++ b/rustfmt-core/rustfmt-lib/src/config.rs @@ -105,6 +105,8 @@ create_config! { "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_leading_pipes: MatchArmLeadingPipe, MatchArmLeadingPipe::Never, true, + "Determines whether leading pipes are emitted on match arms"; force_multiline_blocks: bool, false, false, "Force multiline closure bodies and match arms to be wrapped in a block"; fn_args_layout: Density, Density::Tall, true, @@ -551,6 +553,7 @@ overflow_delimited_expr = false struct_field_align_threshold = 0 enum_discrim_align_threshold = 0 match_arm_blocks = true +match_arm_leading_pipes = "Never" force_multiline_blocks = false fn_args_layout = "Tall" brace_style = "SameLineWhere" diff --git a/rustfmt-core/rustfmt-lib/src/config/options.rs b/rustfmt-core/rustfmt-lib/src/config/options.rs index d93491a6ce0..5de1f03fae5 100644 --- a/rustfmt-core/rustfmt-lib/src/config/options.rs +++ b/rustfmt-core/rustfmt-lib/src/config/options.rs @@ -376,3 +376,14 @@ impl From for rustc_span::edition::Edition { } } } + +/// Controls how rustfmt should handle leading pipes on match arms. +#[config_type] +pub enum MatchArmLeadingPipe { + /// Place leading pipes on all match arms + Always, + /// Never emit leading pipes on match arms + Never, + /// Maintain any existing leading pipes + KeepExisting, +} diff --git a/rustfmt-core/rustfmt-lib/src/matches.rs b/rustfmt-core/rustfmt-lib/src/matches.rs index c11c65aac89..0f3d835bcce 100644 --- a/rustfmt-core/rustfmt-lib/src/matches.rs +++ b/rustfmt-core/rustfmt-lib/src/matches.rs @@ -7,7 +7,7 @@ use rustc_span::{BytePos, Span}; use crate::comment::{combine_strs_with_missing_comments, rewrite_comment}; use crate::config::lists::*; -use crate::config::{Config, ControlBraceStyle, IndentStyle}; +use crate::config::{Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe}; use crate::expr::{ format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, rewrite_cond, ExprType, RhsTactics, @@ -55,7 +55,13 @@ impl<'a> Spanned for ArmWrapper<'a> { impl<'a> Rewrite for ArmWrapper<'a> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - rewrite_match_arm(context, self.arm, shape, self.is_last) + rewrite_match_arm( + context, + self.arm, + shape, + self.is_last, + self.beginning_vert.is_some(), + ) } } @@ -215,6 +221,7 @@ fn rewrite_match_arm( arm: &ast::Arm, shape: Shape, is_last: bool, + has_leading_pipe: bool, ) -> Option { let (missing_span, attrs_str) = if !arm.attrs.is_empty() { if contains_skip(&arm.attrs) { @@ -232,9 +239,18 @@ fn rewrite_match_arm( (mk_sp(arm.span().lo(), arm.span().lo()), String::new()) }; + // Leading pipe offset + // 2 = `| ` + let (pipe_offset, pipe_str) = match context.config.match_arm_leading_pipes() { + MatchArmLeadingPipe::Never => (0, ""), + MatchArmLeadingPipe::KeepExisting if !has_leading_pipe => (0, ""), + MatchArmLeadingPipe::KeepExisting | MatchArmLeadingPipe::Always => (2, "| "), + }; + // Patterns // 5 = ` => {` - let pat_shape = shape.sub_width(5)?; + let pat_shape = shape.sub_width(5)?.offset_left(pipe_offset)?; + let pats_str = arm.pat.rewrite(context, pat_shape)?; // Guard @@ -251,7 +267,7 @@ fn rewrite_match_arm( let lhs_str = combine_strs_with_missing_comments( context, &attrs_str, - &format!("{}{}", pats_str, guard_str), + &format!("{}{}{}", pipe_str, pats_str, guard_str), missing_span, shape, false, From fee465feebd093b799a17d7dd2d295e576747f81 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 20 Apr 2020 21:47:40 -0500 Subject: [PATCH 2/3] tests: add tests for leading pipe config --- .../configs/match_arm_leading_pipes/always.rs | 27 ++++++++++++++++++ .../match_arm_leading_pipes/keep_existing.rs | 28 +++++++++++++++++++ .../configs/match_arm_leading_pipes/never.rs | 28 +++++++++++++++++++ .../configs/match_arm_leading_pipes/always.rs | 27 ++++++++++++++++++ .../match_arm_leading_pipes/keep_existing.rs | 27 ++++++++++++++++++ .../configs/match_arm_leading_pipes/never.rs | 27 ++++++++++++++++++ 6 files changed, 164 insertions(+) create mode 100644 rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/always.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/keep_existing.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/never.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/always.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/keep_existing.rs create mode 100644 rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/never.rs diff --git a/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/always.rs b/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/always.rs new file mode 100644 index 00000000000..162d812d8cf --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/always.rs @@ -0,0 +1,27 @@ +// rustfmt-match_arm_leading_pipes: Always + +fn foo() { + match foo { + "foo" | "bar" => {} + "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + "qux" => println!("y"), + _ => {} + } +} + +fn issue_3973() { + match foo { + "foo" | "bar" => {} + _ => {} + } +} + +fn bar() { + match baz { + "qux" => {} + "foo" | "bar" => {} + _ => {} + } +} diff --git a/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/keep_existing.rs b/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/keep_existing.rs new file mode 100644 index 00000000000..3980edb3dcd --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/keep_existing.rs @@ -0,0 +1,28 @@ +// rustfmt-match_arm_leading_pipes: KeepExisting + +fn foo() { + match foo { + | "foo" | "bar" => {} + | "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + | "qux" => println!("y"), + _ => {} + } +} + +fn issue_3973() { + match foo { + | "foo" + | "bar" => {} + _ => {} + } +} + +fn bar() { + match baz { + "qux" => { } + "foo" | "bar" => {} + _ => {} + } +} diff --git a/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/never.rs b/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/never.rs new file mode 100644 index 00000000000..8a68fe21407 --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/source/configs/match_arm_leading_pipes/never.rs @@ -0,0 +1,28 @@ +// rustfmt-match_arm_leading_pipes: Never + +fn foo() { + match foo { + | "foo" | "bar" => {} + | "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + | "qux" => println!("y"), + _ => {} + } +} + +fn issue_3973() { + match foo { + | "foo" + | "bar" => {} + _ => {} + } +} + +fn bar() { + match baz { + "qux" => {} + "foo" | "bar" => {} + _ => {} + } +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/always.rs b/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/always.rs new file mode 100644 index 00000000000..f2af81eac3c --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/always.rs @@ -0,0 +1,27 @@ +// rustfmt-match_arm_leading_pipes: Always + +fn foo() { + match foo { + | "foo" | "bar" => {} + | "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + | "qux" => println!("y"), + | _ => {} + } +} + +fn issue_3973() { + match foo { + | "foo" | "bar" => {} + | _ => {} + } +} + +fn bar() { + match baz { + | "qux" => {} + | "foo" | "bar" => {} + | _ => {} + } +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/keep_existing.rs b/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/keep_existing.rs new file mode 100644 index 00000000000..4b76f845e0a --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/keep_existing.rs @@ -0,0 +1,27 @@ +// rustfmt-match_arm_leading_pipes: KeepExisting + +fn foo() { + match foo { + | "foo" | "bar" => {} + | "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + | "qux" => println!("y"), + _ => {} + } +} + +fn issue_3973() { + match foo { + | "foo" | "bar" => {} + _ => {} + } +} + +fn bar() { + match baz { + "qux" => {} + "foo" | "bar" => {} + _ => {} + } +} diff --git a/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/never.rs b/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/never.rs new file mode 100644 index 00000000000..345014e4b4e --- /dev/null +++ b/rustfmt-core/rustfmt-lib/tests/target/configs/match_arm_leading_pipes/never.rs @@ -0,0 +1,27 @@ +// rustfmt-match_arm_leading_pipes: Never + +fn foo() { + match foo { + "foo" | "bar" => {} + "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + "qux" => println!("y"), + _ => {} + } +} + +fn issue_3973() { + match foo { + "foo" | "bar" => {} + _ => {} + } +} + +fn bar() { + match baz { + "qux" => {} + "foo" | "bar" => {} + _ => {} + } +} From 1239d7183bfb5bc9d9d1ece94e4dafeb62609aec Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 20 Apr 2020 21:48:22 -0500 Subject: [PATCH 3/3] docs: add config info for match_arm_leading_pipes --- Configurations.md | 82 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/Configurations.md b/Configurations.md index 6ba78e714e0..9ac95d80416 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1508,6 +1508,88 @@ fn main() { See also: [`match_block_trailing_comma`](#match_block_trailing_comma). +## `match_arm_leading_pipes` + +Controls whether to include a leading pipe on match arms + +- **Default value**: `Never` +- **Possible values**: `Always`, `Never`, `KeepExisting` +- **Stable**: Yes + +#### `Never` (default): +```rust +// Leading pipes are from this: +// fn foo() { +// match foo { +// | "foo" | "bar" => {} +// | "baz" +// | "something relatively long" +// | "something really really really realllllllllllllly long" => println!("x"), +// | "qux" => println!("y"), +// _ => {} +// } +// } + +// Are removed: +fn foo() { + match foo { + "foo" | "bar" => {} + "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + "qux" => println!("y"), + _ => {} + } +} +``` + +#### `Always`: +```rust +// Leading pipes are emitted on all arms of this: +// fn foo() { +// match foo { +// "foo" | "bar" => {} +// "baz" +// | "something relatively long" +// | "something really really really realllllllllllllly long" => println!("x"), +// "qux" => println!("y"), +// _ => {} +// } +// } + +// Becomes: +fn foo() { + match foo { + | "foo" | "bar" => {} + | "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + | "qux" => println!("y"), + | _ => {} + } +} +``` + +#### `KeepExisting`: +```rust +fn foo() { + match foo { + | "foo" | "bar" => {} + | "baz" + | "something relatively long" + | "something really really really realllllllllllllly long" => println!("x"), + | "qux" => println!("y"), + _ => {} + } + + match baz { + "qux" => {} + "foo" | "bar" => {} + _ => {} + } +} +``` + ## `match_block_trailing_comma` Put a trailing comma after a block based match arm (non-block arms are not affected)