-
Notifications
You must be signed in to change notification settings - Fork 933
Improve docs for single_line_if_else_max_width
& add tests
#5509
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
truls-p
wants to merge
8
commits into
rust-lang:master
Choose a base branch
from
truls-p:improve-docs-if-else-max
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
41af7e7
Add details to documentation + examples
truls-p f60a569
Add tests for `single_line_if_else_max_width`
truls-p 37d9b88
Refine documentation + add additional tests for `single_line_if_else_…
truls-p d6f3a90
Update Configurations.md
truls-p a372baa
Reformat description in Configurations.md
truls-p c021610
Add some more whitespace in examples, but remove unnecessary spaces
truls-p 63ccc1c
Add missing newlines in tests/source files
truls-p a536146
Some small tweaks to Configuration.md
truls-p File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// rustfmt-version: One | ||
// rustfmt-single_line_if_else_max_width: 70 | ||
fn foo() -> usize { | ||
let some_long_name = true; | ||
let some_other_long_name = false; | ||
let bar = if some_long_name && some_other_long_name { baz() } else { buzz() }; | ||
if some_long_name && some_other_long_name { 1 } else { 2 } | ||
} | ||
truls-p marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// rustfmt-version: Two | ||
// rustfmt-single_line_if_else_max_width: 70 | ||
fn foo() -> usize { | ||
let some_long_name = true; | ||
let some_other_long_name = false; | ||
let bar = if some_long_name && some_other_long_name { baz() } else { buzz() }; | ||
if some_long_name && some_other_long_name { | ||
1 | ||
} else { | ||
2 | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
fn foo() -> usize { | ||
let some_long_name = true; | ||
let some_other_long_name = false; | ||
let bar = if some_long_name && some_other_long_name { baz() } else { buzz() }; | ||
if some_long_name && some_other_long_name { 1 } else { 2 } | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// rustfmt-version: One | ||
// rustfmt-single_line_if_else_max_width: 70 | ||
fn foo() -> usize { | ||
let some_long_name = true; | ||
let some_other_long_name = false; | ||
let bar = if some_long_name && some_other_long_name { baz() } else { buzz() }; | ||
if some_long_name && some_other_long_name { | ||
1 | ||
} else { | ||
2 | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// rustfmt-version: Two | ||
// rustfmt-single_line_if_else_max_width: 70 | ||
fn foo() -> usize { | ||
let some_long_name = true; | ||
let some_other_long_name = false; | ||
let bar = if some_long_name && some_other_long_name { baz() } else { buzz() }; | ||
if some_long_name && some_other_long_name { 1 } else { 2 } | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
fn foo() -> usize { | ||
let some_long_name = true; | ||
let some_other_long_name = false; | ||
let bar = if some_long_name && some_other_long_name { | ||
baz() | ||
} else { | ||
buzz() | ||
}; | ||
if some_long_name && some_other_long_name { | ||
1 | ||
} else { | ||
2 | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you saying that this would only apply to the last if-else expression? I don't think that's correct, but I could be wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for having a look! I agree that this behavior sounds strange and maybe my research and testing has come up short here, or maybe the proposed documentation is not clear enough. Let me try to explain what I see happening. When we try to use
single_line_if_else_max_width
in expr.rsself.allow_single_line
needs to betrue
(see here), which only happens when we have anif
and expression type is ==ExprType::SubExpression
(see here). Now, theversion = "Two"
is relevant here where we setexpr_type
toExprType::SubExpression
. The two tests I added, 70.rs and 70_version_two.rs tries to test this specific behavior.Here is also another example to play around with. If you run rustfmt --check on this you will see we get a diff for both functions. However, if we change version to "Two" we only get a diff for the last
if
infoo
.Config options:
main.rs:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here are some other examples to consider:
What about something like this where the
if-else
is on the right hand side of an assignment expression?Also what about conditionally passing an argument to a function call or returning a value from a closure?
Again, really appreciate your work on this, and helping us to nail down the description for this option. I think a little rewording is still needed, and maybe it's worth investigating how we set the
expr_type
argument. For example, when we callrewrite
on a top levelast::Expr
node we always passexpr_type
asExprType::SubExpression
. Seeimpl Rewrite for ast::Expr
. The only place in the code base I could find where we don't hard code theexpr_type
argument toformat_expr
is when it gets called fromformat_stmt
.We happen to define our own borrowed version of a
ast::Stmt
:rustfmt/src/stmt.rs
Lines 13 to 16 in 38659ec
And the rewrite method for that does follow the behavior that you outlined above where the last expression is set to a
ExprType::SubExpression
ifVersion=Two
is also setrustfmt/src/stmt.rs
Lines 76 to 85 in 38659ec
So maybe that's what explains the last expression behavior that you documented.
I also came across this interesting comment in the code base that would be nice to have a test for.
It would also be great to have tests for each of these cases that you outlined!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the detailed feedback so far!
These are good examples and I have added them to the documentation in the example section and mentioned them explicitly (the let, function call, and closure) in the description of the config option. I have also reworded the part about if-else expressions at the end of blocks. More on this below.
I have also added some more test cases for the nested if-else case (note how the inner if-else is on a single line when using
Version = "Two"
because it is the last expression in the block) and the comment about the if-else blocks needing to be simple.Regarding the
Version = "Two"
and how theexpr_type
is set I believe I now have a slightly better understanding about how this all works. My understanding is that as we walk the nodes everything starts out as aStmt
. This is why, forVersion = "One"
, when we look at an if-else at the end of a block we hit the following block of code andexpr_type
is set toExprType::Statement
.rustfmt/src/stmt.rs
Lines 76 to 85 in 38659ec
However, in the let, function call, and closure examples we set the
expr_type
for the if-else much further down the call stack. As an example, for the if-else inside the function call we call we hitrewrite_cond
where theexpr_type
is set toExprType::SubExpression
by default.rustfmt/src/expr.rs
Line 610 in 38659ec
Then, crucially,
expr_type == ExprType::SubExpression
evaluates to true infn to_control_flow
.rustfmt/src/expr.rs
Lines 645 to 658 in 38659ec
On the other hand, for the if-else at the end of a block we go straight from
impl<'a> Rewrite for Stmt<'a>
tofn format_stmt
tofn format_expr
, and finally tofn control_flow
, where theexpr_type
is eitherExprType::Statement
orExprType::SubExpression
(set inimpl<'a> Rewrite for Stmt<'a>
) depending on whether we useVersion = "One"
orVersion = "Two"
.I also dug up the original PR for the
impl<'a> Rewrite for Stmt<'a>
:#3631
Note the tests added for #3614: https://github.com/rust-lang/rustfmt/pull/3631/files#diff-c331b0359e60165a708105a49c54a82dc01be48cd219a4c83f91ba0ba961dcb2
Please let me know your thoughts!