Report grammar errors for invalid decorator grammar (#57749)

This commit is contained in:
Ron Buckton 2024-03-13 14:50:04 -04:00 committed by GitHub
parent c1f0f7cb58
commit 5e8f900afa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 1553 additions and 50 deletions

View File

@ -651,6 +651,7 @@ import {
isNewExpression,
isNodeDescendantOf,
isNonNullAccess,
isNonNullExpression,
isNullishCoalesce,
isNumericLiteral,
isNumericLiteralName,
@ -41572,8 +41573,82 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
function checkGrammarDecorator(decorator: Decorator): boolean {
const sourceFile = getSourceFileOfNode(decorator);
if (!hasParseDiagnostics(sourceFile)) {
let node: Expression = decorator.expression;
// DecoratorParenthesizedExpression :
// `(` Expression `)`
if (isParenthesizedExpression(node)) {
return false;
}
let canHaveCallExpression = true;
let errorNode: Node | undefined;
while (true) {
// Allow TS syntax such as non-null assertions and instantiation expressions
if (isExpressionWithTypeArguments(node) || isNonNullExpression(node)) {
node = node.expression;
continue;
}
// DecoratorCallExpression :
// DecoratorMemberExpression Arguments
if (isCallExpression(node)) {
if (!canHaveCallExpression) {
errorNode = node;
}
if (node.questionDotToken) {
// Even if we already have an error node, error at the `?.` token since it appears earlier.
errorNode = node.questionDotToken;
}
node = node.expression;
canHaveCallExpression = false;
continue;
}
// DecoratorMemberExpression :
// IdentifierReference
// DecoratorMemberExpression `.` IdentifierName
// DecoratorMemberExpression `.` PrivateIdentifier
if (isPropertyAccessExpression(node)) {
if (node.questionDotToken) {
// Even if we already have an error node, error at the `?.` token since it appears earlier.
errorNode = node.questionDotToken;
}
node = node.expression;
canHaveCallExpression = false;
continue;
}
if (!isIdentifier(node)) {
// Even if we already have an error node, error at this node since it appears earlier.
errorNode = node;
}
break;
}
if (errorNode) {
addRelatedInfo(
error(decorator.expression, Diagnostics.Expression_must_be_enclosed_in_parentheses_to_be_used_as_a_decorator),
createDiagnosticForNode(errorNode, Diagnostics.Invalid_syntax_in_decorator),
);
return true;
}
}
return false;
}
/** Check a decorator */
function checkDecorator(node: Decorator): void {
checkGrammarDecorator(node);
const signature = getResolvedSignature(node);
checkDeprecatedSignature(signature, node);
const returnType = getReturnTypeOfSignature(signature);

View File

@ -1637,6 +1637,14 @@
"category": "Error",
"code": 1496
},
"Expression must be enclosed in parentheses to be used as a decorator.": {
"category": "Error",
"code": 1497
},
"Invalid syntax in decorator.": {
"category": "Error",
"code": 1498
},
"The types of '{0}' are incompatible between these types.": {
"category": "Error",
@ -7792,6 +7800,14 @@
"category": "Message",
"code": 95193
},
"Wrap in parentheses": {
"category": "Message",
"code": 95194
},
"Wrap all invalid decorator expressions in parentheses": {
"category": "Message",
"code": 95195
},
"No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": {
"category": "Error",

View File

@ -64,6 +64,7 @@ export * from "../codefixes/useDefaultImport";
export * from "../codefixes/useBigintLiteral";
export * from "../codefixes/fixAddModuleReferTypeMissingTypeof";
export * from "../codefixes/wrapJsxInFragment";
export * from "../codefixes/wrapDecoratorInParentheses";
export * from "../codefixes/convertToMappedObjectType";
export * from "../codefixes/removeAccidentalCallParentheses";
export * from "../codefixes/removeUnnecessaryAwait";

View File

@ -0,0 +1,35 @@
import {
Debug,
Diagnostics,
factory,
findAncestor,
getTokenAtPosition,
isDecorator,
SourceFile,
textChanges,
} from "../_namespaces/ts";
import {
codeFixAll,
createCodeFixAction,
registerCodeFix,
} from "../_namespaces/ts.codefix";
const fixId = "wrapDecoratorInParentheses";
const errorCodes = [Diagnostics.Expression_must_be_enclosed_in_parentheses_to_be_used_as_a_decorator.code];
registerCodeFix({
errorCodes,
getCodeActions: function getCodeActionsToWrapDecoratorExpressionInParentheses(context) {
const changes = textChanges.ChangeTracker.with(context, t => makeChange(t, context.sourceFile, context.span.start));
return [createCodeFixAction(fixId, changes, Diagnostics.Wrap_in_parentheses, fixId, Diagnostics.Wrap_all_invalid_decorator_expressions_in_parentheses)];
},
fixIds: [fixId],
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => makeChange(changes, diag.file, diag.start)),
});
function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number) {
const token = getTokenAtPosition(sourceFile, pos);
const decorator = findAncestor(token, isDecorator)!;
Debug.assert(!!decorator, "Expected position to be owned by a decorator.");
const replacement = factory.createParenthesizedExpression(decorator.expression);
changeTracker.replaceNode(sourceFile, decorator.expression, replacement);
}

View File

@ -128,42 +128,43 @@ export class CompilerBaselineRunner extends RunnerBase {
class CompilerTest {
private static varyBy: readonly string[] = [
"module",
"moduleResolution",
"moduleDetection",
"allowArbitraryExtensions",
"allowImportingTsExtensions",
"target",
"jsx",
"noEmit",
"removeComments",
"importHelpers",
"importHelpers",
"downlevelIteration",
"isolatedModules",
"verbatimModuleSyntax",
"strict",
"noImplicitAny",
"strictNullChecks",
"strictFunctionTypes",
"strictBindCallApply",
"strictPropertyInitialization",
"noImplicitThis",
"alwaysStrict",
"allowSyntheticDefaultImports",
"esModuleInterop",
"alwaysStrict",
"downlevelIteration",
"experimentalDecorators",
"emitDecoratorMetadata",
"skipDefaultLibCheck",
"preserveConstEnums",
"skipLibCheck",
"esModuleInterop",
"exactOptionalPropertyTypes",
"useDefineForClassFields",
"useUnknownInCatchVariables",
"noUncheckedIndexedAccess",
"importHelpers",
"importHelpers",
"isolatedModules",
"jsx",
"module",
"moduleDetection",
"moduleResolution",
"noEmit",
"noImplicitAny",
"noImplicitThis",
"noPropertyAccessFromIndexSignature",
"noUncheckedIndexedAccess",
"preserveConstEnums",
"removeComments",
"resolveJsonModule",
"resolvePackageJsonExports",
"resolvePackageJsonImports",
"resolveJsonModule",
"allowArbitraryExtensions",
"skipDefaultLibCheck",
"skipLibCheck",
"strict",
"strictBindCallApply",
"strictFunctionTypes",
"strictNullChecks",
"strictPropertyInitialization",
"target",
"useDefineForClassFields",
"useUnknownInCatchVariables",
"verbatimModuleSyntax",
];
private fileName: string;
private justName: string;

View File

@ -1,4 +1,4 @@
decoratorOnClassMethod11.ts(5,10): error TS2331: 'this' cannot be referenced in a module or namespace body.
decoratorOnClassMethod11.ts(5,11): error TS2331: 'this' cannot be referenced in a module or namespace body.
==== decoratorOnClassMethod11.ts (1 errors) ====
@ -6,8 +6,8 @@ decoratorOnClassMethod11.ts(5,10): error TS2331: 'this' cannot be referenced in
class C {
decorator(target: Object, key: string): void { }
@this.decorator
~~~~
@(this.decorator)
~~~~
!!! error TS2331: 'this' cannot be referenced in a module or namespace body.
method() { }
}

View File

@ -5,7 +5,7 @@ module M {
class C {
decorator(target: Object, key: string): void { }
@this.decorator
@(this.decorator)
method() { }
}
}
@ -25,7 +25,7 @@ var M;
C.prototype.decorator = function (target, key) { };
C.prototype.method = function () { };
__decorate([
this.decorator
(this.decorator)
], C.prototype, "method", null);
return C;
}());

View File

@ -13,7 +13,7 @@ module M {
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>key : Symbol(key, Decl(decoratorOnClassMethod11.ts, 2, 33))
@this.decorator
@(this.decorator)
method() { }
>method : Symbol(C.method, Decl(decoratorOnClassMethod11.ts, 2, 56))
}

View File

@ -12,7 +12,8 @@ module M {
>target : Object
>key : string
@this.decorator
@(this.decorator)
>(this.decorator) : any
>this.decorator : any
>this : any
>decorator : any

View File

@ -1,4 +1,4 @@
decoratorOnClassMethod12.ts(6,10): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions.
decoratorOnClassMethod12.ts(6,11): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions.
==== decoratorOnClassMethod12.ts (1 errors) ====
@ -7,8 +7,8 @@ decoratorOnClassMethod12.ts(6,10): error TS2660: 'super' can only be referenced
decorator(target: Object, key: string): void { }
}
class C extends S {
@super.decorator
~~~~~
@(super.decorator)
~~~~~
!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions.
method() { }
}

View File

@ -6,7 +6,7 @@ module M {
decorator(target: Object, key: string): void { }
}
class C extends S {
@super.decorator
@(super.decorator)
method() { }
}
}
@ -48,7 +48,7 @@ var M;
}
C.prototype.method = function () { };
__decorate([
_super.decorator
(_super.decorator)
], C.prototype, "method", null);
return C;
}(S));

View File

@ -17,7 +17,7 @@ module M {
>C : Symbol(C, Decl(decoratorOnClassMethod12.ts, 3, 5))
>S : Symbol(S, Decl(decoratorOnClassMethod12.ts, 0, 10))
@super.decorator
@(super.decorator)
method() { }
>method : Symbol(C.method, Decl(decoratorOnClassMethod12.ts, 4, 23))
}

View File

@ -16,7 +16,8 @@ module M {
>C : C
>S : S
@super.decorator
@(super.decorator)
>(super.decorator) : any
>super.decorator : any
>super : any
>decorator : any

View File

@ -0,0 +1,137 @@
esDecorators-decoratorExpression.1.ts(3,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(5,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(7,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(9,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(11,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(13,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(15,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(17,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(19,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(21,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(23,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(25,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(27,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(29,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(31,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(33,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(35,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(37,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(39,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(41,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(43,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(45,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
==== esDecorators-decoratorExpression.1.ts (22 errors) ====
declare let x: any;
{ @x().y class C {} }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:3:4: Invalid syntax in decorator.
{ @new x class C {} }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:5:4: Invalid syntax in decorator.
{ @x().y() class C {} }
~~~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:7:4: Invalid syntax in decorator.
{ @x?.y class C {} }
~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:9:5: Invalid syntax in decorator.
{ @x?.y() class C {} }
~~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:11:5: Invalid syntax in decorator.
{ @x?.["y"] class C {} }
~~~~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:13:4: Invalid syntax in decorator.
{ @x?.() class C {} }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:15:5: Invalid syntax in decorator.
{ @x`` class C {} }
~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:17:4: Invalid syntax in decorator.
{ @x``() class C {} }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:19:4: Invalid syntax in decorator.
{ @x.y`` class C {} }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:21:4: Invalid syntax in decorator.
{ @x.y``() class C {} }
~~~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:23:4: Invalid syntax in decorator.
{ class C { @x().y m() {} } }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:25:14: Invalid syntax in decorator.
{ class C { @new x m() {} } }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:27:14: Invalid syntax in decorator.
{ class C { @x().y() m() {} } }
~~~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:29:14: Invalid syntax in decorator.
{ class C { @x?.y m() {} } }
~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:31:15: Invalid syntax in decorator.
{ class C { @x?.y() m() {} } }
~~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:33:15: Invalid syntax in decorator.
{ class C { @x?.["y"] m() {} } }
~~~~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:35:14: Invalid syntax in decorator.
{ class C { @x?.() m() {} } }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:37:15: Invalid syntax in decorator.
{ class C { @x`` m() {} } }
~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:39:14: Invalid syntax in decorator.
{ class C { @x``() m() {} } }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:41:14: Invalid syntax in decorator.
{ class C { @x.y`` m() {} } }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:43:14: Invalid syntax in decorator.
{ class C { @x.y``() m() {} } }
~~~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:45:14: Invalid syntax in decorator.

View File

@ -0,0 +1,172 @@
//// [tests/cases/conformance/esDecorators/esDecorators-decoratorExpression.1.ts] ////
//// [esDecorators-decoratorExpression.1.ts]
declare let x: any;
{ @x().y class C {} }
{ @new x class C {} }
{ @x().y() class C {} }
{ @x?.y class C {} }
{ @x?.y() class C {} }
{ @x?.["y"] class C {} }
{ @x?.() class C {} }
{ @x`` class C {} }
{ @x``() class C {} }
{ @x.y`` class C {} }
{ @x.y``() class C {} }
{ class C { @x().y m() {} } }
{ class C { @new x m() {} } }
{ class C { @x().y() m() {} } }
{ class C { @x?.y m() {} } }
{ class C { @x?.y() m() {} } }
{ class C { @x?.["y"] m() {} } }
{ class C { @x?.() m() {} } }
{ class C { @x`` m() {} } }
{ class C { @x``() m() {} } }
{ class C { @x.y`` m() {} } }
{ class C { @x.y``() m() {} } }
//// [esDecorators-decoratorExpression.1.js]
{
@x().y
class C {
}
}
{
@new x
class C {
}
}
{
@x().y()
class C {
}
}
{
@x?.y
class C {
}
}
{
@x?.y()
class C {
}
}
{
@x?.["y"]
class C {
}
}
{
@x?.()
class C {
}
}
{
@x ``
class C {
}
}
{
@x ``()
class C {
}
}
{
@x.y ``
class C {
}
}
{
@x.y ``()
class C {
}
}
{
class C {
@x().y
m() { }
}
}
{
class C {
@new x
m() { }
}
}
{
class C {
@x().y()
m() { }
}
}
{
class C {
@x?.y
m() { }
}
}
{
class C {
@x?.y()
m() { }
}
}
{
class C {
@x?.["y"]
m() { }
}
}
{
class C {
@x?.()
m() { }
}
}
{
class C {
@x ``
m() { }
}
}
{
class C {
@x ``()
m() { }
}
}
{
class C {
@x.y ``
m() { }
}
}
{
class C {
@x.y ``()
m() { }
}
}

View File

@ -0,0 +1,137 @@
esDecorators-decoratorExpression.1.ts(3,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(5,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(7,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(9,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(11,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(13,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(15,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(17,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(19,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(21,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(23,4): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(25,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(27,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(29,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(31,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(33,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(35,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(37,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(39,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(41,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(43,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
esDecorators-decoratorExpression.1.ts(45,14): error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
==== esDecorators-decoratorExpression.1.ts (22 errors) ====
declare let x: any;
{ @x().y class C {} }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:3:4: Invalid syntax in decorator.
{ @new x class C {} }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:5:4: Invalid syntax in decorator.
{ @x().y() class C {} }
~~~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:7:4: Invalid syntax in decorator.
{ @x?.y class C {} }
~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:9:5: Invalid syntax in decorator.
{ @x?.y() class C {} }
~~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:11:5: Invalid syntax in decorator.
{ @x?.["y"] class C {} }
~~~~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:13:4: Invalid syntax in decorator.
{ @x?.() class C {} }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:15:5: Invalid syntax in decorator.
{ @x`` class C {} }
~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:17:4: Invalid syntax in decorator.
{ @x``() class C {} }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:19:4: Invalid syntax in decorator.
{ @x.y`` class C {} }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:21:4: Invalid syntax in decorator.
{ @x.y``() class C {} }
~~~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:23:4: Invalid syntax in decorator.
{ class C { @x().y m() {} } }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:25:14: Invalid syntax in decorator.
{ class C { @new x m() {} } }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:27:14: Invalid syntax in decorator.
{ class C { @x().y() m() {} } }
~~~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:29:14: Invalid syntax in decorator.
{ class C { @x?.y m() {} } }
~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:31:15: Invalid syntax in decorator.
{ class C { @x?.y() m() {} } }
~~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:33:15: Invalid syntax in decorator.
{ class C { @x?.["y"] m() {} } }
~~~~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:35:14: Invalid syntax in decorator.
{ class C { @x?.() m() {} } }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:37:15: Invalid syntax in decorator.
{ class C { @x`` m() {} } }
~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:39:14: Invalid syntax in decorator.
{ class C { @x``() m() {} } }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:41:14: Invalid syntax in decorator.
{ class C { @x.y`` m() {} } }
~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:43:14: Invalid syntax in decorator.
{ class C { @x.y``() m() {} } }
~~~~~~~
!!! error TS1497: Expression must be enclosed in parentheses to be used as a decorator.
!!! related TS1498 esDecorators-decoratorExpression.1.ts:45:14: Invalid syntax in decorator.

View File

@ -0,0 +1,216 @@
//// [tests/cases/conformance/esDecorators/esDecorators-decoratorExpression.1.ts] ////
//// [esDecorators-decoratorExpression.1.ts]
declare let x: any;
{ @x().y class C {} }
{ @new x class C {} }
{ @x().y() class C {} }
{ @x?.y class C {} }
{ @x?.y() class C {} }
{ @x?.["y"] class C {} }
{ @x?.() class C {} }
{ @x`` class C {} }
{ @x``() class C {} }
{ @x.y`` class C {} }
{ @x.y``() class C {} }
{ class C { @x().y m() {} } }
{ class C { @new x m() {} } }
{ class C { @x().y() m() {} } }
{ class C { @x?.y m() {} } }
{ class C { @x?.y() m() {} } }
{ class C { @x?.["y"] m() {} } }
{ class C { @x?.() m() {} } }
{ class C { @x`` m() {} } }
{ class C { @x``() m() {} } }
{ class C { @x.y`` m() {} } }
{ class C { @x.y``() m() {} } }
//// [esDecorators-decoratorExpression.1.js]
{
let C = class C {
};
C = __decorate([
x().y
], C);
}
{
let C = class C {
};
C = __decorate([
new x
], C);
}
{
let C = class C {
};
C = __decorate([
x().y()
], C);
}
{
let C = class C {
};
C = __decorate([
x?.y
], C);
}
{
let C = class C {
};
C = __decorate([
x?.y()
], C);
}
{
let C = class C {
};
C = __decorate([
x?.["y"]
], C);
}
{
let C = class C {
};
C = __decorate([
x?.()
], C);
}
{
let C = class C {
};
C = __decorate([
x ``
], C);
}
{
let C = class C {
};
C = __decorate([
x ``()
], C);
}
{
let C = class C {
};
C = __decorate([
x.y ``
], C);
}
{
let C = class C {
};
C = __decorate([
x.y ``()
], C);
}
{
class C {
m() { }
}
__decorate([
x().y
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
new x
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
x().y()
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
x?.y
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
x?.y()
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
x?.["y"]
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
x?.()
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
x ``
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
x ``()
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
x.y ``
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
x.y ``()
], C.prototype, "m", null);
}

View File

@ -0,0 +1,204 @@
//// [tests/cases/conformance/esDecorators/esDecorators-decoratorExpression.2.ts] ////
//// [esDecorators-decoratorExpression.2.ts]
declare let x: any;
declare let g: <T>(...args: any) => any;
declare let h: () => <T>(...args: any) => any;
{ @x! class C {} }
{ @x.y! class C {} }
{ @x!.y class C {} }
{ @g<number>() class C {} }
{ @(g<number>) class C {} }
{ @(h()<number>) class C {} }
{ @(x().y) class C {} }
{ @(x().y()) class C {} }
{ @(x``) class C {} }
{ @(x.y``) class C {} }
{ @(x?.y!) class C {} }
{ @(x["y"]) class C {} }
{ @(x?.["y"]) class C {} }
{ class C { @x! m() {} } }
{ class C { @x.y! m() {} } }
{ class C { @x!.y m() {} } }
{ class C { @g<number>() m() {} } }
{ class C { @(g<number>) m() {} } }
{ class C { @(h()<number>) m() {} } }
{ class C { @(x().y) m() {} } }
{ class C { @(x().y()) m() {} } }
{ class C { @(x``) m() {} } }
{ class C { @(x.y``) m() {} } }
{ class C { @(x?.y!) m() {} } }
{ class C { @(x["y"]) m() {} } }
{ class C { @(x?.["y"]) m() {} } }
//// [esDecorators-decoratorExpression.2.js]
{
@x
class C {
}
}
{
@x.y
class C {
}
}
{
@x.y
class C {
}
}
{
@g()
class C {
}
}
{
@(g)
class C {
}
}
{
@(h())
class C {
}
}
{
@(x().y)
class C {
}
}
{
@(x().y())
class C {
}
}
{
@(x ``)
class C {
}
}
{
@(x.y ``)
class C {
}
}
{
@(x?.y)
class C {
}
}
{
@(x["y"])
class C {
}
}
{
@(x?.["y"])
class C {
}
}
{
class C {
@x
m() { }
}
}
{
class C {
@x.y
m() { }
}
}
{
class C {
@x.y
m() { }
}
}
{
class C {
@g()
m() { }
}
}
{
class C {
@(g)
m() { }
}
}
{
class C {
@(h())
m() { }
}
}
{
class C {
@(x().y)
m() { }
}
}
{
class C {
@(x().y())
m() { }
}
}
{
class C {
@(x ``)
m() { }
}
}
{
class C {
@(x.y ``)
m() { }
}
}
{
class C {
@(x?.y)
m() { }
}
}
{
class C {
@(x["y"])
m() { }
}
}
{
class C {
@(x?.["y"])
m() { }
}
}

View File

@ -0,0 +1,256 @@
//// [tests/cases/conformance/esDecorators/esDecorators-decoratorExpression.2.ts] ////
//// [esDecorators-decoratorExpression.2.ts]
declare let x: any;
declare let g: <T>(...args: any) => any;
declare let h: () => <T>(...args: any) => any;
{ @x! class C {} }
{ @x.y! class C {} }
{ @x!.y class C {} }
{ @g<number>() class C {} }
{ @(g<number>) class C {} }
{ @(h()<number>) class C {} }
{ @(x().y) class C {} }
{ @(x().y()) class C {} }
{ @(x``) class C {} }
{ @(x.y``) class C {} }
{ @(x?.y!) class C {} }
{ @(x["y"]) class C {} }
{ @(x?.["y"]) class C {} }
{ class C { @x! m() {} } }
{ class C { @x.y! m() {} } }
{ class C { @x!.y m() {} } }
{ class C { @g<number>() m() {} } }
{ class C { @(g<number>) m() {} } }
{ class C { @(h()<number>) m() {} } }
{ class C { @(x().y) m() {} } }
{ class C { @(x().y()) m() {} } }
{ class C { @(x``) m() {} } }
{ class C { @(x.y``) m() {} } }
{ class C { @(x?.y!) m() {} } }
{ class C { @(x["y"]) m() {} } }
{ class C { @(x?.["y"]) m() {} } }
//// [esDecorators-decoratorExpression.2.js]
{
let C = class C {
};
C = __decorate([
x
], C);
}
{
let C = class C {
};
C = __decorate([
x.y
], C);
}
{
let C = class C {
};
C = __decorate([
x.y
], C);
}
{
let C = class C {
};
C = __decorate([
g()
], C);
}
{
let C = class C {
};
C = __decorate([
(g)
], C);
}
{
let C = class C {
};
C = __decorate([
(h())
], C);
}
{
let C = class C {
};
C = __decorate([
(x().y)
], C);
}
{
let C = class C {
};
C = __decorate([
(x().y())
], C);
}
{
let C = class C {
};
C = __decorate([
(x ``)
], C);
}
{
let C = class C {
};
C = __decorate([
(x.y ``)
], C);
}
{
let C = class C {
};
C = __decorate([
(x?.y)
], C);
}
{
let C = class C {
};
C = __decorate([
(x["y"])
], C);
}
{
let C = class C {
};
C = __decorate([
(x?.["y"])
], C);
}
{
class C {
m() { }
}
__decorate([
x
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
x.y
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
x.y
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
g()
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
(g)
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
(h())
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
(x().y)
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
(x().y())
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
(x ``)
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
(x.y ``)
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
(x?.y)
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
(x["y"])
], C.prototype, "m", null);
}
{
class C {
m() { }
}
__decorate([
(x?.["y"])
], C.prototype, "m", null);
}

View File

@ -0,0 +1,23 @@
esDecorators-decoratorExpression.3.ts(5,5): error TS1146: Declaration expected.
esDecorators-decoratorExpression.3.ts(5,5): error TS2352: Conversion of type 'typeof C' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
esDecorators-decoratorExpression.3.ts(7,7): error TS1146: Declaration expected.
esDecorators-decoratorExpression.3.ts(7,7): error TS2352: Conversion of type 'typeof C' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
==== esDecorators-decoratorExpression.3.ts (4 errors) ====
declare let g: <T>(...args: any) => any;
// existing errors
{ @g<number> class C {} }
!!! error TS1146: Declaration expected.
~~~~~~~~~~~~~~~~~~~
!!! error TS2352: Conversion of type 'typeof C' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
{ @g()<number> class C {} }
!!! error TS1146: Declaration expected.
~~~~~~~~~~~~~~~~~~~
!!! error TS2352: Conversion of type 'typeof C' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.

View File

@ -0,0 +1,22 @@
//// [tests/cases/conformance/esDecorators/esDecorators-decoratorExpression.3.ts] ////
//// [esDecorators-decoratorExpression.3.ts]
declare let g: <T>(...args: any) => any;
// existing errors
{ @g<number> class C {} }
{ @g()<number> class C {} }
//// [esDecorators-decoratorExpression.3.js]
// existing errors
{
class C {
};
}
{
class C {
};
}

View File

@ -0,0 +1,23 @@
esDecorators-decoratorExpression.3.ts(5,5): error TS1146: Declaration expected.
esDecorators-decoratorExpression.3.ts(5,5): error TS2352: Conversion of type 'typeof C' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
esDecorators-decoratorExpression.3.ts(7,7): error TS1146: Declaration expected.
esDecorators-decoratorExpression.3.ts(7,7): error TS2352: Conversion of type 'typeof C' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
==== esDecorators-decoratorExpression.3.ts (4 errors) ====
declare let g: <T>(...args: any) => any;
// existing errors
{ @g<number> class C {} }
!!! error TS1146: Declaration expected.
~~~~~~~~~~~~~~~~~~~
!!! error TS2352: Conversion of type 'typeof C' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
{ @g()<number> class C {} }
!!! error TS1146: Declaration expected.
~~~~~~~~~~~~~~~~~~~
!!! error TS2352: Conversion of type 'typeof C' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.

View File

@ -0,0 +1,22 @@
//// [tests/cases/conformance/esDecorators/esDecorators-decoratorExpression.3.ts] ////
//// [esDecorators-decoratorExpression.3.ts]
declare let g: <T>(...args: any) => any;
// existing errors
{ @g<number> class C {} }
{ @g()<number> class C {} }
//// [esDecorators-decoratorExpression.3.js]
// existing errors
{
class C {
};
}
{
class C {
};
}

View File

@ -26,7 +26,7 @@ class C {
class D extends DecoratorProvider {
m() {
class C {
@super.decorate
@(super.decorate)
method1() { }
@(super["decorate"])
@ -114,7 +114,7 @@ class D extends DecoratorProvider {
return class C {
static {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
_method1_decorators = [super.decorate.bind(_outerThis)];
_method1_decorators = [(super.decorate.bind(_outerThis))];
_method2_decorators = [(super["decorate"].bind(_outerThis))];
_method3_decorators = [((super.decorate.bind(_outerThis)))];
__esDecorate(this, null, _method1_decorators, { kind: "method", name: "method1", static: false, private: false, access: { has: obj => "method1" in obj, get: obj => obj.method1 }, metadata: _metadata }, null, _instanceExtraInitializers);

View File

@ -62,7 +62,7 @@ class D extends DecoratorProvider {
class C {
>C : Symbol(C, Decl(esDecorators-preservesThis.ts, 23, 9))
@super.decorate
@(super.decorate)
>super.decorate : Symbol(DecoratorProvider.decorate, Decl(esDecorators-preservesThis.ts, 2, 33))
>super : Symbol(DecoratorProvider, Decl(esDecorators-preservesThis.ts, 0, 0))
>decorate : Symbol(DecoratorProvider.decorate, Decl(esDecorators-preservesThis.ts, 2, 33))

View File

@ -60,7 +60,8 @@ class D extends DecoratorProvider {
class C {
>C : C
@super.decorate
@(super.decorate)
>(super.decorate) : <T>(this: DecoratorProvider, v: T, ctx: DecoratorContext) => T
>super.decorate : <T>(this: DecoratorProvider, v: T, ctx: DecoratorContext) => T
>super : DecoratorProvider
>decorate : <T>(this: DecoratorProvider, v: T, ctx: DecoratorContext) => T

View File

@ -4,7 +4,7 @@ module M {
class C {
decorator(target: Object, key: string): void { }
@this.decorator
@(this.decorator)
method() { }
}
}

View File

@ -5,7 +5,7 @@ module M {
decorator(target: Object, key: string): void { }
}
class C extends S {
@super.decorator
@(super.decorator)
method() { }
}
}

View File

@ -0,0 +1,50 @@
// @target: esnext
// @experimentalDecorators: *
// @noEmitHelpers: true
// @noTypesAndSymbols: true
declare let x: any;
{ @x().y class C {} }
{ @new x class C {} }
{ @x().y() class C {} }
{ @x?.y class C {} }
{ @x?.y() class C {} }
{ @x?.["y"] class C {} }
{ @x?.() class C {} }
{ @x`` class C {} }
{ @x``() class C {} }
{ @x.y`` class C {} }
{ @x.y``() class C {} }
{ class C { @x().y m() {} } }
{ class C { @new x m() {} } }
{ class C { @x().y() m() {} } }
{ class C { @x?.y m() {} } }
{ class C { @x?.y() m() {} } }
{ class C { @x?.["y"] m() {} } }
{ class C { @x?.() m() {} } }
{ class C { @x`` m() {} } }
{ class C { @x``() m() {} } }
{ class C { @x.y`` m() {} } }
{ class C { @x.y``() m() {} } }

View File

@ -0,0 +1,60 @@
// @target: esnext
// @experimentalDecorators: *
// @noEmitHelpers: true
// @noTypesAndSymbols: true
declare let x: any;
declare let g: <T>(...args: any) => any;
declare let h: () => <T>(...args: any) => any;
{ @x! class C {} }
{ @x.y! class C {} }
{ @x!.y class C {} }
{ @g<number>() class C {} }
{ @(g<number>) class C {} }
{ @(h()<number>) class C {} }
{ @(x().y) class C {} }
{ @(x().y()) class C {} }
{ @(x``) class C {} }
{ @(x.y``) class C {} }
{ @(x?.y!) class C {} }
{ @(x["y"]) class C {} }
{ @(x?.["y"]) class C {} }
{ class C { @x! m() {} } }
{ class C { @x.y! m() {} } }
{ class C { @x!.y m() {} } }
{ class C { @g<number>() m() {} } }
{ class C { @(g<number>) m() {} } }
{ class C { @(h()<number>) m() {} } }
{ class C { @(x().y) m() {} } }
{ class C { @(x().y()) m() {} } }
{ class C { @(x``) m() {} } }
{ class C { @(x.y``) m() {} } }
{ class C { @(x?.y!) m() {} } }
{ class C { @(x["y"]) m() {} } }
{ class C { @(x?.["y"]) m() {} } }

View File

@ -0,0 +1,12 @@
// @target: esnext
// @experimentalDecorators: *
// @noEmitHelpers: true
// @noTypesAndSymbols: true
declare let g: <T>(...args: any) => any;
// existing errors
{ @g<number> class C {} }
{ @g()<number> class C {} }

View File

@ -24,7 +24,7 @@ class C {
class D extends DecoratorProvider {
m() {
class C {
@super.decorate
@(super.decorate)
method1() { }
@(super["decorate"])

View File

@ -0,0 +1,14 @@
/// <reference path='fourslash.ts' />
////declare var x: any;
////class C {
//// @[|x?.y|]
//// bar() {
////
//// }
////}
verify.codeFix({
description: "Wrap in parentheses",
newRangeContent: `(x?.y)`
});

View File

@ -0,0 +1,24 @@
/// <reference path='fourslash.ts' />
////declare var x: any;
////class C {
//// @x?.y
//// bar() {}
////
//// @x?.()
//// baz() {}
////}
verify.codeFixAll({
fixId: "wrapDecoratorInParentheses",
fixAllDescription: "Wrap all invalid decorator expressions in parentheses",
newFileContent:
`declare var x: any;
class C {
@(x?.y)
bar() {}
@(x?.())
baz() {}
}`
});