From 54142954e5c67a4c9274a1ea29d26b5bd72df694 Mon Sep 17 00:00:00 2001 From: Flier Lu Date: Fri, 11 May 2018 17:48:06 +0800 Subject: [PATCH 1/4] normalize match reference style, #929 --- Configurations.md | 43 ++++++ src/config/mod.rs | 2 + src/config/options.rs | 19 +++ src/matches.rs | 124 +++++++++++++++++- .../configs/match_reference_style/auto.rs | 23 ++++ .../match_reference_style/derefence.rs | 23 ++++ .../match_reference_style/reference.rs | 23 ++++ .../configs/match_reference_style/auto.rs | 23 ++++ .../match_reference_style/derefence.rs | 23 ++++ .../match_reference_style/reference.rs | 23 ++++ 10 files changed, 323 insertions(+), 3 deletions(-) create mode 100644 tests/source/configs/match_reference_style/auto.rs create mode 100644 tests/source/configs/match_reference_style/derefence.rs create mode 100644 tests/source/configs/match_reference_style/reference.rs create mode 100644 tests/target/configs/match_reference_style/auto.rs create mode 100644 tests/target/configs/match_reference_style/derefence.rs create mode 100644 tests/target/configs/match_reference_style/reference.rs diff --git a/Configurations.md b/Configurations.md index 07a336d93fa..f928137e678 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1930,6 +1930,49 @@ fn main() { See also: [`match_block_trailing_comma`](#match_block_trailing_comma). +## `match_reference_style` + +Normalize match reference style + +- **Default value**: `dereference` +- **Possible values**: `reference`, `dereference`, `auto` +- **Stable**: No + +**Note:** `auto` style need Rust v1.26.0 or later + +#### `reference` + +```rust +fn hello(name: &Option<&str>) { + match name { + &Some(name) => println!("Hello {}!", name), + &None => println!("I don't know who you are."), + } +} +``` + +#### `dereference` + +```rust +fn hello(name: &Option<&str>) { + match *name { + Some(name) => println!("Hello {}!", name), + None => println!("I don't know who you are."), + } +} +``` + +#### `auto` + +```rust +fn hello(name: &Option<&str>) { + match name { + Some(name) => println!("Hello {}!", name), + None => println!("I don't know who you are."), + } +} +``` + ## `write_mode` What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage diff --git a/src/config/mod.rs b/src/config/mod.rs index ac81ded5f76..221959db98e 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -91,6 +91,8 @@ create_config! { 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_reference_style: MatchReferenceStyle, MatchReferenceStyle::Manual, false, + "Normalize match reference style"; force_multiline_blocks: bool, false, false, "Force multiline closure bodies and match arms to be wrapped in a block"; fn_args_density: Density, Density::Tall, false, "Argument density in functions"; diff --git a/src/config/options.rs b/src/config/options.rs index a11e1f01eaf..ccefc5ce78f 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -141,6 +141,25 @@ configuration_option_enum! { IndentStyle: Block, } +configuration_option_enum! { MatchReferenceStyle: + Manual, + // match x { + // &A => ..., + // ... + // } + Reference, + // match *x { + // A => ..., + // ... + // } + Dereference, + // match x { + // A => ..., + // ... + // } + Auto +} + configuration_option_enum! { Density: // Fit as much on one line as possible. Compressed, diff --git a/src/matches.rs b/src/matches.rs index 0bbdbe62017..192d92d6e72 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -18,7 +18,7 @@ use syntax::{ast, ptr}; use codemap::SpanUtils; use comment::combine_strs_with_missing_comments; -use config::{Config, ControlBraceStyle, IndentStyle}; +use config::{Config, ControlBraceStyle, IndentStyle, MatchReferenceStyle}; use expr::{ format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, rewrite_multiple_patterns, ExprType, RhsTactics, ToExpr, @@ -91,7 +91,7 @@ pub fn rewrite_match( IndentStyle::Visual => cond_shape.shrink_left(6)?, IndentStyle::Block => cond_shape.offset_left(6)?, }; - let cond_str = cond.rewrite(context, cond_shape)?; + let mut cond_str = cond.rewrite(context, cond_shape)?; let alt_block_sep = &shape.indent.to_string_with_newline(context.config); let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine => alt_block_sep, @@ -138,13 +138,28 @@ pub fn rewrite_match( } } else { let span_after_cond = mk_sp(cond.span.hi(), span.hi()); + let mut arms_str = + rewrite_match_arms(context, arms, shape, span_after_cond, open_brace_pos)?; + + rewrite_match_reference_style( + context, + cond, + arms, + shape, + cond_shape, + span_after_cond, + open_brace_pos, + &mut cond_str, + &mut arms_str, + )?; + Some(format!( "match {}{}{{\n{}{}{}\n{}}}", cond_str, block_sep, inner_attrs_str, nested_indent_str, - rewrite_match_arms(context, arms, shape, span_after_cond, open_brace_pos)?, + arms_str, shape.indent.to_string(context.config), )) } @@ -183,6 +198,109 @@ fn collect_beginning_verts( beginning_verts } +fn rewrite_match_reference_style( + context: &RewriteContext, + cond: &ast::Expr, + arms: &[ast::Arm], + shape: Shape, + cond_shape: Shape, + span_after_cond: Span, + open_brace_pos: BytePos, + cond_str: &mut String, + arms_str: &mut String, +) -> Option<()> { + let match_in_reference_style = arms.iter().all(|arm| { + arm.pats.iter().all(|pat| match pat.node { + ast::PatKind::Wild | ast::PatKind::Ref(..) => true, + _ => false, + }) + }); + let match_in_derefrence_style = match cond.node { + ast::ExprKind::Unary(ast::UnOp::Deref, _) => true, + _ => false, + }; + + let prepend_arms_ref = || { + arms.iter() + .map(|arm| { + let pats = arm + .pats + .iter() + .map(|pat| { + ptr::P(ast::Pat { + id: pat.id, + node: ast::PatKind::Ref(pat.clone(), ast::Mutability::Immutable), + span: pat.span, + }) + }) + .collect::>(); + + ast::Arm { + pats, + ..arm.clone() + } + }) + .collect::>() + }; + + let strip_arms_ref = || { + arms.iter() + .map(|arm| { + let pats = arm + .pats + .iter() + .map(|pat| match pat.node { + ast::PatKind::Ref(ref pat, _) => pat, + _ => pat, + }) + .cloned() + .collect::>(); + + ast::Arm { + pats, + ..arm.clone() + } + }) + .collect::>() + }; + + match context.config.match_reference_style() { + MatchReferenceStyle::Reference if match_in_derefrence_style => { + if let ast::ExprKind::Unary(ast::UnOp::Deref, ref cond) = cond.node { + *cond_str = cond.rewrite(context, cond_shape)?; + } + + let arms = prepend_arms_ref(); + + *arms_str = rewrite_match_arms(context, &arms, shape, span_after_cond, open_brace_pos)? + } + MatchReferenceStyle::Dereference if match_in_reference_style => { + let cond = ast::Expr { + node: ast::ExprKind::Unary(ast::UnOp::Deref, ptr::P(cond.clone())), + ..cond.clone() + }; + *cond_str = cond.rewrite(context, cond_shape)?; + + let arms = strip_arms_ref(); + + *arms_str = rewrite_match_arms(context, &arms, shape, span_after_cond, open_brace_pos)? + } + MatchReferenceStyle::Auto if match_in_derefrence_style => { + if let ast::ExprKind::Unary(ast::UnOp::Deref, ref cond) = cond.node { + *cond_str = cond.rewrite(context, cond_shape)?; + } + } + MatchReferenceStyle::Auto if match_in_reference_style => { + let arms = strip_arms_ref(); + + *arms_str = rewrite_match_arms(context, &arms, shape, span_after_cond, open_brace_pos)? + } + _ => {} + } + + Some(()) +} + fn rewrite_match_arms( context: &RewriteContext, arms: &[ast::Arm], diff --git a/tests/source/configs/match_reference_style/auto.rs b/tests/source/configs/match_reference_style/auto.rs new file mode 100644 index 00000000000..466edf3beeb --- /dev/null +++ b/tests/source/configs/match_reference_style/auto.rs @@ -0,0 +1,23 @@ +// rustfmt-match_reference_style: auto +// Normalize match reference style + +fn hello(name: &Option<&str>) { + match name { + &Some(name) => println!("Hello {}!", name), + &None => println!("I don't know who you are."), + } +} + +fn kiss(name: &Option<&str>) { + match *name { + Some(name) => println!("Kiss {}!", name), + None => println!("I don't know who you are."), + } +} + +fn main() { + let name = Some("rustfmt"); + + hello(&name); + kiss(&name); +} diff --git a/tests/source/configs/match_reference_style/derefence.rs b/tests/source/configs/match_reference_style/derefence.rs new file mode 100644 index 00000000000..bd0a65ec606 --- /dev/null +++ b/tests/source/configs/match_reference_style/derefence.rs @@ -0,0 +1,23 @@ +// rustfmt-match_reference_style: dereference +// Normalize match reference style + +fn hello(name: &Option<&str>) { + match name { + &Some(name) => println!("Hello {}!", name), + &None => println!("I don't know who you are."), + } +} + +fn kiss(name: &Option<&str>) { + match *name { + Some(name) => println!("Kiss {}!", name), + None => println!("I don't know who you are."), + } +} + +fn main() { + let name = Some("rustfmt"); + + hello(&name); + kiss(&name); +} diff --git a/tests/source/configs/match_reference_style/reference.rs b/tests/source/configs/match_reference_style/reference.rs new file mode 100644 index 00000000000..0921c20e3ff --- /dev/null +++ b/tests/source/configs/match_reference_style/reference.rs @@ -0,0 +1,23 @@ +// rustfmt-match_reference_style: reference +// Normalize match reference style + +fn hello(name: &Option<&str>) { + match name { + &Some(name) => println!("Hello {}!", name), + &None => println!("I don't know who you are."), + } +} + +fn kiss(name: &Option<&str>) { + match *name { + Some(name) => println!("Kiss {}!", name), + None => println!("I don't know who you are."), + } +} + +fn main() { + let name = Some("rustfmt"); + + hello(&name); + kiss(&name); +} diff --git a/tests/target/configs/match_reference_style/auto.rs b/tests/target/configs/match_reference_style/auto.rs new file mode 100644 index 00000000000..12f827c1374 --- /dev/null +++ b/tests/target/configs/match_reference_style/auto.rs @@ -0,0 +1,23 @@ +// rustfmt-match_reference_style: auto +// Normalize match reference style + +fn hello(name: &Option<&str>) { + match name { + Some(name) => println!("Hello {}!", name), + None => println!("I don't know who you are."), + } +} + +fn kiss(name: &Option<&str>) { + match name { + Some(name) => println!("Kiss {}!", name), + None => println!("I don't know who you are."), + } +} + +fn main() { + let name = Some("rustfmt"); + + hello(&name); + kiss(&name); +} diff --git a/tests/target/configs/match_reference_style/derefence.rs b/tests/target/configs/match_reference_style/derefence.rs new file mode 100644 index 00000000000..db4a0024892 --- /dev/null +++ b/tests/target/configs/match_reference_style/derefence.rs @@ -0,0 +1,23 @@ +// rustfmt-match_reference_style: dereference +// Normalize match reference style + +fn hello(name: &Option<&str>) { + match *name { + Some(name) => println!("Hello {}!", name), + None => println!("I don't know who you are."), + } +} + +fn kiss(name: &Option<&str>) { + match *name { + Some(name) => println!("Kiss {}!", name), + None => println!("I don't know who you are."), + } +} + +fn main() { + let name = Some("rustfmt"); + + hello(&name); + kiss(&name); +} diff --git a/tests/target/configs/match_reference_style/reference.rs b/tests/target/configs/match_reference_style/reference.rs new file mode 100644 index 00000000000..d6494e76622 --- /dev/null +++ b/tests/target/configs/match_reference_style/reference.rs @@ -0,0 +1,23 @@ +// rustfmt-match_reference_style: reference +// Normalize match reference style + +fn hello(name: &Option<&str>) { + match name { + &Some(name) => println!("Hello {}!", name), + &None => println!("I don't know who you are."), + } +} + +fn kiss(name: &Option<&str>) { + match name { + &Some(name) => println!("Kiss {}!", name), + &None => println!("I don't know who you are."), + } +} + +fn main() { + let name = Some("rustfmt"); + + hello(&name); + kiss(&name); +} From 3f7308d7055b0409dc2ab794acbf81162c35af5c Mon Sep 17 00:00:00 2001 From: Flier Lu Date: Fri, 11 May 2018 17:54:15 +0800 Subject: [PATCH 2/4] add `manual` style as default value --- Configurations.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Configurations.md b/Configurations.md index f928137e678..59b882dae4c 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1934,12 +1934,16 @@ See also: [`match_block_trailing_comma`](#match_block_trailing_comma). Normalize match reference style -- **Default value**: `dereference` -- **Possible values**: `reference`, `dereference`, `auto` +- **Default value**: `manual` +- **Possible values**: `manual`, `reference`, `dereference`, `auto` - **Stable**: No **Note:** `auto` style need Rust v1.26.0 or later +#### `manual` + +don't touch anything + #### `reference` ```rust From 797f7e0abade9d283d39b62e815714accec7d281 Mon Sep 17 00:00:00 2001 From: Flier Lu Date: Mon, 14 May 2018 11:41:17 +0800 Subject: [PATCH 3/4] fix wording issue --- Configurations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configurations.md b/Configurations.md index 59b882dae4c..88f5948a27c 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1938,7 +1938,7 @@ Normalize match reference style - **Possible values**: `manual`, `reference`, `dereference`, `auto` - **Stable**: No -**Note:** `auto` style need Rust v1.26.0 or later +**Note:** `auto` style requires Rust v1.26.0 or later #### `manual` From 1aa7e9035d0d9be710713077abb3dc9087d8f244 Mon Sep 17 00:00:00 2001 From: Flier Lu Date: Tue, 22 May 2018 10:49:05 +0800 Subject: [PATCH 4/4] Update Configurations.md --- Configurations.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Configurations.md b/Configurations.md index 640d3cf8046..cb2e1707150 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1932,14 +1932,6 @@ fn hello(name: &Option<&str>) { } ``` -## `write_mode` - -What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage - -- **Default value**: `"Overwrite"` -- **Possible values**: `"Checkstyle"`, `"Coverage"`, `"Diff"`, `"Display"`, `"Overwrite"`, `"Plain"`, `"Replace"` -- **Stable**: No - ## `blank_lines_upper_bound` Maximum number of blank lines which can be put between items. If more than this number of consecutive empty