Skip to content

Commit

Permalink
single_line_if config option
Browse files Browse the repository at this point in the history
  • Loading branch information
Sjael committed Jan 24, 2024
1 parent cf18df7 commit 50c1c83
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 10 deletions.
28 changes: 28 additions & 0 deletions Configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -2481,6 +2481,34 @@ fn main() {

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

## `single_line_simple_if`

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.

Note that line will still break if:
1. The condition length is over the `max_width`/`single_line_simple_if_max_width length`
2. The block contains a trailing semicolon
3. The block contains a single or multi-lined comment

- **Default value**: `false`
- **Possible values**: `true`, `false`
- **Stable**: No

#### `false` (default):

## `single_line_simple_if_max_width`

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.

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`.

- **Default value**: `50`
- **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
- **Stable**: Yes

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.

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

## `space_after_colon`

Expand Down
10 changes: 10 additions & 0 deletions src/config/config_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ macro_rules! create_config {
| "fn_call_width"
| "single_line_if_else_max_width"
| "single_line_let_else_max_width"
| "single_line_simple_if_max_width"
| "attr_fn_like_width"
| "struct_lit_width"
| "struct_variant_width"
Expand Down Expand Up @@ -273,6 +274,7 @@ macro_rules! create_config {
| "fn_call_width"
| "single_line_if_else_max_width"
| "single_line_let_else_max_width"
| "single_line_simple_if_max_width"
| "attr_fn_like_width"
| "struct_lit_width"
| "struct_variant_width"
Expand Down Expand Up @@ -421,6 +423,14 @@ macro_rules! create_config {
"single_line_let_else_max_width",
);
self.single_line_let_else_max_width.2 = single_line_let_else_max_width;

let single_line_simple_if_max_width = get_width_value(
self.was_set().single_line_simple_if_max_width(),
self.single_line_simple_if_max_width.2,
heuristics.single_line_simple_if_max_width,
"single_line_simple_if_max_width",
);
self.single_line_simple_if_max_width.2 = single_line_simple_if_max_width;
}

fn set_heuristics(&mut self) {
Expand Down
7 changes: 7 additions & 0 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ create_config! {
single_line_let_else_max_width: usize, 50, true, "Maximum line length for single line \
let-else statements. A value of zero means always format the divergent `else` block \
over multiple lines.";
single_line_simple_if_max_width: usize, 50, false, "Maximum line length for single line \
if statement. A value of zero means always format to multiple lines.";

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

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

// Options that are used by the tests
stable_option: bool, false, true, "A stable option";
Expand Down Expand Up @@ -634,6 +639,7 @@ array_width = 60
chain_width = 60
single_line_if_else_max_width = 50
single_line_let_else_max_width = 50
single_line_simple_if_max_width = 50
wrap_comments = false
format_code_in_doc_comments = false
doc_comment_code_block_width = 100
Expand All @@ -645,6 +651,7 @@ format_macro_matchers = false
format_macro_bodies = true
skip_macro_invocations = []
hex_literal_case = "Preserve"
single_line_simple_if = false
empty_item_single_line = true
struct_lit_single_line = true
fn_single_line = false
Expand Down
6 changes: 6 additions & 0 deletions src/config/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,9 @@ pub struct WidthHeuristics {
// Maximum line length for single line let-else statements. A value of zero means
// always format the divergent `else` block over multiple lines.
pub(crate) single_line_let_else_max_width: usize,
// Maximum line length for single line if statement.
// A value of zero means always format to multiple lines.
pub(crate) single_line_simple_if_max_width: usize,
}

impl fmt::Display for WidthHeuristics {
Expand All @@ -261,6 +264,7 @@ impl WidthHeuristics {
chain_width: usize::max_value(),
single_line_if_else_max_width: 0,
single_line_let_else_max_width: 0,
single_line_simple_if_max_width: 0,
}
}

Expand All @@ -274,6 +278,7 @@ impl WidthHeuristics {
chain_width: max_width,
single_line_if_else_max_width: max_width,
single_line_let_else_max_width: max_width,
single_line_simple_if_max_width: max_width,
}
}

Expand All @@ -296,6 +301,7 @@ impl WidthHeuristics {
chain_width: (60.0 * max_width_ratio).round() as usize,
single_line_if_else_max_width: (50.0 * max_width_ratio).round() as usize,
single_line_let_else_max_width: (50.0 * max_width_ratio).round() as usize,
single_line_simple_if_max_width: (50.0 * max_width_ratio).round() as usize,
}
}
}
Expand Down
41 changes: 31 additions & 10 deletions src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1102,16 +1102,31 @@ impl<'a> Rewrite for ControlFlow<'a> {
};
let block_str = {
let old_val = context.is_if_else_block.replace(self.else_block.is_some());
let allow_single_line =
allow_single_line_if(&cond_str, self.block) && self.keyword == "if";
let max_width = if context.config.single_line_simple_if() {
std::cmp::min(
shape.width,
context.config.single_line_simple_if_max_width(),
)
} else {
shape.width
};
let available_space = max_width.saturating_sub(used_width);
let allow_single_line = allow_single_line_if(&cond_str, self.block)
&& self.keyword == "if"
&& available_space > 0;

let result = if allow_single_line {
rewrite_block_inner(self.block, None, None, true, context, block_shape)
let mut result = if allow_single_line && context.config.single_line_simple_if() {
rewrite_block_inner(self.block, None, None, true, context, block_shape)?
} else {
rewrite_block_with_visitor(context, "", self.block, None, None, block_shape, true)
rewrite_block_with_visitor(context, "", self.block, None, None, block_shape, true)?
};

let block_exceeds_width = result.len() > available_space;
if allow_single_line && !result.contains('\n') && block_exceeds_width {
result = rewrite_block_inner(self.block, None, None, false, context, block_shape)?;
}
context.is_if_else_block.replace(old_val);
result?
result
};

let mut result = format!("{cond_str}{block_str}");
Expand Down Expand Up @@ -1168,20 +1183,26 @@ fn allow_single_line_if(result: &str, block: &ast::Block) -> bool {
if result.contains('\n') {
return false;
}

if block.stmts.len() == 0 {
return true;
}
if block.stmts.len() == 1 {
return is_simple_stmt(&block.stmts[0]);
return is_simple_control_flow_stmt(&block.stmts[0]);
}
false
}

fn is_simple_stmt(stmt: &ast::Stmt) -> bool {
fn is_simple_control_flow_stmt(stmt: &ast::Stmt) -> bool {
match stmt.kind {
ast::StmtKind::Expr(ref expr) => match expr.kind {
ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => true,
ast::ExprKind::Continue(..) => true,
ast::ExprKind::Break(_, ref opt_expr) | ast::ExprKind::Ret(ref opt_expr) => {
if let Some(_) = *opt_expr {
false
} else {
true
}
}
_ => false,
},
_ => false,
Expand Down

0 comments on commit 50c1c83

Please sign in to comment.