Skip to content
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

Fix comment duplication for experimental ternaries #15965

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 30 additions & 0 deletions changelog_unreleased/javascript/15965.md
@@ -0,0 +1,30 @@
#### Fix comment duplication for experimental ternaries (#15965 by @sosukesuzuki)

<!-- prettier-ignore -->
```jsx
// Input
x =
IS_AUTOTEST || (IS_DEV && !IS_TEST) ?
[
/*FooBlock*/
]
: [];

// Prettier stable
x =
IS_AUTOTEST || (IS_DEV && !IS_TEST) ?
/*FooBlock*/
[
/*FooBlock*/
]
: [];

// Prettier main
x =
IS_AUTOTEST || (IS_DEV && !IS_TEST) ?
[
/*FooBlock*/
]
: [];

```
7 changes: 6 additions & 1 deletion src/language-js/comments/handle-comments.js
Expand Up @@ -11,6 +11,7 @@ import isNonEmptyArray from "../../utils/is-non-empty-array.js";
import { locEnd, locStart } from "../loc.js";
import {
createTypeCheckFunction,
experimentalTernaryDanglingCommentMarker,
getCallArguments,
getFunctionParameters,
isCallExpression,
Expand Down Expand Up @@ -395,7 +396,11 @@ function handleConditionalExpressionComments({
)
)
) {
addDanglingComment(enclosingNode, comment);
addDanglingComment(
enclosingNode,
comment,
experimentalTernaryDanglingCommentMarker,
);
return true;
}
addLeadingComment(followingNode, comment);
Expand Down
32 changes: 25 additions & 7 deletions src/language-js/print/ternary.js
Expand Up @@ -14,6 +14,7 @@
import pathNeedsParens from "../needs-parens.js";
import {
CommentCheckFlags,
experimentalTernaryDanglingCommentMarker,
getComments,
hasComment,
isBinaryCastExpression,
Expand Down Expand Up @@ -284,28 +285,45 @@
hasComment(consequentNode, CommentCheckFlags.Dangling)
) {
path.call((childPath) => {
consequentComments.push(
printDanglingComments(childPath, options),
hardline,
);
const danglingComments = printDanglingComments(childPath, options, {
marker: experimentalTernaryDanglingCommentMarker,
});
if (danglingComments) {
consequentComments.push(danglingComments, hardline);
}

Check warning on line 293 in src/language-js/print/ternary.js

View check run for this annotation

Codecov / codecov/patch

src/language-js/print/ternary.js#L292-L293

Added lines #L292 - L293 were not covered by tests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took some time to find the root cause, I think the problem here is we are printing the dangling comments in the consequent and the consequent will also print them.

Do you think we can check node type of consequent instead?

Something like:

const nodesShouldPrintDanglingComments = node =>
  node.type === 'ArrayExpression' || 
  node.type === 'ObjectExpression'
if (!nodesShouldPrintDanglingComments (node)) {
  ...
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds plausible to me fwiw

}, "consequent");
}
const alternateComments = [];
if (hasComment(node.test, CommentCheckFlags.Dangling)) {
path.call((childPath) => {
alternateComments.push(printDanglingComments(childPath, options));
const danglingComments = printDanglingComments(childPath, options, {
marker: experimentalTernaryDanglingCommentMarker,
});
if (danglingComments) {
alternateComments.push(danglingComments, hardline);
}

Check warning on line 304 in src/language-js/print/ternary.js

View check run for this annotation

Codecov / codecov/patch

src/language-js/print/ternary.js#L303-L304

Added lines #L303 - L304 were not covered by tests
}, "test");
}
if (
!isAlternateTernary &&
hasComment(alternateNode, CommentCheckFlags.Dangling)
) {
path.call((childPath) => {
alternateComments.push(printDanglingComments(childPath, options));
const danglingComments = printDanglingComments(childPath, options, {
marker: experimentalTernaryDanglingCommentMarker,
});
if (danglingComments) {
alternateComments.push(danglingComments, hardline);
}

Check warning on line 317 in src/language-js/print/ternary.js

View check run for this annotation

Codecov / codecov/patch

src/language-js/print/ternary.js#L316-L317

Added lines #L316 - L317 were not covered by tests
}, "alternate");
}
if (hasComment(node, CommentCheckFlags.Dangling)) {
alternateComments.push(printDanglingComments(path, options));
const danglingComments = printDanglingComments(path, options, {
marker: experimentalTernaryDanglingCommentMarker,
});
if (danglingComments) {
alternateComments.push(danglingComments);
}
}

const testId = Symbol("test");
Expand Down
5 changes: 5 additions & 0 deletions src/language-js/utils/index.js
Expand Up @@ -1217,9 +1217,14 @@ const isIntersectionType = createTypeCheckFunction([
"TSIntersectionType",
]);

const experimentalTernaryDanglingCommentMarker = Symbol(
"ternaryDanglingCommentMarker",
);

export {
CommentCheckFlags,
createTypeCheckFunction,
experimentalTernaryDanglingCommentMarker,
getCallArguments,
getCallArgumentSelector,
getComments,
Expand Down
16 changes: 16 additions & 0 deletions tests/format/js/conditional/15875.js
@@ -0,0 +1,16 @@
([
/* comment1 */
]) ? [
/* comment2 */
] : [
/* comment3 */
];

({
/* comment4 */
}) ? ({
/* comment5 */
}) : ({
/* comment6 */
});

99 changes: 99 additions & 0 deletions tests/format/js/conditional/__snapshots__/jsfmt.spec.js.snap
@@ -1,5 +1,104 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`15875.js - {"experimentalTernaries":true} format 1`] = `
====================================options=====================================
experimentalTernaries: true
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
([
/* comment1 */
]) ? [
/* comment2 */
] : [
/* comment3 */
];

({
/* comment4 */
}) ? ({
/* comment5 */
}) : ({
/* comment6 */
});


=====================================output=====================================
(
[
/* comment1 */
]
) ?
[
/* comment2 */
]
: [
/* comment3 */
];

(
({
/* comment4 */
})
) ?
{
/* comment5 */
}
: {
/* comment6 */
};

================================================================================
`;

exports[`15875.js format 1`] = `
====================================options=====================================
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
([
/* comment1 */
]) ? [
/* comment2 */
] : [
/* comment3 */
];

({
/* comment4 */
}) ? ({
/* comment5 */
}) : ({
/* comment6 */
});


=====================================output=====================================
[
/* comment1 */
]
? [
/* comment2 */
]
: [
/* comment3 */
];

({
/* comment4 */
})
? {
/* comment5 */
}
: {
/* comment6 */
};

================================================================================
`;

exports[`comments.js - {"experimentalTernaries":true} format 1`] = `
====================================options=====================================
experimentalTernaries: true
Expand Down