TSX: Fix incorrectly removing parentheses around jsx elements being accessed in tsx file (#6640)
* Modify to wrap jsx element used with member-expression in tsx * Add tests * Update CHANGELOG.unreleased.md * Modify to support no-inline jsx element * Add pr number * Fix from lint-docs * Modify to rename isTsx => isTSXFile * Modify to no considering file ext * Support JSXFragment and add tests * Update CHANGELOG.unreleased.mdmaster
parent
c949f5ba20
commit
3a998df02e
|
@ -898,6 +898,20 @@ function doSmth() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### TypeScript: sometimes removing parentheses around JSX made the code unparseable ([#6640] by [@sosukesuzuki])
|
||||||
|
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
```tsx
|
||||||
|
// Input
|
||||||
|
(<a />).toString();
|
||||||
|
|
||||||
|
// Prettier (stable)
|
||||||
|
<a />.toString():
|
||||||
|
|
||||||
|
// Prettier (master)
|
||||||
|
(<a />).toString();
|
||||||
|
```
|
||||||
|
|
||||||
[#5910]: https://github.com/prettier/prettier/pull/5910
|
[#5910]: https://github.com/prettier/prettier/pull/5910
|
||||||
[#6033]: https://github.com/prettier/prettier/pull/6033
|
[#6033]: https://github.com/prettier/prettier/pull/6033
|
||||||
[#6186]: https://github.com/prettier/prettier/pull/6186
|
[#6186]: https://github.com/prettier/prettier/pull/6186
|
||||||
|
@ -927,6 +941,7 @@ function doSmth() {
|
||||||
[#6604]: https://github.com/prettier/prettier/pull/6604
|
[#6604]: https://github.com/prettier/prettier/pull/6604
|
||||||
[#6496]: https://github.com/prettier/prettier/pull/6496
|
[#6496]: https://github.com/prettier/prettier/pull/6496
|
||||||
[#6605]: https://github.com/prettier/prettier/pull/6605
|
[#6605]: https://github.com/prettier/prettier/pull/6605
|
||||||
|
[#6640]: https://github.com/prettier/prettier/pull/6640
|
||||||
[@brainkim]: https://github.com/brainkim
|
[@brainkim]: https://github.com/brainkim
|
||||||
[@duailibe]: https://github.com/duailibe
|
[@duailibe]: https://github.com/duailibe
|
||||||
[@gavinjoyce]: https://github.com/gavinjoyce
|
[@gavinjoyce]: https://github.com/gavinjoyce
|
||||||
|
|
|
@ -6,8 +6,8 @@ const util = require("../common/util");
|
||||||
const comments = require("./comments");
|
const comments = require("./comments");
|
||||||
const {
|
const {
|
||||||
getLeftSidePathName,
|
getLeftSidePathName,
|
||||||
hasNakedLeftSide,
|
hasFlowShorthandAnnotationComment,
|
||||||
hasFlowShorthandAnnotationComment
|
hasNakedLeftSide
|
||||||
} = require("./utils");
|
} = require("./utils");
|
||||||
|
|
||||||
function hasClosureCompilerTypeCastComment(text, path) {
|
function hasClosureCompilerTypeCastComment(text, path) {
|
||||||
|
@ -722,6 +722,29 @@ function needsParens(path, options) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
case "JSXFragment":
|
||||||
|
case "JSXElement":
|
||||||
|
return (
|
||||||
|
parent.type !== "ArrayExpression" &&
|
||||||
|
parent.type !== "ArrowFunctionExpression" &&
|
||||||
|
parent.type !== "AssignmentExpression" &&
|
||||||
|
parent.type !== "AssignmentPattern" &&
|
||||||
|
parent.type !== "BinaryExpression" &&
|
||||||
|
parent.type !== "CallExpression" &&
|
||||||
|
parent.type !== "ConditionalExpression" &&
|
||||||
|
parent.type !== "ExpressionStatement" &&
|
||||||
|
parent.type !== "JsExpressionRoot" &&
|
||||||
|
parent.type !== "JSXAttribute" &&
|
||||||
|
parent.type !== "JSXElement" &&
|
||||||
|
parent.type !== "JSXExpressionContainer" &&
|
||||||
|
parent.type !== "JSXFragment" &&
|
||||||
|
parent.type !== "LogicalExpression" &&
|
||||||
|
parent.type !== "ObjectProperty" &&
|
||||||
|
parent.type !== "Property" &&
|
||||||
|
parent.type !== "ReturnStatement" &&
|
||||||
|
parent.type !== "TypeCastExpression" &&
|
||||||
|
parent.type !== "VariableDeclarator"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -84,6 +84,7 @@ const {
|
||||||
isTemplateOnItsOwnLine,
|
isTemplateOnItsOwnLine,
|
||||||
isTestCall,
|
isTestCall,
|
||||||
isTheOnlyJSXElementInMarkdown,
|
isTheOnlyJSXElementInMarkdown,
|
||||||
|
isTSXFile,
|
||||||
isTypeAnnotationAFunction,
|
isTypeAnnotationAFunction,
|
||||||
matchJsxWhitespaceRegex,
|
matchJsxWhitespaceRegex,
|
||||||
needsHardlineAfterDanglingComment,
|
needsHardlineAfterDanglingComment,
|
||||||
|
@ -2152,7 +2153,7 @@ function printPathNoParens(path, options, print, args) {
|
||||||
() => printJSXElement(path, options, print),
|
() => printJSXElement(path, options, print),
|
||||||
options
|
options
|
||||||
);
|
);
|
||||||
return maybeWrapJSXElementInParens(path, elem);
|
return maybeWrapJSXElementInParens(path, elem, options);
|
||||||
}
|
}
|
||||||
case "JSXOpeningElement": {
|
case "JSXOpeningElement": {
|
||||||
const n = path.getValue();
|
const n = path.getValue();
|
||||||
|
@ -3005,8 +3006,7 @@ function printPathNoParens(path, options, print, args) {
|
||||||
if (
|
if (
|
||||||
parent.params &&
|
parent.params &&
|
||||||
parent.params.length === 1 &&
|
parent.params.length === 1 &&
|
||||||
options.filepath &&
|
isTSXFile(options) &&
|
||||||
/\.tsx$/i.test(options.filepath) &&
|
|
||||||
!n.constraint &&
|
!n.constraint &&
|
||||||
grandParent.type === "ArrowFunctionExpression"
|
grandParent.type === "ArrowFunctionExpression"
|
||||||
) {
|
) {
|
||||||
|
@ -5385,7 +5385,7 @@ function printJSXElement(path, options, print) {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function maybeWrapJSXElementInParens(path, elem) {
|
function maybeWrapJSXElementInParens(path, elem, options) {
|
||||||
const parent = path.getParentNode();
|
const parent = path.getParentNode();
|
||||||
if (!parent) {
|
if (!parent) {
|
||||||
return elem;
|
return elem;
|
||||||
|
@ -5413,12 +5413,14 @@ function maybeWrapJSXElementInParens(path, elem) {
|
||||||
"JSXExpressionContainer"
|
"JSXExpressionContainer"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const needsParens = pathNeedsParens(path, options);
|
||||||
|
|
||||||
return group(
|
return group(
|
||||||
concat([
|
concat([
|
||||||
ifBreak("("),
|
needsParens ? "" : ifBreak("("),
|
||||||
indent(concat([softline, elem])),
|
indent(concat([softline, elem])),
|
||||||
softline,
|
softline,
|
||||||
ifBreak(")")
|
needsParens ? "" : ifBreak(")")
|
||||||
]),
|
]),
|
||||||
{ shouldBreak }
|
{ shouldBreak }
|
||||||
);
|
);
|
||||||
|
|
|
@ -888,6 +888,10 @@ function identity(x) {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isTSXFile(options) {
|
||||||
|
return options.filepath && /\.tsx$/i.test(options.filepath);
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
classChildNeedsASIProtection,
|
classChildNeedsASIProtection,
|
||||||
classPropMayCauseASIProblems,
|
classPropMayCauseASIProblems,
|
||||||
|
@ -934,6 +938,7 @@ module.exports = {
|
||||||
isTemplateOnItsOwnLine,
|
isTemplateOnItsOwnLine,
|
||||||
isTestCall,
|
isTestCall,
|
||||||
isTheOnlyJSXElementInMarkdown,
|
isTheOnlyJSXElementInMarkdown,
|
||||||
|
isTSXFile,
|
||||||
isTypeAnnotationAFunction,
|
isTypeAnnotationAFunction,
|
||||||
matchJsxWhitespaceRegex,
|
matchJsxWhitespaceRegex,
|
||||||
needsHardlineAfterDanglingComment,
|
needsHardlineAfterDanglingComment,
|
||||||
|
|
|
@ -55,6 +55,30 @@ foo = (
|
||||||
</ // close fragment
|
</ // close fragment
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
[<></>, <></>];
|
||||||
|
const fun1 = () => <></>;
|
||||||
|
x = <></>
|
||||||
|
function fun2(param = <></>) {}
|
||||||
|
1 + <></>;
|
||||||
|
1 || <></>;
|
||||||
|
fun2(<></>);
|
||||||
|
test ? <></> : x;
|
||||||
|
<></>;
|
||||||
|
<a>
|
||||||
|
<></>
|
||||||
|
</a>;
|
||||||
|
const obj = {
|
||||||
|
foo: <></>
|
||||||
|
};
|
||||||
|
const fragmentVar = <></>;
|
||||||
|
function fun3() {
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
(<></>).toString();
|
||||||
|
(<></>).props;
|
||||||
|
(<></>)["computed"];
|
||||||
|
(<></>)["computed"]();
|
||||||
|
|
||||||
=====================================output=====================================
|
=====================================output=====================================
|
||||||
<></>;
|
<></>;
|
||||||
|
|
||||||
|
@ -105,5 +129,29 @@ foo = (
|
||||||
// close fragment
|
// close fragment
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
[<></>, <></>];
|
||||||
|
const fun1 = () => <></>;
|
||||||
|
x = <></>;
|
||||||
|
function fun2(param = <></>) {}
|
||||||
|
1 + <></>;
|
||||||
|
1 || <></>;
|
||||||
|
fun2(<></>);
|
||||||
|
test ? <></> : x;
|
||||||
|
<></>;
|
||||||
|
<a>
|
||||||
|
<></>
|
||||||
|
</a>;
|
||||||
|
const obj = {
|
||||||
|
foo: <></>
|
||||||
|
};
|
||||||
|
const fragmentVar = <></>;
|
||||||
|
function fun3() {
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
(<></>).toString();
|
||||||
|
(<></>).props;
|
||||||
|
(<></>)["computed"];
|
||||||
|
(<></>)["computed"]();
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -46,3 +46,27 @@ foo = (
|
||||||
<Component />
|
<Component />
|
||||||
</ // close fragment
|
</ // close fragment
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
[<></>, <></>];
|
||||||
|
const fun1 = () => <></>;
|
||||||
|
x = <></>
|
||||||
|
function fun2(param = <></>) {}
|
||||||
|
1 + <></>;
|
||||||
|
1 || <></>;
|
||||||
|
fun2(<></>);
|
||||||
|
test ? <></> : x;
|
||||||
|
<></>;
|
||||||
|
<a>
|
||||||
|
<></>
|
||||||
|
</a>;
|
||||||
|
const obj = {
|
||||||
|
foo: <></>
|
||||||
|
};
|
||||||
|
const fragmentVar = <></>;
|
||||||
|
function fun3() {
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
(<></>).toString();
|
||||||
|
(<></>).props;
|
||||||
|
(<></>)["computed"];
|
||||||
|
(<></>)["computed"]();
|
||||||
|
|
|
@ -38,6 +38,66 @@ printWidth: 80
|
||||||
================================================================================
|
================================================================================
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`member-expression.tsx 1`] = `
|
||||||
|
====================================options=====================================
|
||||||
|
parsers: ["typescript"]
|
||||||
|
printWidth: 80
|
||||||
|
| printWidth
|
||||||
|
=====================================input======================================
|
||||||
|
(<a />).method();
|
||||||
|
(<a />).property;
|
||||||
|
(<a />)["computed"];
|
||||||
|
(<a />)["computed"]();
|
||||||
|
(
|
||||||
|
<div>
|
||||||
|
<a>foo</a>
|
||||||
|
</div>
|
||||||
|
).method();
|
||||||
|
(
|
||||||
|
<div>
|
||||||
|
<a>foo</a>
|
||||||
|
</div>
|
||||||
|
).property;
|
||||||
|
(
|
||||||
|
<div>
|
||||||
|
<a>foo</a>
|
||||||
|
</div>
|
||||||
|
)["computed"];
|
||||||
|
(
|
||||||
|
<div>
|
||||||
|
<a>foo</a>
|
||||||
|
</div>
|
||||||
|
)["computed"]();
|
||||||
|
|
||||||
|
=====================================output=====================================
|
||||||
|
(<a />).method();
|
||||||
|
(<a />).property;
|
||||||
|
(<a />)["computed"];
|
||||||
|
(<a />)["computed"]();
|
||||||
|
(
|
||||||
|
<div>
|
||||||
|
<a>foo</a>
|
||||||
|
</div>
|
||||||
|
).method();
|
||||||
|
(
|
||||||
|
<div>
|
||||||
|
<a>foo</a>
|
||||||
|
</div>
|
||||||
|
).property;
|
||||||
|
(
|
||||||
|
<div>
|
||||||
|
<a>foo</a>
|
||||||
|
</div>
|
||||||
|
)["computed"];
|
||||||
|
(
|
||||||
|
<div>
|
||||||
|
<a>foo</a>
|
||||||
|
</div>
|
||||||
|
)["computed"]();
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`not-react.ts 1`] = `
|
exports[`not-react.ts 1`] = `
|
||||||
====================================options=====================================
|
====================================options=====================================
|
||||||
parsers: ["typescript"]
|
parsers: ["typescript"]
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
(<a />).method();
|
||||||
|
(<a />).property;
|
||||||
|
(<a />)["computed"];
|
||||||
|
(<a />)["computed"]();
|
||||||
|
(
|
||||||
|
<div>
|
||||||
|
<a>foo</a>
|
||||||
|
</div>
|
||||||
|
).method();
|
||||||
|
(
|
||||||
|
<div>
|
||||||
|
<a>foo</a>
|
||||||
|
</div>
|
||||||
|
).property;
|
||||||
|
(
|
||||||
|
<div>
|
||||||
|
<a>foo</a>
|
||||||
|
</div>
|
||||||
|
)["computed"];
|
||||||
|
(
|
||||||
|
<div>
|
||||||
|
<a>foo</a>
|
||||||
|
</div>
|
||||||
|
)["computed"]();
|
Loading…
Reference in New Issue