Skip to content
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

RemoveScala3OptionalBraces: handle fewer braces #3815

Merged
merged 2 commits into from
Mar 28, 2024

Conversation

kitbellew
Copy link
Collaborator

Fixes #3812.

@kitbellew kitbellew requested a review from tgodzik March 6, 2024 15:27
@kitbellew kitbellew force-pushed the 3812 branch 4 times, most recently from 0d26ecd to fc0c020 Compare March 10, 2024 01:55
@@ -3698,6 +3698,13 @@ The section contains the following settings (available since v3.8.1):
- other flags below might extend rewrites to other cases
- `oldSyntaxToo`
- if `true`, applies also to expressions using deprecated syntax
- `fewerBracesMinStats` and `fewerBracesMaxStats`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's maybe add some info about the defaults? I assume it's 0?

Copy link
Collaborator Author

@kitbellew kitbellew left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in general, it would have been ideal to count the number of lines and not the statements. however, this is performed before the formatting, and the number of output lines is not known at that point.

counting the number of input lines will lead to non idempotent formatting, as that will change. but the tree won't change, and so the number of statements.

in general, i was trying to avoid rewriting very short blocks, e.g. foo { bar }, which might look better on one line, especially since enabled redundant braces actually causes that to be charged to parens after the formatting, hence the minimum statements parameter. but we could also permanently fix it to, say, 2, if we can figure out how to exclude invisible blocks, and remove the parameter.

but the biggest one is the maximum. i think that rewriting a block which is way too large might make the code unreadable. but one can argue that in that case the code was unreadable to begin with, since very large blocks should have been refactored as separate methods.

what do you think? here are the two options, specifically:

  • keep it very configurable, with both parameters; in that case, why wouldn't we count cases or other nested blocks?
  • keep it simple, replace both parameters with a single boolean, determine minimum size ourselves and do not restrict maximum, if that's how the function argument is written?

}
val delta = next match {
case x: Term.Block => enqueue(x.stats)
case x: Tree.WithBody => enqueue(x.body :: Nil) - 1
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as you can see here, -1 means that the parent expression is not counted and fully replaced by the statements in the body. this applies, for instance, to a function, which doesn't count the parameters.

queue.length - len
}
val delta = next match {
case x: Term.Block => enqueue(x.stats)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is where the block, including one without braces, is counted

val delta = next match {
case x: Term.Block => enqueue(x.stats)
case x: Tree.WithBody => enqueue(x.body :: Nil) - 1
case x: Tree.WithCases => enqueue(x.cases)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you mentioned not counting cases in a match statement. this line applies to partial functions as well, should we not count them either?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i have decided to go with the same approach that is used for runner.optimizer.forceConfigStyleOnOffset parameter, by counting total span of non-whitespace tokens.

that was the only approach that is easy to describe, easy to implement and is not subject to non-idempotence problems (since we know which tokens are being removed during the rewrite session).

@tgodzik
Copy link
Contributor

tgodzik commented Mar 10, 2024

keep it very configurable, with both parameters; in that case, why wouldn't we count cases or other nested blocks?

I would opt for that, since I can imagine people wanting fewer braces, but not at all possible cases, which without the additional configuration, would be very unfriendly to use.

The only issue I see is that it should be obvious what the parameter does. And currently users would need to understand inner working of the parser to see what is going on. I would try to make it as simple as possible and only count statements inside the body of the block at the toplevel.

@kitbellew
Copy link
Collaborator Author

@tgodzik sorry, it's been taking a while, found a few rare bugs and non-idempotent behaviour between rewrite rules. please expect a flurry of changes to fix them, before this one is refreshed. all tracked under #3812.

Copy link
Contributor

@tgodzik tgodzik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one minor nitpick

@@ -3698,6 +3698,13 @@ The section contains the following settings (available since v3.8.1):
- other flags below might extend rewrites to other cases
- `oldSyntaxToo`
- if `true`, applies also to expressions using deprecated syntax
- `fewerBracesMinNonWsSpan` and `fewerBracesMaxNonWsSpan`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- `fewerBracesMinNonWsSpan` and `fewerBracesMaxNonWsSpan`
- `fewerBracesMinSpan` and `fewerBracesMaxSpan`

I would try to make it a bit less explicit, if anyone needs to check what is exactly being done they will anyway have to check the docs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you, done!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

In some cases, invoke this rule from redundant-braces, since that rule
is guaranteed to run before remove-optional-braces.
@kitbellew kitbellew merged commit 2b2a6d5 into scalameta:master Mar 28, 2024
9 checks passed
@kitbellew kitbellew deleted the 3812 branch March 28, 2024 16:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement fewer-braces rewrite
2 participants