Corrected parsing for decorators on 'this' parameters (#43175)

* Corrected parsing for decorators on 'this' parameters

* Moved checking to parser and added a specific test

* Remove unrelated checker.ts blank line

* Missed some baseeline updates...
This commit is contained in:
Josh Goldberg
2021-04-07 11:21:28 -07:00
committed by GitHub
parent 2484210a00
commit 905a1fea39
15 changed files with 175 additions and 33 deletions
+4
View File
@@ -1360,6 +1360,10 @@
"category": "Error",
"code": 1432
},
"Decorators may not be applied to 'this' parameters.": {
"category": "Error",
"code": 1433
},
"The types of '{0}' are incompatible between these types.": {
"category": "Error",
+13 -6
View File
@@ -2991,9 +2991,16 @@ namespace ts {
function parseParameterWorker(inOuterAwaitContext: boolean): ParameterDeclaration {
const pos = getNodePos();
const hasJSDoc = hasPrecedingJSDocComment();
// FormalParameter [Yield,Await]:
// BindingElement[?Yield,?Await]
// Decorators are parsed in the outer [Await] context, the rest of the parameter is parsed in the function's [Await] context.
const decorators = inOuterAwaitContext ? doInAwaitContext(parseDecorators) : parseDecorators();
if (token() === SyntaxKind.ThisKeyword) {
const node = factory.createParameterDeclaration(
/*decorators*/ undefined,
decorators,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
createIdentifier(/*isIdentifier*/ true),
@@ -3001,14 +3008,14 @@ namespace ts {
parseTypeAnnotation(),
/*initializer*/ undefined
);
if (decorators) {
parseErrorAtRange(decorators[0], Diagnostics.Decorators_may_not_be_applied_to_this_parameters);
}
return withJSDoc(finishNode(node, pos), hasJSDoc);
}
// FormalParameter [Yield,Await]:
// BindingElement[?Yield,?Await]
// Decorators are parsed in the outer [Await] context, the rest of the parameter is parsed in the function's [Await] context.
const decorators = inOuterAwaitContext ? doInAwaitContext(parseDecorators) : parseDecorators();
const savedTopLevel = topLevel;
topLevel = false;
const modifiers = parseModifiers();
@@ -1,14 +1,21 @@
tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodThisParameter.ts(4,17): error TS1359: Identifier expected. 'this' is a reserved word that cannot be used here.
tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodThisParameter.ts(4,17): error TS2680: A 'this' parameter must be the first parameter.
tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodThisParameter.ts(4,12): error TS1433: Decorators may not be applied to 'this' parameters.
tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodThisParameter.ts(8,29): error TS1433: Decorators may not be applied to 'this' parameters.
tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodThisParameter.ts(8,30): error TS2680: A 'this' parameter must be the first parameter.
==== tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodThisParameter.ts (2 errors) ====
==== tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodThisParameter.ts (3 errors) ====
declare function dec(target: Object, propertyKey: string | symbol, parameterIndex: number): void;
class C {
method(@dec this: C) {}
~~~~
!!! error TS1359: Identifier expected. 'this' is a reserved word that cannot be used here.
~~~~~~~
~~~~
!!! error TS1433: Decorators may not be applied to 'this' parameters.
}
class C2 {
method(@dec allowed: C2, @dec this: C2) {}
~~~~~
!!! error TS1433: Decorators may not be applied to 'this' parameters.
~~~~~~~~~~~~~
!!! error TS2680: A 'this' parameter must be the first parameter.
}
@@ -3,6 +3,10 @@ declare function dec(target: Object, propertyKey: string | symbol, parameterInde
class C {
method(@dec this: C) {}
}
class C2 {
method(@dec allowed: C2, @dec this: C2) {}
}
//// [decoratorOnClassMethodThisParameter.js]
@@ -19,8 +23,14 @@ var C = /** @class */ (function () {
function C() {
}
C.prototype.method = function () { };
__decorate([
__param(0, dec)
], C.prototype, "method", null);
return C;
}());
var C2 = /** @class */ (function () {
function C2() {
}
C2.prototype.method = function (allowed) { };
__decorate([
__param(0, dec), __param(1, dec)
], C2.prototype, "method", null);
return C2;
}());
@@ -12,7 +12,19 @@ class C {
method(@dec this: C) {}
>method : Symbol(C.method, Decl(decoratorOnClassMethodThisParameter.ts, 2, 9))
>dec : Symbol(dec, Decl(decoratorOnClassMethodThisParameter.ts, 0, 0))
> : Symbol((Missing), Decl(decoratorOnClassMethodThisParameter.ts, 3, 11))
>this : Symbol(this, Decl(decoratorOnClassMethodThisParameter.ts, 3, 15))
>this : Symbol(this, Decl(decoratorOnClassMethodThisParameter.ts, 3, 11))
>C : Symbol(C, Decl(decoratorOnClassMethodThisParameter.ts, 0, 97))
}
class C2 {
>C2 : Symbol(C2, Decl(decoratorOnClassMethodThisParameter.ts, 4, 1))
method(@dec allowed: C2, @dec this: C2) {}
>method : Symbol(C2.method, Decl(decoratorOnClassMethodThisParameter.ts, 6, 10))
>dec : Symbol(dec, Decl(decoratorOnClassMethodThisParameter.ts, 0, 0))
>allowed : Symbol(allowed, Decl(decoratorOnClassMethodThisParameter.ts, 7, 11))
>C2 : Symbol(C2, Decl(decoratorOnClassMethodThisParameter.ts, 4, 1))
>dec : Symbol(dec, Decl(decoratorOnClassMethodThisParameter.ts, 0, 0))
>this : Symbol(this, Decl(decoratorOnClassMethodThisParameter.ts, 7, 28))
>C2 : Symbol(C2, Decl(decoratorOnClassMethodThisParameter.ts, 4, 1))
}
@@ -9,8 +9,18 @@ class C {
>C : C
method(@dec this: C) {}
>method : (: any, this: C) => void
>method : (this: C) => void
>dec : (target: Object, propertyKey: string | symbol, parameterIndex: number) => void
> : any
>this : C
}
class C2 {
>C2 : C2
method(@dec allowed: C2, @dec this: C2) {}
>method : (allowed: C2, this: C2) => void
>dec : (target: Object, propertyKey: string | symbol, parameterIndex: number) => void
>allowed : C2
>dec : (target: Object, propertyKey: string | symbol, parameterIndex: number) => void
>this : C2
}
@@ -0,0 +1,15 @@
tests/cases/conformance/decorators/invalid/decoratorOnFunctionParameter.ts(5,17): error TS1433: Decorators may not be applied to 'this' parameters.
tests/cases/conformance/decorators/invalid/decoratorOnFunctionParameter.ts(6,17): error TS1433: Decorators may not be applied to 'this' parameters.
==== tests/cases/conformance/decorators/invalid/decoratorOnFunctionParameter.ts (2 errors) ====
declare const dec: any;
class C { n = true; }
function direct(@dec this: C) { return this.n; }
~~~~
!!! error TS1433: Decorators may not be applied to 'this' parameters.
function called(@dec() this: C) { return this.n; }
~~~~~~
!!! error TS1433: Decorators may not be applied to 'this' parameters.
@@ -0,0 +1,17 @@
//// [decoratorOnFunctionParameter.ts]
declare const dec: any;
class C { n = true; }
function direct(@dec this: C) { return this.n; }
function called(@dec() this: C) { return this.n; }
//// [decoratorOnFunctionParameter.js]
var C = /** @class */ (function () {
function C() {
this.n = true;
}
return C;
}());
function direct() { return this.n; }
function called() { return this.n; }
@@ -0,0 +1,26 @@
=== tests/cases/conformance/decorators/invalid/decoratorOnFunctionParameter.ts ===
declare const dec: any;
>dec : Symbol(dec, Decl(decoratorOnFunctionParameter.ts, 0, 13))
class C { n = true; }
>C : Symbol(C, Decl(decoratorOnFunctionParameter.ts, 0, 23))
>n : Symbol(C.n, Decl(decoratorOnFunctionParameter.ts, 2, 9))
function direct(@dec this: C) { return this.n; }
>direct : Symbol(direct, Decl(decoratorOnFunctionParameter.ts, 2, 21))
>dec : Symbol(dec, Decl(decoratorOnFunctionParameter.ts, 0, 13))
>this : Symbol(this, Decl(decoratorOnFunctionParameter.ts, 4, 16))
>C : Symbol(C, Decl(decoratorOnFunctionParameter.ts, 0, 23))
>this.n : Symbol(C.n, Decl(decoratorOnFunctionParameter.ts, 2, 9))
>this : Symbol(this, Decl(decoratorOnFunctionParameter.ts, 4, 16))
>n : Symbol(C.n, Decl(decoratorOnFunctionParameter.ts, 2, 9))
function called(@dec() this: C) { return this.n; }
>called : Symbol(called, Decl(decoratorOnFunctionParameter.ts, 4, 48))
>dec : Symbol(dec, Decl(decoratorOnFunctionParameter.ts, 0, 13))
>this : Symbol(this, Decl(decoratorOnFunctionParameter.ts, 5, 16))
>C : Symbol(C, Decl(decoratorOnFunctionParameter.ts, 0, 23))
>this.n : Symbol(C.n, Decl(decoratorOnFunctionParameter.ts, 2, 9))
>this : Symbol(this, Decl(decoratorOnFunctionParameter.ts, 5, 16))
>n : Symbol(C.n, Decl(decoratorOnFunctionParameter.ts, 2, 9))
@@ -0,0 +1,26 @@
=== tests/cases/conformance/decorators/invalid/decoratorOnFunctionParameter.ts ===
declare const dec: any;
>dec : any
class C { n = true; }
>C : C
>n : boolean
>true : true
function direct(@dec this: C) { return this.n; }
>direct : (this: C) => boolean
>dec : any
>this : C
>this.n : boolean
>this : C
>n : boolean
function called(@dec() this: C) { return this.n; }
>called : (this: C) => boolean
>dec() : any
>dec : any
>this : C
>this.n : boolean
>this : C
>n : boolean
@@ -79,8 +79,7 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,26): e
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(169,23): error TS1359: Identifier expected. 'this' is a reserved word that cannot be used here.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(169,23): error TS2680: A 'this' parameter must be the first parameter.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,23): error TS1005: ',' expected.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,28): error TS1359: Identifier expected. 'this' is a reserved word that cannot be used here.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,28): error TS2680: A 'this' parameter must be the first parameter.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,20): error TS1433: Decorators may not be applied to 'this' parameters.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,30): error TS1005: ',' expected.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,32): error TS1359: Identifier expected. 'new' is a reserved word that cannot be used here.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,37): error TS1005: ',' expected.
@@ -95,7 +94,7 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(177,19): e
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(178,22): error TS2730: An arrow function cannot have a 'this' parameter.
==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (65 errors) ====
==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (64 errors) ====
class C {
n: number;
explicitThis(this: this, m: number): number {
@@ -407,10 +406,8 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(178,22): e
~
!!! error TS1005: ',' expected.
function decorated(@deco() this: C): number { return this.n; }
~~~~
!!! error TS1359: Identifier expected. 'this' is a reserved word that cannot be used here.
~~~~~~~
!!! error TS2680: A 'this' parameter must be the first parameter.
~~~~~~~
!!! error TS1433: Decorators may not be applied to 'this' parameters.
function initializer(this: C = new C()): number { return this.n; }
~
!!! error TS1005: ',' expected.
@@ -646,9 +646,11 @@ function optional(this?: C): number { return this.n; }
function decorated(@deco() this: C): number { return this.n; }
>decorated : Symbol(decorated, Decl(thisTypeInFunctionsNegative.ts, 169, 54))
> : Symbol((Missing), Decl(thisTypeInFunctionsNegative.ts, 170, 19))
>this : Symbol(this, Decl(thisTypeInFunctionsNegative.ts, 170, 26))
>this : Symbol(this, Decl(thisTypeInFunctionsNegative.ts, 170, 19))
>C : Symbol(C, Decl(thisTypeInFunctionsNegative.ts, 0, 0))
>this.n : Symbol(C.n, Decl(thisTypeInFunctionsNegative.ts, 0, 9))
>this : Symbol(this, Decl(thisTypeInFunctionsNegative.ts, 170, 19))
>n : Symbol(C.n, Decl(thisTypeInFunctionsNegative.ts, 0, 9))
function initializer(this: C = new C()): number { return this.n; }
>initializer : Symbol(initializer, Decl(thisTypeInFunctionsNegative.ts, 170, 62))
@@ -733,14 +733,13 @@ function optional(this?: C): number { return this.n; }
>n : any
function decorated(@deco() this: C): number { return this.n; }
>decorated : (: any, this: C) => number
>decorated : (this: C) => number
>deco() : any
>deco : any
> : any
>this : C
>this.n : any
>this : any
>n : any
>this.n : number
>this : C
>n : number
function initializer(this: C = new C()): number { return this.n; }
>initializer : (this: C, : any, C: any) => any
@@ -4,4 +4,8 @@ declare function dec(target: Object, propertyKey: string | symbol, parameterInde
class C {
method(@dec this: C) {}
}
class C2 {
method(@dec allowed: C2, @dec this: C2) {}
}
@@ -0,0 +1,6 @@
declare const dec: any;
class C { n = true; }
function direct(@dec this: C) { return this.n; }
function called(@dec() this: C) { return this.n; }