Skip to content

Commit 50c1c83

Browse files
committed
single_line_if config option
1 parent cf18df7 commit 50c1c83

File tree

5 files changed

+82
-10
lines changed

5 files changed

+82
-10
lines changed

Configurations.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2481,6 +2481,34 @@ fn main() {
24812481

24822482
See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
24832483

2484+
## `single_line_simple_if`
2485+
2486+
Allows simple single expression if blocks to format on one line. Useful in the case of keeping `let-else` guards format consistent with `if` guards.
2487+
2488+
Note that line will still break if:
2489+
1. The condition length is over the `max_width`/`single_line_simple_if_max_width length`
2490+
2. The block contains a trailing semicolon
2491+
3. The block contains a single or multi-lined comment
2492+
2493+
- **Default value**: `false`
2494+
- **Possible values**: `true`, `false`
2495+
- **Stable**: No
2496+
2497+
#### `false` (default):
2498+
2499+
## `single_line_simple_if_max_width`
2500+
2501+
Maximum line length for single line if with a simple inner expression. Useful in the case of keeping `let-else` guards format consistent with `if` guards.
2502+
2503+
A value of `0` (zero) results in if-else expressions always being broken into multiple lines. Note this occurs when `use_small_heuristics` is set to `Off`.
2504+
2505+
- **Default value**: `50`
2506+
- **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
2507+
- **Stable**: Yes
2508+
2509+
By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `single_line_if_else_max_width` will take precedence.
2510+
2511+
See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
24842512

24852513
## `space_after_colon`
24862514

src/config/config_type.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ macro_rules! create_config {
122122
| "fn_call_width"
123123
| "single_line_if_else_max_width"
124124
| "single_line_let_else_max_width"
125+
| "single_line_simple_if_max_width"
125126
| "attr_fn_like_width"
126127
| "struct_lit_width"
127128
| "struct_variant_width"
@@ -273,6 +274,7 @@ macro_rules! create_config {
273274
| "fn_call_width"
274275
| "single_line_if_else_max_width"
275276
| "single_line_let_else_max_width"
277+
| "single_line_simple_if_max_width"
276278
| "attr_fn_like_width"
277279
| "struct_lit_width"
278280
| "struct_variant_width"
@@ -421,6 +423,14 @@ macro_rules! create_config {
421423
"single_line_let_else_max_width",
422424
);
423425
self.single_line_let_else_max_width.2 = single_line_let_else_max_width;
426+
427+
let single_line_simple_if_max_width = get_width_value(
428+
self.was_set().single_line_simple_if_max_width(),
429+
self.single_line_simple_if_max_width.2,
430+
heuristics.single_line_simple_if_max_width,
431+
"single_line_simple_if_max_width",
432+
);
433+
self.single_line_simple_if_max_width.2 = single_line_simple_if_max_width;
424434
}
425435

426436
fn set_heuristics(&mut self) {

src/config/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ create_config! {
6161
single_line_let_else_max_width: usize, 50, true, "Maximum line length for single line \
6262
let-else statements. A value of zero means always format the divergent `else` block \
6363
over multiple lines.";
64+
single_line_simple_if_max_width: usize, 50, false, "Maximum line length for single line \
65+
if statement. A value of zero means always format to multiple lines.";
6466

6567
// Comments. macros, and strings
6668
wrap_comments: bool, false, false, "Break comments to fit on the line";
@@ -81,6 +83,7 @@ create_config! {
8183
"Format hexadecimal integer literals";
8284

8385
// Single line expressions and items
86+
single_line_simple_if: bool, false, false, "Simple if statements can format to a single line";
8487
empty_item_single_line: bool, true, false,
8588
"Put empty-body functions and impls on a single line";
8689
struct_lit_single_line: bool, true, false,
@@ -490,6 +493,8 @@ mod test {
490493
single_line_let_else_max_width: usize, 50, false, "Maximum line length for single \
491494
line let-else statements. A value of zero means always format the divergent \
492495
`else` block over multiple lines.";
496+
single_line_simple_if_max_width: usize, 50, false, "Maximum line length for \
497+
single line if statement. A value of zero means always format to multiple lines.";
493498

494499
// Options that are used by the tests
495500
stable_option: bool, false, true, "A stable option";
@@ -634,6 +639,7 @@ array_width = 60
634639
chain_width = 60
635640
single_line_if_else_max_width = 50
636641
single_line_let_else_max_width = 50
642+
single_line_simple_if_max_width = 50
637643
wrap_comments = false
638644
format_code_in_doc_comments = false
639645
doc_comment_code_block_width = 100
@@ -645,6 +651,7 @@ format_macro_matchers = false
645651
format_macro_bodies = true
646652
skip_macro_invocations = []
647653
hex_literal_case = "Preserve"
654+
single_line_simple_if = false
648655
empty_item_single_line = true
649656
struct_lit_single_line = true
650657
fn_single_line = false

src/config/options.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ pub struct WidthHeuristics {
241241
// Maximum line length for single line let-else statements. A value of zero means
242242
// always format the divergent `else` block over multiple lines.
243243
pub(crate) single_line_let_else_max_width: usize,
244+
// Maximum line length for single line if statement.
245+
// A value of zero means always format to multiple lines.
246+
pub(crate) single_line_simple_if_max_width: usize,
244247
}
245248

246249
impl fmt::Display for WidthHeuristics {
@@ -261,6 +264,7 @@ impl WidthHeuristics {
261264
chain_width: usize::max_value(),
262265
single_line_if_else_max_width: 0,
263266
single_line_let_else_max_width: 0,
267+
single_line_simple_if_max_width: 0,
264268
}
265269
}
266270

@@ -274,6 +278,7 @@ impl WidthHeuristics {
274278
chain_width: max_width,
275279
single_line_if_else_max_width: max_width,
276280
single_line_let_else_max_width: max_width,
281+
single_line_simple_if_max_width: max_width,
277282
}
278283
}
279284

@@ -296,6 +301,7 @@ impl WidthHeuristics {
296301
chain_width: (60.0 * max_width_ratio).round() as usize,
297302
single_line_if_else_max_width: (50.0 * max_width_ratio).round() as usize,
298303
single_line_let_else_max_width: (50.0 * max_width_ratio).round() as usize,
304+
single_line_simple_if_max_width: (50.0 * max_width_ratio).round() as usize,
299305
}
300306
}
301307
}

src/expr.rs

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,16 +1102,31 @@ impl<'a> Rewrite for ControlFlow<'a> {
11021102
};
11031103
let block_str = {
11041104
let old_val = context.is_if_else_block.replace(self.else_block.is_some());
1105-
let allow_single_line =
1106-
allow_single_line_if(&cond_str, self.block) && self.keyword == "if";
1105+
let max_width = if context.config.single_line_simple_if() {
1106+
std::cmp::min(
1107+
shape.width,
1108+
context.config.single_line_simple_if_max_width(),
1109+
)
1110+
} else {
1111+
shape.width
1112+
};
1113+
let available_space = max_width.saturating_sub(used_width);
1114+
let allow_single_line = allow_single_line_if(&cond_str, self.block)
1115+
&& self.keyword == "if"
1116+
&& available_space > 0;
11071117

1108-
let result = if allow_single_line {
1109-
rewrite_block_inner(self.block, None, None, true, context, block_shape)
1118+
let mut result = if allow_single_line && context.config.single_line_simple_if() {
1119+
rewrite_block_inner(self.block, None, None, true, context, block_shape)?
11101120
} else {
1111-
rewrite_block_with_visitor(context, "", self.block, None, None, block_shape, true)
1121+
rewrite_block_with_visitor(context, "", self.block, None, None, block_shape, true)?
11121122
};
1123+
1124+
let block_exceeds_width = result.len() > available_space;
1125+
if allow_single_line && !result.contains('\n') && block_exceeds_width {
1126+
result = rewrite_block_inner(self.block, None, None, false, context, block_shape)?;
1127+
}
11131128
context.is_if_else_block.replace(old_val);
1114-
result?
1129+
result
11151130
};
11161131

11171132
let mut result = format!("{cond_str}{block_str}");
@@ -1168,20 +1183,26 @@ fn allow_single_line_if(result: &str, block: &ast::Block) -> bool {
11681183
if result.contains('\n') {
11691184
return false;
11701185
}
1171-
11721186
if block.stmts.len() == 0 {
11731187
return true;
11741188
}
11751189
if block.stmts.len() == 1 {
1176-
return is_simple_stmt(&block.stmts[0]);
1190+
return is_simple_control_flow_stmt(&block.stmts[0]);
11771191
}
11781192
false
11791193
}
11801194

1181-
fn is_simple_stmt(stmt: &ast::Stmt) -> bool {
1195+
fn is_simple_control_flow_stmt(stmt: &ast::Stmt) -> bool {
11821196
match stmt.kind {
11831197
ast::StmtKind::Expr(ref expr) => match expr.kind {
1184-
ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => true,
1198+
ast::ExprKind::Continue(..) => true,
1199+
ast::ExprKind::Break(_, ref opt_expr) | ast::ExprKind::Ret(ref opt_expr) => {
1200+
if let Some(_) = *opt_expr {
1201+
false
1202+
} else {
1203+
true
1204+
}
1205+
}
11851206
_ => false,
11861207
},
11871208
_ => false,

0 commit comments

Comments
 (0)