-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Add BestFittingMode #5184
Merged
Merged
Add BestFittingMode #5184
Conversation
This file contains 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
Current dependencies on/for this PR:
This comment was auto-generated by Graphite. |
This was referenced Jun 19, 2023
Merged
PR Check ResultsEcosystem✅ ecosystem check detected no changes. BenchmarkLinux
Windows
|
f672744
to
89c5ea6
Compare
This was referenced Jun 20, 2023
Merged
konstin
approved these changes
Jun 20, 2023
@MichaReiser started a stack merge that includes this pull request via Graphite. |
@MichaReiser merged this pull request with Graphite. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Black supports for layouts when it comes to breaking binary expressions:
Our current implementation only handles
ExpandRight
andDefault
correctly.ExpandLeft
turns out to be surprisingly hard. This PR adds a newBestFittingMode
parameter toBestFitting
to supportExpandLeft
.There are 3 variants that
ExpandLeft
must support:Variant 1: Everything fits on the line (easy)
Variant 2: Left breaks, but right fits on the line. Doesn't need parentheses
Variant 3: The left breaks, but there's still not enough space for the right hand side. Parenthesize the whole expression:
Solving Variant 1 and 2 on their own is straightforward The printer gives us this behavior by nesting right inside of the group of left:
The fundamental problem is that the outer group, which adds the parentheses, always breaks if the left side breaks. That means, we end up with
which is not what we want (we only want parentheses if the right side doesn't fit).
Okay, so nesting groups don't work because of the outer parentheses. Sequencing groups doesn't work because it results in a right-to-left breaking which is the opposite of what we want.
Could we use best fitting? Almost!
I hope I managed to write this up correctly. The problem is that the printer never reaches the 3rd variant because the second variant always fits:
group(&left).should_expand(true)
changes the group so that allsoft_line_breaks
are turned into hard line breaks. This is necessary because we want to test if the content fits if we break after the[
.best_fitting
is that you can pretend that some content fits on the line when it actually does not. The way this works is that the printer only tests if all the content of the variant up to the first line break fits on the line (we insert that line break by usingshould_expand(true))
. The printer doesn't care whether the resta\n, b\n ] + c
all fits on (multiple?) lines.Why does breaking right work but not breaking the left? The difference is that we can make the decision whether to parenthesis the expression based on the left expression. We can't do this for breaking left because the decision whether to insert parentheses or not would depend on a lookahead: will the right side break. We simply don't know this yet when printing the parentheses (it would work for the right parentheses but not for the left and indent).
What we kind of want here is to tell the printer: Look, what comes here may or may not fit on a single line but we don't care. Simply test that what comes after fits on a line.
This PR adds a new
BestFittingMode
that has a newAllLines
option that gives us the desired behavior of testing all content and not just up to the first line break.Test Plan
I added a new example to
BestFitting::with_mode