-
Notifications
You must be signed in to change notification settings - Fork 14
Implement if statement autobracing #340
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
base: main
Are you sure you want to change the base?
Conversation
…fs in `consequence` They should get to compute their own value, because the user could have validly written a one liner if statement inside a braced if to begin with, and we want to be consistent with that.
This causes too many issues with idempotence and verbatim handling, even though it would be quite nice
It seems like it is actually hard to get this right, as there are many other places where one liners feel "pretty good" and expanding them out causes more churn than it is worth.
And use in if statement handling as a big improvement on context awareness!
// TODO!: Repurpose this as `FormatBracedBody` for use in: | ||
// - For loops (unconditionally) | ||
// - Repeat loops (unconditionally) | ||
// - While loops (unconditionally) | ||
// - Function definitions | ||
// - Includes anonymous functions | ||
// - Allow 1 liner function definitions | ||
// - Definitely breaks if argument list expands over multiple lines | ||
// - Use `if_group_breaks(&text("{"))` to add missing `{}` if the group breaks, | ||
// like if statements. Probably won't be able to use simple `FormatBracedBody` |
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.
This gets removed in the next PR
# If statements and comments | ||
|
||
# fmt: skip | ||
if (TRUE) 1 # hi |
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.
Very important test related to comment placement and verbatim formatting
The # hi
comment must be trailing on the whole if statement, rather than trailing on the 1
node, for this to work correctly. Otherwise verbatim printing will drop the # hi
comment entirely, which would be bad.
When you remove the # fmt: skip
, you get this
if (TRUE) {
1
} # hi
which I can live with for this rare-ish scenario if the alternative is that a comment would be dropped.
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.
Added an absurd amount of new test cases in here. I tried to be exhaustive in where I thought a comment could be placed, and then also added test cases from real life usage on tidyverse packages.
Closes #334
Closes #225
This PR also has the side effect of fixing all idempotence issues on both data.table and R core. Those projects probably won't ever use Air, but they are a very good test case for "are we stable between runs?". We should probably set up some CI for ourselves that runs some kind of idempotence check on a set of large community packages (dplyr, data.table, r-svn) to ensure we don't slip here.
This PR introduces the idea of autobracing. This is the idea of wrapping an if statement body in
{ }
This ensures that the if statement is portable. The above original if statement actually won't even parse at top level due to the
else
on its own line. If you wrap the whole thing in{ }
(like would be the case if you found it inside a function body) then it parses fine. Portability ensures:We still allow short single line if statements when the if statement is in a value position (as opposed to an effect position). The if statement must also meet some other criteria (no existing newlines, no existing braces, etc) to be considered a single line candidate.
I think the formatter code for this feature is rather elegant and easy enough to follow. By far the most complex part of this PR is if/else comment handling. I've added a huge slew of comment related tests to ensure we are doing it "well enough". Movement of comments with something like this will always be a "best effort" kind of transformation, but I think it is worth a little ambiguity. The main promise we make is that we won't ever drop your comments.
Documentation for if/else autobracing ended up in the new Autobracing section of this PR
#344