Improve dangling comment handling in flow components (#18629)

This commit is contained in:
fisker Cheung authored and GitHub committed 2026-01-15 04:04:39 +08:00
1 parent d40da4a260
commit b1c75ac9ad
6 files changed
+190 -30

No files matched your search

+21
View File
@@ -0,0 +1,21 @@
#### Fix dangling comment print in components (#18629 by @fisker)
<!-- prettier-ignore -->
```jsx
// Input
component A(
// comment
) {}
component B(/* comment */) {}
// Prettier stable
component A() // comment
{}
component B /* comment */() {}
// Prettier main
component A(
// comment
) {}
component B(/* comment */) {}
```
@@ -14,6 +14,7 @@ import getTextWithoutComments from "../utilities/get-text-without-comments.js";
import {
createTypeCheckFunction,
getCallArguments,
getComponentParameters,
getFunctionParameters,
isBinaryCastExpression,
isCallExpression,
@@ -645,6 +646,12 @@ function isInArgumentOrParameterParentheses(node, comment, options) {
);
}
const isFlowComponent = createTypeCheckFunction([
"ComponentDeclaration",
"DeclareComponent",
"ComponentTypeAnnotation",
]);
function handleCommentInEmptyParens({ comment, enclosingNode, options }) {
if (!enclosingNode) {
return false;
@@ -659,6 +666,15 @@ function handleCommentInEmptyParens({ comment, enclosingNode, options }) {
return true;
}
if (
isFlowComponent(enclosingNode) &&
getComponentParameters(enclosingNode).length === 0 &&
isInArgumentOrParameterParentheses(enclosingNode, comment, options)
) {
addDanglingComment(enclosingNode, comment);
return true;
}
// Only add dangling comments to fix the case when no params are present,
// i.e. a function without any argument.
+12 -30
View File
@@ -6,11 +6,16 @@ import {
line,
softline,
} from "../../document/index.js";
import { printDanglingComments } from "../../main/comments/print.js";
import getNextNonSpaceNonCommentCharacter from "../../utilities/get-next-non-space-non-comment-character.js";
import { locEnd } from "../loc.js";
import { isNextLineEmpty, shouldPrintComma } from "../utilities/index.js";
import { printDeclareToken } from "./miscellaneous.js";
import {
getComponentParameters,
isNextLineEmpty,
iterateComponentParametersPath,
shouldPrintComma,
} from "../utilities/index.js";
import {
printDanglingCommentsInList,
printDeclareToken,
} from "./miscellaneous.js";
/**
* @import AstPath from "../../common/ast-path.js"
@@ -52,23 +57,10 @@ function printComponent(path, options, print) {
function printComponentParameters(path, options, print) {
const { node: componentNode } = path;
let parameters = componentNode.params;
if (componentNode.rest) {
parameters = [...parameters, componentNode.rest];
}
const parameters = getComponentParameters(componentNode);
if (parameters.length === 0) {
return [
"(",
printDanglingComments(path, options, {
filter: (comment) =>
getNextNonSpaceNonCommentCharacter(
options.originalText,
locEnd(comment),
) === ")",
}),
")",
];
return ["(", printDanglingCommentsInList(path, options), ")"];
}
const printed = [];
@@ -107,16 +99,6 @@ function hasRestParameter(componentNode, parameters) {
return componentNode.rest || parameters.at(-1)?.type === "RestElement";
}
function iterateComponentParametersPath(path, iteratee) {
const { node } = path;
let index = 0;
const callback = (childPath) => iteratee(childPath, index++);
path.each(callback, "params");
if (node.rest) {
path.call(callback, "rest");
}
}
/*
- `ComponentParameter` (Flow)
*/
+27
View File
@@ -849,6 +849,31 @@ function iterateFunctionParametersPath(path, iteratee) {
}
}
const componentParametersCache = new WeakMap();
function getComponentParameters(node) {
if (componentParametersCache.has(node)) {
return componentParametersCache.get(node);
}
const parameters = [...node.params];
if (node.rest) {
parameters.push(node.rest);
}
componentParametersCache.set(node, parameters);
return parameters;
}
function iterateComponentParametersPath(path, iteratee) {
const { node } = path;
let index = 0;
const callback = () => iteratee(path, index++);
path.each(callback, "params");
if (node.rest) {
path.call(callback, "rest");
}
}
const callArgumentsCache = new WeakMap();
function getCallArguments(node) {
if (callArgumentsCache.has(node)) {
@@ -1119,6 +1144,7 @@ export {
getCallArguments,
getCallArgumentSelector,
getComments,
getComponentParameters,
getFunctionParameters,
getLeftSide,
getLeftSidePathName,
@@ -1174,6 +1200,7 @@ export {
isTypeAnnotationAFunction,
isUnionType,
iterateCallArgumentsPath,
iterateComponentParametersPath,
iterateFunctionParametersPath,
needsHardlineAfterDanglingComment,
shouldFlatten,
@@ -317,6 +317,83 @@ function A(
================================================================================
`;
exports[`dangling-comments.js format 1`] = `
====================================options=====================================
parsers: ["flow"]
printWidth: 80
| printWidth
=====================================input======================================
component C11(// 11
) {}
component C12(
// 12
) {}
declare component C13(// 13
)
declare component C14(
// 14
)
type T11 = component(//15
);
type T12 = component(
//16
);
component C21(/* 21 */
) {}
component C22(
/* 22*/
) {}
component C23(
/* 23*/){}
declare component C24(/* 24 */
)
declare component C25(
/* 25*/
)
declare component C26(
/* 26*/)
type T21 = component(/* 27*/
);
type T22 = component(
/* 28*/
);
type T23 = component(
/* 29*/);
=====================================output=====================================
component C11(
// 11
) {}
component C12(
// 12
) {}
declare component C13(
// 13
);
declare component C14(
// 14
);
type T11 = component(
//15
);
type T12 = component(
//16
);
component C21(/* 21 */) {}
component C22(/* 22*/) {}
component C23(/* 23*/) {}
declare component C24(/* 24 */);
declare component C25(/* 25*/);
declare component C26(/* 26*/);
type T21 = component(/* 27*/);
type T22 = component(/* 28*/);
type T23 = component(/* 29*/);
================================================================================
`;
exports[`declare-component.js format 1`] = `
====================================options=====================================
parsers: ["flow"]
@@ -0,0 +1,37 @@
component C11(// 11
) {}
component C12(
// 12
) {}
declare component C13(// 13
)
declare component C14(
// 14
)
type T11 = component(//15
);
type T12 = component(
//16
);
component C21(/* 21 */
) {}
component C22(
/* 22*/
) {}
component C23(
/* 23*/){}
declare component C24(/* 24 */
)
declare component C25(
/* 25*/
)
declare component C26(
/* 26*/)
type T21 = component(/* 27*/
);
type T22 = component(
/* 28*/
);
type T23 = component(
/* 29*/);