diff --git a/src/config.rs b/src/config.rs index 176d40026d2..82715c2164a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -38,6 +38,13 @@ configuration_option_enum! { BraceStyle: SameLineWhere, } +configuration_option_enum! { ControlBraceStyle: + // K&R/Stroustrup style, Rust community default + AlwaysSameLine, + // Allman style + AlwaysNextLine, +} + configuration_option_enum! { ElseIfBraceStyle: // K&R style, Rust community default AlwaysSameLine, @@ -326,6 +333,8 @@ create_config! { item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums"; else_if_brace_style: ElseIfBraceStyle, ElseIfBraceStyle::AlwaysSameLine, "Brace style for if, else if, and else constructs"; + control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, + "Brace style for match, loop, for, and while constructs"; impl_empty_single_line: bool, true, "Put empty-body implementations on a single line"; fn_empty_single_line: bool, true, "Put empty-body functions on a single line"; fn_single_line: bool, false, "Put single-expression functions on a single line"; diff --git a/src/expr.rs b/src/expr.rs index 7b080760f38..248cc7e090a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -23,7 +23,7 @@ use string::{StringFormat, rewrite_string}; use utils::{CodeMapSpanUtils, extra_offset, last_line_width, wrap_str, binary_search, first_line_width, semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr}; use visitor::FmtVisitor; -use config::{Config, StructLitStyle, MultilineStyle, ElseIfBraceStyle}; +use config::{Config, StructLitStyle, MultilineStyle, ElseIfBraceStyle, ControlBraceStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; use types::rewrite_path; use items::{span_lo_for_arg, span_hi_for_arg}; @@ -648,14 +648,20 @@ impl<'a> Rewrite for Loop<'a> { None => String::new(), }; + let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); + let block_sep = match context.config.control_brace_style { + ControlBraceStyle::AlwaysNextLine => alt_block_sep.as_str(), + ControlBraceStyle::AlwaysSameLine => " ", + }; // FIXME: this drops any comment between "loop" and the block. self.block .rewrite(context, width, offset) .map(|result| { - format!("{}{}{} {}", + format!("{}{}{}{}{}", label_string, self.keyword, pat_expr_string, + block_sep, result) }) } @@ -940,7 +946,12 @@ fn rewrite_match(context: &RewriteContext, // `match `cond` {` let cond_budget = try_opt!(width.checked_sub(8)); let cond_str = try_opt!(cond.rewrite(context, cond_budget, offset + 6)); - let mut result = format!("match {} {{", cond_str); + let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); + let block_sep = match context.config.control_brace_style { + ControlBraceStyle::AlwaysSameLine => " ", + ControlBraceStyle::AlwaysNextLine => alt_block_sep.as_str(), + }; + let mut result = format!("match {}{}{{", cond_str, block_sep); let nested_context = context.nested_context(); let arm_indent = nested_context.block_indent; @@ -1099,6 +1110,7 @@ impl Rewrite for ast::Arm { }; let comma = arm_comma(&context.config, self, body); + let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() @@ -1112,12 +1124,17 @@ impl Rewrite for ast::Arm { false }; + let block_sep = match context.config.control_brace_style { + ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep.as_str(), + _ => " ", + }; match rewrite { Some(ref body_str) if !body_str.contains('\n') || !context.config.wrap_match_arms || is_block => { - return Some(format!("{}{} => {}{}", + return Some(format!("{}{} =>{}{}{}", attr_str.trim_left(), pats_str, + block_sep, body_str, comma)); } @@ -1145,10 +1162,14 @@ impl Rewrite for ast::Arm { ("", "") }; - Some(format!("{}{} =>{}\n{}{}\n{}{}", + let block_sep = match context.config.control_brace_style { + ControlBraceStyle::AlwaysNextLine => alt_block_sep, + ControlBraceStyle::AlwaysSameLine => String::from(body_prefix) + "\n", + }; + Some(format!("{}{} =>{}{}{}\n{}{}", attr_str.trim_left(), pats_str, - body_prefix, + block_sep, indent_str, next_line_body, offset.to_string(context.config), diff --git a/tests/source/control-brace-style-always-next-line.rs b/tests/source/control-brace-style-always-next-line.rs new file mode 100644 index 00000000000..9a2ec04e300 --- /dev/null +++ b/tests/source/control-brace-style-always-next-line.rs @@ -0,0 +1,44 @@ +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + loop { + (); + (); + } + + + 'loop_label: loop // loop comment + { + (); + } + + + cond = true; + while cond { + (); + } + + + 'while_label: while cond { // while comment + (); + } + + + for obj in iter { + for sub_obj in obj + { + 'nested_while_label: while cond { + (); + } + } + } + + match some_var { // match comment + pattern0 => val0, + pattern1 => val1, + pattern2 | pattern3 => { + do_stuff(); + val2 + }, + }; +} diff --git a/tests/source/control-brace-style-always-same-line.rs b/tests/source/control-brace-style-always-same-line.rs new file mode 100644 index 00000000000..52b0c8fdc46 --- /dev/null +++ b/tests/source/control-brace-style-always-same-line.rs @@ -0,0 +1,44 @@ +// rustfmt-control_brace_style: AlwaysSameLine + +fn main() { + loop { + (); + (); + } + + + 'loop_label: loop // loop comment + { + (); + } + + + cond = true; + while cond { + (); + } + + + 'while_label: while cond { // while comment + (); + } + + + for obj in iter { + for sub_obj in obj + { + 'nested_while_label: while cond { + (); + } + } + } + + match some_var { // match comment + pattern0 => val0, + pattern1 => val1, + pattern2 | pattern3 => { + do_stuff(); + val2 + }, + }; +} diff --git a/tests/target/control-brace-style-always-next-line.rs b/tests/target/control-brace-style-always-next-line.rs new file mode 100644 index 00000000000..534dfb89969 --- /dev/null +++ b/tests/target/control-brace-style-always-next-line.rs @@ -0,0 +1,52 @@ +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + loop + { + (); + (); + } + + + 'loop_label: loop + { + (); + } + + + cond = true; + while cond + { + (); + } + + + 'while_label: while cond + { + // while comment + (); + } + + + for obj in iter + { + for sub_obj in obj + { + 'nested_while_label: while cond + { + (); + } + } + } + + match some_var + { // match comment + pattern0 => val0, + pattern1 => val1, + pattern2 | pattern3 => + { + do_stuff(); + val2 + } + }; +} diff --git a/tests/target/control-brace-style-always-same-line.rs b/tests/target/control-brace-style-always-same-line.rs new file mode 100644 index 00000000000..60a07e46986 --- /dev/null +++ b/tests/target/control-brace-style-always-same-line.rs @@ -0,0 +1,43 @@ +// rustfmt-control_brace_style: AlwaysSameLine + +fn main() { + loop { + (); + (); + } + + + 'loop_label: loop { + (); + } + + + cond = true; + while cond { + (); + } + + + 'while_label: while cond { + // while comment + (); + } + + + for obj in iter { + for sub_obj in obj { + 'nested_while_label: while cond { + (); + } + } + } + + match some_var { // match comment + pattern0 => val0, + pattern1 => val1, + pattern2 | pattern3 => { + do_stuff(); + val2 + } + }; +}