fix(js_formatter): fix array fill elements expanding from leading comments #1135
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
This one was a doozy to figure out. The root of the issue is printing a concise array with an own-line comment:
We want the formatted output to look exactly like this, but it was actually being printed as:
Where the entry with the leading comment got its own line, and then the fill continued on the following line.
This was somewhat intended, as noted by this comment in a test, but it doesn't match the behavior of Prettier, which does preserve the exact formatting as the input.
The cause of this difference was how
FormatElement::Line(LineMode::Hard)
got handled when measuring fit. It had been checkingmust_be_flat
and returningNo
if there was a hard line whenmust_be_flat
was true. This makes sense, as that comment above mentions, because the content doesn't fit on a single line. Prettier, however, doesn't care about whether the fit must be flat, and just always considered hard line breaks as fitting. This also makes sense, because the print is guaranteed to not exceed the line width, which is the real purpose offits
.Fixing this original issue was then just a matter of removing the check for
must_be_flat
when a hard line is encountered. That (plus a change to the generated IR for array fills to use a hardline separator before the leading comment) made these tests for array fills match Prettier.However, this caused a different issue with JSX elements, where now multiline elements that hadn't been considered "fitting" before now did fit and caused the separators to print in flat mode when they shouldn't, like so:
In this case, because
<span>...</span>
contains hard lines and goes over multiple lines, we don't want it to count as a "flat" element, and instead it should force expansion like it did before (and matching Prettier), yielding:We know why this changed (because hard lines weren't considered fitting before and now they are), but if that behavior now matches Prettier, why does this result in the JSX not? After much attempted debugging of the printer to try to find other differences about how
fits_element
was working, it turned out to just be that the generated IR for these multiline children was different.For any multiline JSX element, Prettier wraps the content with a
group
. This group gets automatically expanded by propagation from thehardline
breaks contained within it, and so when thefits
check happens, the group says "nope, I definitely expand, so I don't fit in flat mode" and returns false. Because of that, the fill element expands and the separator also gets printed in expanded mode (matching theif_group_breaks
condition as mentioned in the comment above).But Biome wasn't wrapping the content with a
group
. That meant that the hardline breaks weren't propagated to anything within theFill
, and it didn't know that it shouldn't be considered fitting. By adding thegroup
around the JSX children, it now knows that there is a line break, shouldn't fit, and should expand both the item and the separator, exactly the way that Prettier does.Test Plan
Prettier diff snapshots are deleted since they now match, and no other tests were affected.
I did remove the prettier difference spec test since the behavior now matches Prettier.