Skip to content

Commit 68f04ce

Browse files
committed
Merge pull request #948 from flutterhash/master
Added option to configure if/else brace style
2 parents fe993db + d773cc5 commit 68f04ce

12 files changed

+589
-11
lines changed

src/config.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,22 @@ configuration_option_enum! { BraceStyle:
3838
SameLineWhere,
3939
}
4040

41+
configuration_option_enum! { ControlBraceStyle:
42+
// K&R/Stroustrup style, Rust community default
43+
AlwaysSameLine,
44+
// Allman style
45+
AlwaysNextLine,
46+
}
47+
48+
configuration_option_enum! { ElseIfBraceStyle:
49+
// K&R style, Rust community default
50+
AlwaysSameLine,
51+
// Stroustrup style
52+
ClosingNextLine,
53+
// Allman style
54+
AlwaysNextLine,
55+
}
56+
4157
// How to indent a function's return type.
4258
configuration_option_enum! { ReturnIndent:
4359
// Aligned with the arguments
@@ -315,6 +331,10 @@ create_config! {
315331
newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings";
316332
fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions";
317333
item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums";
334+
else_if_brace_style: ElseIfBraceStyle, ElseIfBraceStyle::AlwaysSameLine,
335+
"Brace style for if, else if, and else constructs";
336+
control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine,
337+
"Brace style for match, loop, for, and while constructs";
318338
impl_empty_single_line: bool, true, "Put empty-body implementations on a single line";
319339
fn_empty_single_line: bool, true, "Put empty-body functions on a single line";
320340
fn_single_line: bool, false, "Put single-expression functions on a single line";

src/expr.rs

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use string::{StringFormat, rewrite_string};
2323
use utils::{CodeMapSpanUtils, extra_offset, last_line_width, wrap_str, binary_search,
2424
first_line_width, semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr};
2525
use visitor::FmtVisitor;
26-
use config::{Config, StructLitStyle, MultilineStyle};
26+
use config::{Config, StructLitStyle, MultilineStyle, ElseIfBraceStyle, ControlBraceStyle};
2727
use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed};
2828
use types::rewrite_path;
2929
use items::{span_lo_for_arg, span_hi_for_arg};
@@ -648,14 +648,20 @@ impl<'a> Rewrite for Loop<'a> {
648648
None => String::new(),
649649
};
650650

651+
let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config);
652+
let block_sep = match context.config.control_brace_style {
653+
ControlBraceStyle::AlwaysNextLine => alt_block_sep.as_str(),
654+
ControlBraceStyle::AlwaysSameLine => " ",
655+
};
651656
// FIXME: this drops any comment between "loop" and the block.
652657
self.block
653658
.rewrite(context, width, offset)
654659
.map(|result| {
655-
format!("{}{}{} {}",
660+
format!("{}{}{}{}{}",
656661
label_string,
657662
self.keyword,
658663
pat_expr_string,
664+
block_sep,
659665
result)
660666
})
661667
}
@@ -701,12 +707,16 @@ fn rewrite_if_else(context: &RewriteContext,
701707
allow_single_line: bool)
702708
-> Option<String> {
703709
// 3 = "if ", 2 = " {"
710+
let pat_penalty = match context.config.else_if_brace_style {
711+
ElseIfBraceStyle::AlwaysNextLine => 3,
712+
_ => 3 + 2,
713+
};
704714
let pat_expr_string = try_opt!(rewrite_pat_expr(context,
705715
pat,
706716
cond,
707717
"let ",
708718
" =",
709-
try_opt!(width.checked_sub(3 + 2)),
719+
try_opt!(width.checked_sub(pat_penalty)),
710720
offset + 3));
711721

712722
// Try to format if-else on single line.
@@ -731,13 +741,19 @@ fn rewrite_if_else(context: &RewriteContext,
731741
offset,
732742
width);
733743

744+
let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config);
745+
let after_sep = match context.config.else_if_brace_style {
746+
ElseIfBraceStyle::AlwaysNextLine => alt_block_sep.as_str(),
747+
_ => " ",
748+
};
734749
let mut result = format!("if{}{}{}{}",
735750
between_if_cond_comment.as_ref().map_or(" ", |str| &**str),
736751
pat_expr_string,
737-
after_cond_comment.as_ref().map_or(" ", |str| &**str),
752+
after_cond_comment.as_ref().map_or(after_sep, |str| &**str),
738753
if_block_string);
739754

740755
if let Some(else_block) = else_block_opt {
756+
let mut last_in_chain = false;
741757
let rewrite = match else_block.node {
742758
// If the else expression is another if-else expression, prevent it
743759
// from being formatted on a single line.
@@ -763,7 +779,10 @@ fn rewrite_if_else(context: &RewriteContext,
763779
offset,
764780
false)
765781
}
766-
_ => else_block.rewrite(context, width, offset),
782+
_ => {
783+
last_in_chain = true;
784+
else_block.rewrite(context, width, offset)
785+
}
767786
};
768787

769788
let between_if_else_block = mk_sp(if_block.span.hi,
@@ -781,10 +800,20 @@ fn rewrite_if_else(context: &RewriteContext,
781800
else_block.span.lo);
782801
let after_else_comment = extract_comment(after_else, &context, offset, width);
783802

803+
let between_sep = match context.config.else_if_brace_style {
804+
ElseIfBraceStyle::AlwaysNextLine |
805+
ElseIfBraceStyle::ClosingNextLine => alt_block_sep.as_str(),
806+
ElseIfBraceStyle::AlwaysSameLine => " ",
807+
};
808+
let after_sep = match context.config.else_if_brace_style {
809+
ElseIfBraceStyle::AlwaysNextLine if last_in_chain => alt_block_sep.as_str(),
810+
_ => " ",
811+
};
784812
try_opt!(write!(&mut result,
785813
"{}else{}",
786-
between_if_else_block_comment.as_ref().map_or(" ", |str| &**str),
787-
after_else_comment.as_ref().map_or(" ", |str| &**str))
814+
between_if_else_block_comment.as_ref()
815+
.map_or(between_sep, |str| &**str),
816+
after_else_comment.as_ref().map_or(after_sep, |str| &**str))
788817
.ok());
789818
result.push_str(&&try_opt!(rewrite));
790819
}
@@ -917,7 +946,12 @@ fn rewrite_match(context: &RewriteContext,
917946
// `match `cond` {`
918947
let cond_budget = try_opt!(width.checked_sub(8));
919948
let cond_str = try_opt!(cond.rewrite(context, cond_budget, offset + 6));
920-
let mut result = format!("match {} {{", cond_str);
949+
let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config);
950+
let block_sep = match context.config.control_brace_style {
951+
ControlBraceStyle::AlwaysSameLine => " ",
952+
ControlBraceStyle::AlwaysNextLine => alt_block_sep.as_str(),
953+
};
954+
let mut result = format!("match {}{}{{", cond_str, block_sep);
921955

922956
let nested_context = context.nested_context();
923957
let arm_indent = nested_context.block_indent;
@@ -1076,6 +1110,7 @@ impl Rewrite for ast::Arm {
10761110
};
10771111

10781112
let comma = arm_comma(&context.config, self, body);
1113+
let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config);
10791114

10801115
// Let's try and get the arm body on the same line as the condition.
10811116
// 4 = ` => `.len()
@@ -1089,12 +1124,17 @@ impl Rewrite for ast::Arm {
10891124
false
10901125
};
10911126

1127+
let block_sep = match context.config.control_brace_style {
1128+
ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep.as_str(),
1129+
_ => " ",
1130+
};
10921131
match rewrite {
10931132
Some(ref body_str) if !body_str.contains('\n') || !context.config.wrap_match_arms ||
10941133
is_block => {
1095-
return Some(format!("{}{} => {}{}",
1134+
return Some(format!("{}{} =>{}{}{}",
10961135
attr_str.trim_left(),
10971136
pats_str,
1137+
block_sep,
10981138
body_str,
10991139
comma));
11001140
}
@@ -1122,10 +1162,14 @@ impl Rewrite for ast::Arm {
11221162
("", "")
11231163
};
11241164

1125-
Some(format!("{}{} =>{}\n{}{}\n{}{}",
1165+
let block_sep = match context.config.control_brace_style {
1166+
ControlBraceStyle::AlwaysNextLine => alt_block_sep,
1167+
ControlBraceStyle::AlwaysSameLine => String::from(body_prefix) + "\n",
1168+
};
1169+
Some(format!("{}{} =>{}{}{}\n{}{}",
11261170
attr_str.trim_left(),
11271171
pats_str,
1128-
body_prefix,
1172+
block_sep,
11291173
indent_str,
11301174
next_line_body,
11311175
offset.to_string(context.config),
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// rustfmt-control_brace_style: AlwaysNextLine
2+
3+
fn main() {
4+
loop {
5+
();
6+
();
7+
}
8+
9+
10+
'loop_label: loop // loop comment
11+
{
12+
();
13+
}
14+
15+
16+
cond = true;
17+
while cond {
18+
();
19+
}
20+
21+
22+
'while_label: while cond { // while comment
23+
();
24+
}
25+
26+
27+
for obj in iter {
28+
for sub_obj in obj
29+
{
30+
'nested_while_label: while cond {
31+
();
32+
}
33+
}
34+
}
35+
36+
match some_var { // match comment
37+
pattern0 => val0,
38+
pattern1 => val1,
39+
pattern2 | pattern3 => {
40+
do_stuff();
41+
val2
42+
},
43+
};
44+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// rustfmt-control_brace_style: AlwaysSameLine
2+
3+
fn main() {
4+
loop {
5+
();
6+
();
7+
}
8+
9+
10+
'loop_label: loop // loop comment
11+
{
12+
();
13+
}
14+
15+
16+
cond = true;
17+
while cond {
18+
();
19+
}
20+
21+
22+
'while_label: while cond { // while comment
23+
();
24+
}
25+
26+
27+
for obj in iter {
28+
for sub_obj in obj
29+
{
30+
'nested_while_label: while cond {
31+
();
32+
}
33+
}
34+
}
35+
36+
match some_var { // match comment
37+
pattern0 => val0,
38+
pattern1 => val1,
39+
pattern2 | pattern3 => {
40+
do_stuff();
41+
val2
42+
},
43+
};
44+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// rustfmt-else_if_brace_style: AlwaysNextLine
2+
3+
fn main() {
4+
if false
5+
{
6+
();
7+
();
8+
}
9+
10+
if false // lone if comment
11+
{
12+
();
13+
();
14+
}
15+
16+
17+
let a =
18+
if 0 > 1 {
19+
unreachable!()
20+
}
21+
else
22+
{
23+
0x0
24+
};
25+
26+
27+
if true
28+
{
29+
();
30+
} else if false {
31+
();
32+
();
33+
}
34+
else {
35+
();
36+
();
37+
();
38+
}
39+
40+
if true // else-if-chain if comment
41+
{
42+
();
43+
}
44+
else if false // else-if-chain else-if comment
45+
{
46+
();
47+
();
48+
} else // else-if-chain else comment
49+
{
50+
();
51+
();
52+
();
53+
}
54+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// rustfmt-else_if_brace_style: AlwaysSameLine
2+
3+
fn main() {
4+
if false
5+
{
6+
();
7+
();
8+
}
9+
10+
if false // lone if comment
11+
{
12+
();
13+
();
14+
}
15+
16+
17+
let a =
18+
if 0 > 1 {
19+
unreachable!()
20+
}
21+
else
22+
{
23+
0x0
24+
};
25+
26+
27+
if true
28+
{
29+
();
30+
} else if false {
31+
();
32+
();
33+
}
34+
else {
35+
();
36+
();
37+
();
38+
}
39+
40+
if true // else-if-chain if comment
41+
{
42+
();
43+
}
44+
else if false // else-if-chain else-if comment
45+
{
46+
();
47+
();
48+
} else // else-if-chain else comment
49+
{
50+
();
51+
();
52+
();
53+
}
54+
}

0 commit comments

Comments
 (0)