Add parentheses for decorator expressions (#16458)
Co-authored-by: fisker <lionkay@gmail.com>
This commit is contained in:
1 parent
6bbd46194e
commit
9102b73d8c
6 files changed
+109
-40
No files matched your search
@@ -0,0 +1,18 @@
|
||||
#### Add parentheses for decorator expressions (#16458 by @y-schneider)
|
||||
|
||||
Prevent parentheses around member expressions or tagged template literals from being removed to follow the stricter parsing rules of TypeScript 5.5.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```ts
|
||||
// Input
|
||||
@(foo`tagged template`)
|
||||
class X {}
|
||||
|
||||
// Prettier stable
|
||||
@foo`tagged template`
|
||||
class X {}
|
||||
|
||||
// Prettier main
|
||||
@(foo`tagged template`)
|
||||
class X {}
|
||||
```
|
||||
@@ -295,6 +295,7 @@
|
||||
"unaries",
|
||||
"uncook",
|
||||
"unparenthesised",
|
||||
"Unparenthesized",
|
||||
"Unrestrict",
|
||||
"upvoted",
|
||||
"upvotes",
|
||||
|
||||
@@ -224,40 +224,10 @@ function needsParens(path, options) {
|
||||
);
|
||||
|
||||
case "Decorator":
|
||||
if (key === "expression") {
|
||||
if (isMemberExpression(node) && node.computed) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let hasCallExpression = false;
|
||||
let hasMemberExpression = false;
|
||||
let current = node;
|
||||
while (current) {
|
||||
switch (current.type) {
|
||||
case "MemberExpression":
|
||||
hasMemberExpression = true;
|
||||
current = current.object;
|
||||
break;
|
||||
case "CallExpression":
|
||||
if (
|
||||
/** @(x().y) */ hasMemberExpression ||
|
||||
/** @(x().y()) */ hasCallExpression
|
||||
) {
|
||||
return options.parser !== "typescript";
|
||||
}
|
||||
hasCallExpression = true;
|
||||
current = current.callee;
|
||||
break;
|
||||
case "Identifier":
|
||||
return false;
|
||||
case "TaggedTemplateExpression":
|
||||
// babel-parser cannot parse
|
||||
// @foo`bar`
|
||||
return options.parser !== "typescript";
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (
|
||||
key === "expression" &&
|
||||
!canDecoratorExpressionUnparenthesized(node)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -1276,4 +1246,36 @@ function shouldAddParenthesesToChainElement(path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function isDecoratorMemberExpression(node) {
|
||||
if (node.type === "Identifier") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isMemberExpression(node)) {
|
||||
return (
|
||||
!node.computed &&
|
||||
!node.optional &&
|
||||
node.property.type === "Identifier" &&
|
||||
isDecoratorMemberExpression(node.object)
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Based on babel implementation
|
||||
// https://github.com/nicolo-ribaudo/babel/blob/c4b88a4e5005364255f7e964fe324cf7bfdfb019/packages/babel-generator/src/node/index.ts#L111
|
||||
function canDecoratorExpressionUnparenthesized(node) {
|
||||
if (node.type === "ChainExpression") {
|
||||
node = node.expression;
|
||||
}
|
||||
|
||||
return (
|
||||
isDecoratorMemberExpression(node) ||
|
||||
(isCallExpression(node) &&
|
||||
!node.optional &&
|
||||
isDecoratorMemberExpression(node.callee))
|
||||
);
|
||||
}
|
||||
|
||||
export default needsParens;
|
||||
@@ -176,7 +176,7 @@ exports[`member-expression.js [acorn] format 1`] = `
|
||||
"Unexpected character '@' (3:5)
|
||||
1 | [
|
||||
2 | class {
|
||||
> 3 | @(decorators[0])
|
||||
> 3 | @(decorator)
|
||||
| ^
|
||||
4 | method() {}
|
||||
5 | },
|
||||
@@ -188,7 +188,7 @@ exports[`member-expression.js [espree] format 1`] = `
|
||||
"Unexpected character '@' (3:5)
|
||||
1 | [
|
||||
2 | class {
|
||||
> 3 | @(decorators[0])
|
||||
> 3 | @(decorator)
|
||||
| ^
|
||||
4 | method() {}
|
||||
5 | },
|
||||
@@ -203,6 +203,18 @@ printWidth: 80
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
[
|
||||
class {
|
||||
@(decorator)
|
||||
method() {}
|
||||
},
|
||||
class {
|
||||
@(decorator())
|
||||
method() {}
|
||||
},
|
||||
class {
|
||||
@(decorator?.())
|
||||
method() {}
|
||||
},
|
||||
class {
|
||||
@(decorators[0])
|
||||
method() {}
|
||||
@@ -223,6 +235,10 @@ printWidth: 80
|
||||
@(decorators?.at(0))
|
||||
method() {}
|
||||
},
|
||||
class {
|
||||
@(decorators.at?.(0))
|
||||
method() {}
|
||||
},
|
||||
class {
|
||||
@(decorators.first)
|
||||
method() {}
|
||||
@@ -255,6 +271,18 @@ printWidth: 80
|
||||
|
||||
=====================================output=====================================
|
||||
[
|
||||
class {
|
||||
@decorator
|
||||
method() {}
|
||||
},
|
||||
class {
|
||||
@decorator()
|
||||
method() {}
|
||||
},
|
||||
class {
|
||||
@(decorator?.())
|
||||
method() {}
|
||||
},
|
||||
class {
|
||||
@(decorators[0])
|
||||
method() {}
|
||||
@@ -275,6 +303,10 @@ printWidth: 80
|
||||
@(decorators?.at(0))
|
||||
method() {}
|
||||
},
|
||||
class {
|
||||
@(decorators.at?.(0))
|
||||
method() {}
|
||||
},
|
||||
class {
|
||||
@decorators.first
|
||||
method() {}
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
[
|
||||
class {
|
||||
@(decorator)
|
||||
method() {}
|
||||
},
|
||||
class {
|
||||
@(decorator())
|
||||
method() {}
|
||||
},
|
||||
class {
|
||||
@(decorator?.())
|
||||
method() {}
|
||||
},
|
||||
class {
|
||||
@(decorators[0])
|
||||
method() {}
|
||||
@@ -19,6 +31,10 @@
|
||||
@(decorators?.at(0))
|
||||
method() {}
|
||||
},
|
||||
class {
|
||||
@(decorators.at?.(0))
|
||||
method() {}
|
||||
},
|
||||
class {
|
||||
@(decorators.first)
|
||||
method() {}
|
||||
|
||||
@@ -301,7 +301,7 @@ semi: false
|
||||
class X {}
|
||||
|
||||
=====================================output=====================================
|
||||
@test().x("global").y()
|
||||
@(test().x("global").y())
|
||||
class X {}
|
||||
|
||||
================================================================================
|
||||
@@ -317,7 +317,7 @@ printWidth: 80
|
||||
class X {}
|
||||
|
||||
=====================================output=====================================
|
||||
@test().x("global").y()
|
||||
@(test().x("global").y())
|
||||
class X {}
|
||||
|
||||
================================================================================
|
||||
@@ -337,7 +337,7 @@ class Test {
|
||||
|
||||
=====================================output=====================================
|
||||
class Test {
|
||||
@foo\`bar\`
|
||||
@(foo\`bar\`)
|
||||
text: string = "text"
|
||||
}
|
||||
|
||||
@@ -357,7 +357,7 @@ class Test {
|
||||
|
||||
=====================================output=====================================
|
||||
class Test {
|
||||
@foo\`bar\`
|
||||
@(foo\`bar\`)
|
||||
text: string = "text";
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user