-
-
Notifications
You must be signed in to change notification settings - Fork 4.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
JS: Break lines before binary operators (fixes #3806) #7111
base: main
Are you sure you want to change the base?
Conversation
/cc @prettier/core will be great if you look at this |
I thought there was a consensus that 2.0 would be focused on deprecating old Node versions etc. Updating to 2.0 should not lead to massive code reformatting. Otherwise too many people might prefer to keep using 1.x. |
The main 2.0 thread(s) have mainly talked about Node versions, but there have also been many comments on not introducing changes that there is disagreement or lack of consensus on. But there seems to be a very strong consensus on the proposed fix to #3806. The only argument offered against the change is that it would be breaking and shouldn't be implemented in a minor version. However, for the change itself, there is widespread agreement both in the issue thread and in the JavaScript community. AirBnB Issue: airbnb/javascript#1281 StandardJS (based on ESLint, widely used): https://standardjs.com/rules.html |
@BrianHVB You completely miss the point of why the ex-2.0 was renamed to 3.0. I'm not saying that there is no consensus about this change, only that first things first. |
e16f758
to
7d88fb8
Compare
Anyone considered break line both before and after? const isEventTarget = value != null
&&
typeof value.addEventListener === "function"
&&
typeof value.removeEventListener === "function"
&&
typeof value.dispatchEvent === "function"
&&
typeof value.dispatchEvent === "function"
-
Also_Nice_With_A_Shorter_Operator_Inside
?
SOME_OTHER_EXPRESSION
??
SOME_OTHER_EXPRESSION
instanceof
Even_Longer_Operator |
ba9d939
to
300b900
Compare
@btmills There is still a conflict |
(isAnyValueSelected | ||
&& node.getAttribute(radioAttr.toLowerCase()) === radioValue) | ||
|| (!isAnyValueSelected && values[a].default === true) | ||
|| a === 0; |
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.
Would it be possible to also change this case where the multiline operators are nested? When I encounter such a case in my code, I usually refactor it so that prettier doesn't make it ugly like that. If I was writing it manually I would write something like:
(
isAnyValueSelected
&& node.getAttribute(radioAttr.toLowerCase()) === radioValue
)
|| (
!isAnyValueSelected
&& values[a].default === true
)
|| a === 0;
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'm trying to keep this change as small as possible to improve the odds the team decides to merge it. Based on the volume of 👍s on #3806, putting binary operators at the beginning of lines has pretty widespread support. It helps that the logic change to do that exclusively deletes code. I'm concerned that expanding the scope could reduce the chance it gets merged at all.
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.
Sure. I didn't mean this comment to show as a "review" of this PR. It was just a random question 😅 This needs a separate issue.
@VincentLanglet I'm not surprised one of the snapshots has been updated since I last rebased. Rebasing the branch takes several minutes, so I haven't been actively monitoring this PR to keep it up to date. If the team indicates they're interested in merging, I'll certainly do another rebase as soon as possible! |
f5f93ae
to
8723d6b
Compare
I’ve rebased this on top of |
Hi, it looks like the conflicting files are just snapshots and this for years. There has been a lot of discussion around this PR I think it is a quite important one. Thank you! |
b2d88d9
to
a2f6eb6
Compare
Rebased after the 2.2.0 release:
A demo install via |
This does not seem to handle comments correctly. Input: const logical_expression =
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa /* trailing comment */
/* leading comment */ && bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
// line comment
&& cccccccccccccccccccccccc Output: const logical_expression =
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa /* trailing comment */
&& /* leading comment */ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb &&
// line comment
cccccccccccccccccccccccc; Leading comments are placed after operators (which is fine) and operators do not appear at the start of the line when there is a line comment. |
In right = [
lineBeforeOperator ? line : "",
operator,
lineBeforeOperator ? " " : line,
rightContent,
rightSuffix,
]; with this: // Place leading own line comments before the operator.
const comment = commentBeforeOperator ? rightContent.splice(0, 1)[0] : '';
right = [
line,
comment,
operator,
" ",
rightContent,
rightSuffix,
]; it will extract leading own line comments from the rightContent and place them before the operator. |
Before changing operator positions, these tests demonstrate the current state.
Previously, there was special case logic to break lines before pipe operators but after all other operators. By removing the special case, line breaks, where necesary, will be placed before all operators.
Thank you for catching that bug, @alex12058, and thank you even more for suggesting the fix! I was able to use it with a modification to avoid clobbering type annotation comments. I rebased this on latest |
@btmills Good catch on the type annotation comments.
// Input
var a = veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongVar || /** @type {string} */
(c);
// Output
var a =
veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongVar
|| /** @type {string} */
(c);
// Expected
var a =
veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongVar
|| /** @type {string} */ (c); What do you think the output should be? Edit: I think the current output if is fine as it respects the users preference to place the comment on it's own line or inline. // Input
var a =
veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongVar
|| /** @type {string} */ (c);
var a =
veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongVar
|| /** @type {string} */
(c);
// Output
var a =
veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongVar
|| /** @type {string} */ (c);
var a =
veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongVar
|| /** @type {string} */
(c); |
@alex12058 I agree with your edit. That seems just far enough away as to be unrelated, so I'm glad this change doesn't affect behavior there either way. |
Seeing Release v3 being planned, I'd like to ask whether this is considered for v3. I see it has the 3.0 milestone, but at the same time, it's not on the release checklist. It seems to be the most upvoted PR, issue (second, but almost no downvotes), and comment on the v3 issue. It seems to be non-controversial issue with a broad consensus. Thanks for any information! |
I'm going to postpone this, since we haven't reached a consensus. |
@fisker can you explain what you mean? From what I can see there is a consensus it was just a matter of deciding which release to put it in (v2 or v3): |
This is a major formatting change, so I think we should hide this feature in an experimental flag(Please see #14527 about experimental flags). Then it could be shipped in v3 as an experimental feature. |
I'd love to see this merged in, even if it's only experimental initially! Since it sounds like that's likely to happen after v3, I'll wait until that's out and rebase this branch again. |
On Friday, @evilebottnawi requested a PR to resolve #3806 in v2.0 by breaking lines, where necessary, before binary operators rather than after them, putting the operators at the beginning of each line.
Previously, there was special case logic to break lines before pipe operators but after all other operators. I removed the special case handling so that line breaks occur before all operators.
I left the implementation, tests, and changelog as separate commits to help ease review. Happy to squash or make any other changes as necessary to help get this in!
docs/
directory)changelog_unreleased/*/pr-XXXX.md
file followingchangelog_unreleased/TEMPLATE.md
.✨Try the playground for this PR✨