From 4cd859aa8532f530e034eb0f219b3d781b7744ed Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Mon, 7 Jan 2019 22:09:27 +0100 Subject: [PATCH] Allow referencing 'this' in parameters of functions in the constructor Fixes: #29286 --- src/compiler/checker.ts | 2 +- .../reference/superAccess2.errors.txt | 5 +--- .../baselines/reference/superAccess2.symbols | 1 + tests/baselines/reference/superAccess2.types | 2 +- .../thisInConstructorParameter2.errors.txt | 4 ++- .../reference/thisInConstructorParameter2.js | 15 +++++++++-- .../thisInConstructorParameter2.symbols | 25 +++++++++++++------ .../thisInConstructorParameter2.types | 16 +++++++++++- .../compiler/thisInConstructorParameter2.ts | 4 ++- 9 files changed, 56 insertions(+), 18 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index de44e8bb37c..a5147715bb1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16831,7 +16831,7 @@ namespace ts { } function isInConstructorArgumentInitializer(node: Node, constructorDecl: Node): boolean { - return !!findAncestor(node, n => n === constructorDecl ? "quit" : n.kind === SyntaxKind.Parameter); + return !!findAncestor(node, n => isFunctionLikeDeclaration(n) ? "quit" : n.kind === SyntaxKind.Parameter && n.parent === constructorDecl); } function checkSuperExpression(node: Node): Type { diff --git a/tests/baselines/reference/superAccess2.errors.txt b/tests/baselines/reference/superAccess2.errors.txt index 3ba682b3145..65d4c10794d 100644 --- a/tests/baselines/reference/superAccess2.errors.txt +++ b/tests/baselines/reference/superAccess2.errors.txt @@ -7,7 +7,6 @@ tests/cases/compiler/superAccess2.ts(11,33): error TS1034: 'super' must be follo tests/cases/compiler/superAccess2.ts(11,40): error TS2336: 'super' cannot be referenced in constructor arguments. tests/cases/compiler/superAccess2.ts(11,40): error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class. tests/cases/compiler/superAccess2.ts(11,45): error TS1034: 'super' must be followed by an argument list or member access. -tests/cases/compiler/superAccess2.ts(11,59): error TS2336: 'super' cannot be referenced in constructor arguments. tests/cases/compiler/superAccess2.ts(11,59): error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class. tests/cases/compiler/superAccess2.ts(11,64): error TS1034: 'super' must be followed by an argument list or member access. tests/cases/compiler/superAccess2.ts(15,19): error TS1034: 'super' must be followed by an argument list or member access. @@ -16,7 +15,7 @@ tests/cases/compiler/superAccess2.ts(20,26): error TS1034: 'super' must be follo tests/cases/compiler/superAccess2.ts(21,15): error TS2339: Property 'x' does not exist on type 'typeof P'. -==== tests/cases/compiler/superAccess2.ts (16 errors) ==== +==== tests/cases/compiler/superAccess2.ts (15 errors) ==== class P { x() { } static y() { } @@ -47,8 +46,6 @@ tests/cases/compiler/superAccess2.ts(21,15): error TS2339: Property 'x' does not ~ !!! error TS1034: 'super' must be followed by an argument list or member access. ~~~~~ -!!! error TS2336: 'super' cannot be referenced in constructor arguments. - ~~~~~ !!! error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class. ~ !!! error TS1034: 'super' must be followed by an argument list or member access. diff --git a/tests/baselines/reference/superAccess2.symbols b/tests/baselines/reference/superAccess2.symbols index 7a9fcb236d6..abb3385b970 100644 --- a/tests/baselines/reference/superAccess2.symbols +++ b/tests/baselines/reference/superAccess2.symbols @@ -25,6 +25,7 @@ class Q extends P { >z : Symbol(Q.z, Decl(superAccess2.ts, 10, 16)) >zz : Symbol(zz, Decl(superAccess2.ts, 10, 33)) >zzz : Symbol(zzz, Decl(superAccess2.ts, 10, 45)) +>super : Symbol(P, Decl(superAccess2.ts, 0, 0)) super(); >super : Symbol(P, Decl(superAccess2.ts, 0, 0)) diff --git a/tests/baselines/reference/superAccess2.types b/tests/baselines/reference/superAccess2.types index 06fcd380480..00ae91bf4c3 100644 --- a/tests/baselines/reference/superAccess2.types +++ b/tests/baselines/reference/superAccess2.types @@ -38,7 +38,7 @@ class Q extends P { >zzz : () => any >() => super : () => any >super : any ->super : any +>super : P > : any super(); diff --git a/tests/baselines/reference/thisInConstructorParameter2.errors.txt b/tests/baselines/reference/thisInConstructorParameter2.errors.txt index 35818b8f379..2b6ed8017c2 100644 --- a/tests/baselines/reference/thisInConstructorParameter2.errors.txt +++ b/tests/baselines/reference/thisInConstructorParameter2.errors.txt @@ -10,11 +10,13 @@ tests/cases/compiler/thisInConstructorParameter2.ts(5,39): error TS2333: 'this' ~~~~ !!! error TS2334: 'this' cannot be referenced in a static property initializer. - constructor(public z = this, zz = this) { } + constructor(public z = this, zz = this, zzz = (p = this) => this) { ~~~~ !!! error TS2333: 'this' cannot be referenced in constructor arguments. ~~~~ !!! error TS2333: 'this' cannot be referenced in constructor arguments. + zzz = (p = this) => this; + } foo(zz = this) { zz.x; } static bar(zz = this) { zz.y; } diff --git a/tests/baselines/reference/thisInConstructorParameter2.js b/tests/baselines/reference/thisInConstructorParameter2.js index a5e4f4d8b57..fc1525f03cf 100644 --- a/tests/baselines/reference/thisInConstructorParameter2.js +++ b/tests/baselines/reference/thisInConstructorParameter2.js @@ -3,7 +3,9 @@ class P { x = this; static y = this; - constructor(public z = this, zz = this) { } + constructor(public z = this, zz = this, zzz = (p = this) => this) { + zzz = (p = this) => this; + } foo(zz = this) { zz.x; } static bar(zz = this) { zz.y; } @@ -12,11 +14,20 @@ class P { //// [thisInConstructorParameter2.js] var _this = this; var P = /** @class */ (function () { - function P(z, zz) { + function P(z, zz, zzz) { if (z === void 0) { z = this; } if (zz === void 0) { zz = this; } + if (zzz === void 0) { zzz = function (p) { + if (p === void 0) { p = _this; } + return _this; + }; } + var _this = this; this.z = z; this.x = this; + zzz = function (p) { + if (p === void 0) { p = _this; } + return _this; + }; } P.prototype.foo = function (zz) { if (zz === void 0) { zz = this; } diff --git a/tests/baselines/reference/thisInConstructorParameter2.symbols b/tests/baselines/reference/thisInConstructorParameter2.symbols index 8991e64f66a..96bdfb159be 100644 --- a/tests/baselines/reference/thisInConstructorParameter2.symbols +++ b/tests/baselines/reference/thisInConstructorParameter2.symbols @@ -10,25 +10,36 @@ class P { >y : Symbol(P.y, Decl(thisInConstructorParameter2.ts, 1, 13)) >this : Symbol(P, Decl(thisInConstructorParameter2.ts, 0, 0)) - constructor(public z = this, zz = this) { } + constructor(public z = this, zz = this, zzz = (p = this) => this) { >z : Symbol(P.z, Decl(thisInConstructorParameter2.ts, 4, 16)) >this : Symbol(P, Decl(thisInConstructorParameter2.ts, 0, 0)) >zz : Symbol(zz, Decl(thisInConstructorParameter2.ts, 4, 32)) >this : Symbol(P, Decl(thisInConstructorParameter2.ts, 0, 0)) +>zzz : Symbol(zzz, Decl(thisInConstructorParameter2.ts, 4, 43)) +>p : Symbol(p, Decl(thisInConstructorParameter2.ts, 4, 51)) +>this : Symbol(P, Decl(thisInConstructorParameter2.ts, 0, 0)) +>this : Symbol(P, Decl(thisInConstructorParameter2.ts, 0, 0)) + + zzz = (p = this) => this; +>zzz : Symbol(zzz, Decl(thisInConstructorParameter2.ts, 4, 43)) +>p : Symbol(p, Decl(thisInConstructorParameter2.ts, 5, 15)) +>this : Symbol(P, Decl(thisInConstructorParameter2.ts, 0, 0)) +>this : Symbol(P, Decl(thisInConstructorParameter2.ts, 0, 0)) + } foo(zz = this) { zz.x; } ->foo : Symbol(P.foo, Decl(thisInConstructorParameter2.ts, 4, 47)) ->zz : Symbol(zz, Decl(thisInConstructorParameter2.ts, 6, 8)) +>foo : Symbol(P.foo, Decl(thisInConstructorParameter2.ts, 6, 5)) +>zz : Symbol(zz, Decl(thisInConstructorParameter2.ts, 8, 8)) >this : Symbol(P, Decl(thisInConstructorParameter2.ts, 0, 0)) >zz.x : Symbol(P.x, Decl(thisInConstructorParameter2.ts, 0, 9)) ->zz : Symbol(zz, Decl(thisInConstructorParameter2.ts, 6, 8)) +>zz : Symbol(zz, Decl(thisInConstructorParameter2.ts, 8, 8)) >x : Symbol(P.x, Decl(thisInConstructorParameter2.ts, 0, 9)) static bar(zz = this) { zz.y; } ->bar : Symbol(P.bar, Decl(thisInConstructorParameter2.ts, 6, 28)) ->zz : Symbol(zz, Decl(thisInConstructorParameter2.ts, 7, 15)) +>bar : Symbol(P.bar, Decl(thisInConstructorParameter2.ts, 8, 28)) +>zz : Symbol(zz, Decl(thisInConstructorParameter2.ts, 9, 15)) >this : Symbol(P, Decl(thisInConstructorParameter2.ts, 0, 0)) >zz.y : Symbol(P.y, Decl(thisInConstructorParameter2.ts, 1, 13)) ->zz : Symbol(zz, Decl(thisInConstructorParameter2.ts, 7, 15)) +>zz : Symbol(zz, Decl(thisInConstructorParameter2.ts, 9, 15)) >y : Symbol(P.y, Decl(thisInConstructorParameter2.ts, 1, 13)) } diff --git a/tests/baselines/reference/thisInConstructorParameter2.types b/tests/baselines/reference/thisInConstructorParameter2.types index 73c5f4d7362..69198bafa5f 100644 --- a/tests/baselines/reference/thisInConstructorParameter2.types +++ b/tests/baselines/reference/thisInConstructorParameter2.types @@ -10,11 +10,25 @@ class P { >y : typeof P >this : typeof P - constructor(public z = this, zz = this) { } + constructor(public z = this, zz = this, zzz = (p = this) => this) { >z : this >this : this >zz : this >this : this +>zzz : (p?: this) => this +>(p = this) => this : (p?: this) => this +>p : this +>this : this +>this : this + + zzz = (p = this) => this; +>zzz = (p = this) => this : (p?: this) => this +>zzz : (p?: this) => this +>(p = this) => this : (p?: this) => this +>p : this +>this : this +>this : this + } foo(zz = this) { zz.x; } >foo : (zz?: this) => void diff --git a/tests/cases/compiler/thisInConstructorParameter2.ts b/tests/cases/compiler/thisInConstructorParameter2.ts index 2b09d2bb7e7..18d35bea341 100644 --- a/tests/cases/compiler/thisInConstructorParameter2.ts +++ b/tests/cases/compiler/thisInConstructorParameter2.ts @@ -2,7 +2,9 @@ class P { x = this; static y = this; - constructor(public z = this, zz = this) { } + constructor(public z = this, zz = this, zzz = (p = this) => this) { + zzz = (p = this) => this; + } foo(zz = this) { zz.x; } static bar(zz = this) { zz.y; }