-
Notifications
You must be signed in to change notification settings - Fork 657
feat(rome_js_formatter): Hard line breaks in object expressions. #2458
feat(rome_js_formatter): Hard line breaks in object expressions. #2458
Conversation
/// Formats a group delimited by an opening and closing token, placing the | ||
/// content in an [indent] group with [hard_line_break] tokens at the | ||
/// start and end | ||
pub(crate) fn format_delimited_block_hard_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.
This is mostly a copy of format_delimited_soft_block_spaces
and honestly I don't really understand the name of that function, so I'm not sure if the name of this function here makes sense. Please let me know if there is a better one.
let a = { | ||
get foo() {}, | ||
}; | ||
let b = { | ||
set foo(a) {}, | ||
}; |
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 matches the input in getter_setter.js
.
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.
That file is the source code, you should check the file that finishes with .prettier-snap
.
let has_newlines = has_newline(&members.syntax()); | ||
let members = members.format(formatter)?; | ||
|
||
if members.is_empty() { | ||
formatter.format_delimited_soft_block_indent(&l_curly_token?, members, &r_curly_token?) | ||
} else if has_newlines == true { | ||
formatter.format_delimited_block_hard_line_break( | ||
&l_curly_token?, | ||
members, | ||
&r_curly_token?, | ||
) | ||
} else { | ||
formatter.format_delimited_soft_block_spaces(&l_curly_token?, members, &r_curly_token?) |
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.
We have about 10 callsites for format_delimited_soft_block_spaces
. So far I'm only adding this feature to two of them because I'm looking for guidance on the optimal approach:
- Use the above approach and add the newline check and explicit call to
format_delimited_block_hard_line_break
to every callsite. - Rename
format_delimited_soft_block_spaces
to???
and pass ahas_newlines
boolean to the call, then decide on using soft or hard breaks within that single function.
Option 1 is more explicit, option 2 is less code. Which fits better with Rome?
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.
The functions format_delimited_*
were an attempt to group common patterns that we were starting to see across the board. If you think that this is going to be a common pattern, then it makes sense to make it generic, instead if this is just a single case, then it should stay isolated.
The has_newlines
argument won't be needed, as explained in my comment: https://github.com/rome/tools/pull/2458/files#r851766933
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.
Thanks Christoph.
Regarding the failing :arrow_nested
test.
The test is failing because the formatter output isn't stable. Meaning, that re-formatting the formatted output yields a different result. Why or how it can be avoided I don't know right now. @leops and @ematipico have more experience with this kind of issues.
crates/rome_js_formatter/src/js/expressions/object_expression.rs
Outdated
Show resolved
Hide resolved
b029f4c
to
8e21da3
Compare
Thanks for the feedback so far. Remaining questions:
|
After looking into it, the stability issue seem to be caused by the |
Is anyone looking into this? If not, can we track this as an issue? |
I don't think anyone is working on this right now, I can create an independent issue for it. Since it seems to be blocking for this PR I'm not really sure how we want to handle that, do would we hold on to merging this until the issue is fixed or merge this change now and fix the stability issue later ? |
We cannot merge this PR unless we disable the test. It would be great to fix this issue, and then I can rebase my work on that. @MichaReiser Still looking for guidance on my second question about whether the implementation in this PR is acceptable or whether things should be moved around. |
|
4507fc0
to
5390c57
Compare
Ok this PR is ready for review. It updates a lot of snapshots to look like the input code (I initially got confused and was comparing the snapshot changes to the previous snapshot version, which obviously has changed!). I also changed how TypeScript interface declarations are printed since in Prettier they will always break, even with just one prop (thanks @MichaReiser). The only blocker before merging besides review comments is the failing arrows test. I think it would also be great to fix the test infra so that it keeps running instead of crashing on the first failing test like this one. It's quite confusing otherwise when it doesn't make it through the whole test run. |
5fee185
to
e2d4d9c
Compare
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.
Thanks, @cpojer for updating your PR and sorry for the merge conflicts.
The code looks good to me but this PR now goes further than what prettier does. Prettier only preserves line breaks for object literals and object type literals, but not for imports/exports/assertions/etc...
I would recommend keeping compatibility with Prettier for now.
crates/rome_js_formatter/src/js/assignments/object_assignment_pattern.rs
Outdated
Show resolved
Hide resolved
crates/rome_js_formatter/src/js/bindings/object_binding_pattern.rs
Outdated
Show resolved
Hide resolved
crates/rome_js_formatter/src/js/module/named_import_specifiers.rs
Outdated
Show resolved
Hide resolved
e2d4d9c
to
861a683
Compare
Oh that's unfortunate. Thank you so much for double checking. Subjectively, what I had is better for consistency but objectively it's better to align with prettier. I updated the PR and reverted the changes. |
Thanks. Would you mind having a look at the lint and test failures. We should then be good to merge |
861a683
to
286c2b9
Compare
Done (I think!). |
Tests still failing 😔 It seems there are some snapshots that break when reformatting... And few needs to be updated again. This happens because if a change affects prettier test suite AND our internal suite, we need to run and update the snapshots twice. Not sure why this happens but for now that's how it is (sorry) |
@ematipico how do I update the snapshots? When I run |
Instead if you keep getting a diff error, it means that what it is formatted the first time doesn't match the output of the second pass of the formatter (on the emitted code of the first time) |
1245005
to
3f8eb9c
Compare
3f8eb9c
to
7a6a006
Compare
@ematipico Rebased and resolved conflicts, now the arrow test is failing with a different issue it looks like. |
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.
It seems that the algorithm is not working as intended.
Now the object expressions always break, regardless if they have new lines or not.
I strongly suggest to create a new test case in our test suite, ideally the code that Micha attached to the issue. This will help me to identify the new file and see if it matches the intended behaviour
let a = { | ||
get foo() {}, | ||
}; | ||
let b = { | ||
set foo(a) {}, | ||
}; |
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.
That file is the source code, you should check the file that finishes with .prettier-snap
.
As explained on Discord, this is very confusing but the code here is correct except for the example where it breaks the outer parameters list in a function call into newlines which prettier doesn't do. The input code for all of these examples has those newlines in place, so the snapshots are being updated from not printing those newlines to printing them. When you look at the snapshot changes, it looks like things are broken, but when you compare the source with the new snapshot versions you'll see that it is correct. I got confused about the exact same thing before I wrapped my head around that. |
4ee69b5
to
0539c50
Compare
The reason why this PR keeps failing is because we don't yet format call arguments as prettier does. Prettier uses #2529 (conditional groups) and an extensive heuristic to how to print them. The work in tracked in #2421 , so I guess we should put this PR on hold until we have everything we need in place. |
ea7b3cc
to
0cfc66c
Compare
This PR simplifies the member printing logic to make sure its output is stable. This results in a small regression ``` Before: **File Based Average Prettier Similarity**: 69.29% **Line Based Average Prettier Similarity**: 64.28% After: **File Based Average Prettier Similarity**: 69.13% **Line Based Average Prettier Similarity**: 64.06% ``` But unblocks my work on refactoring the printer behaviour (which seems to trigger this now a lot), and #2458
This PR simplifies the member printing logic to make sure its output is stable. This results in a small regression ``` Before: **File Based Average Prettier Similarity**: 69.29% **Line Based Average Prettier Similarity**: 64.28% After: **File Based Average Prettier Similarity**: 69.13% **Line Based Average Prettier Similarity**: 64.06% ``` But unblocks my work on refactoring the printer behaviour (which seems to trigger this now a lot), and #2458
This PR simplifies the member printing logic to make sure its output is stable. This results in a small regression ``` Before: **File Based Average Prettier Similarity**: 69.29% **Line Based Average Prettier Similarity**: 64.28% After: **File Based Average Prettier Similarity**: 69.13% **Line Based Average Prettier Similarity**: 64.06% ``` But unblocks my work on refactoring the printer behaviour (which seems to trigger this now a lot), and #2458
0cfc66c
to
3d50ac9
Compare
@MichaReiser I redid this PR with the new formatting infra, please check out whether this matches expectations! |
Not sure if I did it right ( File Based Average Prettier Similarity: 69.38% → 70.89% |
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 such an awesome contribution. Thank you @cpojer .
Summary
Fixes #2408.
This is the initial draft for respecting a newline in an object expression (or import specifier) in between an opening curly brace
{
and the first item in the member list. This should make Rome match prettier in this situation. Again, I have no idea what I'm doing :)Open questions to get this over the line:
formatter::js_module::specs::js::module::arrow::arrow_nested
fails and I'm unsure why. Please help!Test Plan