-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Prefer expanding parenthesized expressions before operands #5608
Conversation
Current dependencies on/for this PR: This comment was auto-generated by Graphite. |
0cd2dde
to
5dda384
Compare
PR Check ResultsEcosystem✅ ecosystem check detected no changes. BenchmarkLinux
Windows
|
5dda384
to
c97caf1
Compare
7135143
to
4c48749
Compare
537c84f
to
56bae34
Compare
4c48749
to
4ffd817
Compare
56bae34
to
aa6915d
Compare
## Input | ||
|
||
```py | ||
if True: |
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 is a regression
Ruff tests if all lines fit. This is usless in the given case because strings have no further split point. Meaning, changing the layout to fully expanded doesn't really fix the does not fit problem, because we would need to split the srings, which we cannot. Splitting the last line doesn't really help either.
Should the FitsExpanded
measure mode be FitsEnd
rather than StartAndEnd
? Meaning, we measure if everything up to the first separator fits, then everything coming after the last line break?
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.
i think we do need to measure after the line break here
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.
I'll leave this for now to fix later. This is a general problem when using groups
that contain no further split points.
8803400
to
074d289
Compare
4ffd817
to
6d11701
Compare
074d289
to
b8dff47
Compare
let result = group(&format_args![ | ||
if_group_breaks(&text("(")), | ||
indent_if_group_breaks( | ||
&format_args![soft_line_break(), format_expr], |
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.
why is the line break inside the indent?
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.
Indent
is a bit counter-intuitive. Luckily, this is hidden a way by soft_block_indent
and block_indent
. indent
only increments the indentation level, it doesn't insert any line breaks itself. The soft_line_break
is necessary to then start a new line, with the new, incremented indent.
This is why the closing newline is outside of the indent. We first need to decrement the indent counter, and only then start the new line.
## Input | ||
|
||
```py | ||
if True: |
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.
i think we do need to measure after the line break here
6d11701
to
ff18d52
Compare
b8dff47
to
830edb6
Compare
@MichaReiser merged this pull request with Graphite. |
Summary
This PR implements Black's behavior where it first splits off parenthesized expressions before splitting before operands to avoid unnecessary parentheses:
This is implemented by using the new IR elements introduced in #5596.
parentheses_id
)conditional_group
for the lower priority groups (all non-parenthesized expressions) with the condition that theparentheses_id
group breaks (we want to split before operands only if the parentheses are necessary)fits_expanded
to wrap all other parenthesized expressions (lists, dicts, sets), to prevent that expanding e.g. a list expands theparentheses_id
group. We gate thefits_expand
to only apply if theparentheses_id
group fits (because we prefera\n+[b, c]
over expanding[b, c]
if the whole expression gets parenthesized).We limit using
fits_expanded
andconditional_group
only to expressions that themselves are not in parentheses (checking the conditions isn't free)Test Plan
It increases the Jaccard index for Django from 0.915 to 0.917
Incompatibilites
There are two incompatibilities left that I'm aware of (there may be more, I didn't go through all snapshot differences).
Long string literals
I commented on the regression. The issue is that a very long string (or any content without a split point) may not fit when only breaking the right side. The formatter than inserts the optional parentheses. But this is kind of useless because the overlong string will still not fit, because there are no new split points.
I think we should ignore this incompatibility for now
Expressions on statement level
I don't fully understand the logic behind this yet, but black doesn't break before the operators for the following example even though the expression exceeds the configured line width
But it would if the expression is used inside of a condition.
What I understand so far is that Black doesn't insert optional parentheses on the expression statement level (and a few other places) and, therefore, only breaks after opening parentheses. I propose to keep this deviation for now to avoid overlong-lines and use the compatibility report to make a decision if we should implement the same behavior.