Use all unsolved pieces on the offending line as expand pieces. #1494
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.
The solver works by incrementally building a up a solution by binding pieces to states one at a time. To avoid wasting time exploring solutions that are pointless, it only looks at unbound pieces in play when the first line containing overflow characters or an invalid newline as written.
Before this PR, it only looked at the first unbound piece on that line. Often, the first piece on the line is not the one that actually needs to split. For example, in:
Here, the first piece on the overflowing line is the AssignPiece for the
=
, but the piece we actually want to split at is the ListPiece for the argument list.To handle that, the solver currently tries binding the first piece to all values, including State.unsplit, even though that's effectively the value the current solution used, since unbound pieces behave like they have State.unsplit. The only reason it makes a new solution and binds the piece to State.unsplit is that if that piece turns out to not be the one that needs to split, we can now find the next piece on that same line. Now that the first piece is bound to State.unsplit, the second piece will be the first unbound one.
But the end result is that we end up generating a lot of more or less redundant solutions that just bind a bunch of pieces to State.unsplit and then produce the exact same formatted result.
Instead, this PR collects all of the unbound pieces on the first overflowing line. When it expands, it expands them all, but doesn't bind any of them to State.unsplit. The old formatter works the same way, but it wasn't clear to me that doing so was important for perf. It is!
My goal is to get the new formatter as fast as the old one on a real-world corpus. Here's the results for formatting the Flutter repo:
So not a huge improvement, but a big step in the right direction.