From a5cf7c12bc57e1262592e730b5aae68318ea90b8 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 2 Feb 2016 16:31:32 -0800 Subject: [PATCH 01/10] add conformance tests --- .../classes/superCallBeforeThisAccessing1.ts | 13 +++++++++++++ .../classes/superCallBeforeThisAccessing2.ts | 9 +++++++++ .../classes/superCallBeforeThisAccessing3.ts | 12 ++++++++++++ .../classes/superCallBeforeThisAccessing4.ts | 15 +++++++++++++++ .../classes/superCallBeforeThisAccessing5.ts | 6 ++++++ .../classes/superCallBeforeThisAccessing6.ts | 9 +++++++++ .../classes/superCallBeforeThisAccessing7.ts | 12 ++++++++++++ .../classes/superCallBeforeThisAccessing8.ts | 12 ++++++++++++ 8 files changed, 88 insertions(+) create mode 100644 tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts create mode 100644 tests/cases/conformance/classes/superCallBeforeThisAccessing2.ts create mode 100644 tests/cases/conformance/classes/superCallBeforeThisAccessing3.ts create mode 100644 tests/cases/conformance/classes/superCallBeforeThisAccessing4.ts create mode 100644 tests/cases/conformance/classes/superCallBeforeThisAccessing5.ts create mode 100644 tests/cases/conformance/classes/superCallBeforeThisAccessing6.ts create mode 100644 tests/cases/conformance/classes/superCallBeforeThisAccessing7.ts create mode 100644 tests/cases/conformance/classes/superCallBeforeThisAccessing8.ts diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts b/tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts new file mode 100644 index 00000000000..13b8fb8ed4d --- /dev/null +++ b/tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts @@ -0,0 +1,13 @@ +class Base { + constructor(c) { } +} +class D extends Base { + private _t; + constructor() { + super(i); + var s = { + t: this._t + } + var i = Factory.create(s); + } +} diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing2.ts b/tests/cases/conformance/classes/superCallBeforeThisAccessing2.ts new file mode 100644 index 00000000000..1b0a0d541e9 --- /dev/null +++ b/tests/cases/conformance/classes/superCallBeforeThisAccessing2.ts @@ -0,0 +1,9 @@ +class Base { + constructor(c) { } +} +class D extends Base { + private _t; + constructor() { + super(() => { this._t }); // no error. only check when this is directly accessing in constructor + } +} diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing3.ts b/tests/cases/conformance/classes/superCallBeforeThisAccessing3.ts new file mode 100644 index 00000000000..1386998aaae --- /dev/null +++ b/tests/cases/conformance/classes/superCallBeforeThisAccessing3.ts @@ -0,0 +1,12 @@ +class Base { + constructor(c) { } +} +class D extends Base { + private _t; + constructor() { + let x = () => { this._t }; + x(); // no error; we only check super is called before this when the container is a constructor + this._t; // error + super(undefined); + } +} diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing4.ts b/tests/cases/conformance/classes/superCallBeforeThisAccessing4.ts new file mode 100644 index 00000000000..9135e03b0ce --- /dev/null +++ b/tests/cases/conformance/classes/superCallBeforeThisAccessing4.ts @@ -0,0 +1,15 @@ +class D extends null { + private _t; + constructor() { + this._t; + super(); + } +} + +class E extends null { + private _t; + constructor() { + super(); + this._t; + } +} \ No newline at end of file diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing5.ts b/tests/cases/conformance/classes/superCallBeforeThisAccessing5.ts new file mode 100644 index 00000000000..17820277585 --- /dev/null +++ b/tests/cases/conformance/classes/superCallBeforeThisAccessing5.ts @@ -0,0 +1,6 @@ +class D extends null { + private _t; + constructor() { + this._t; // No error + } +} diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing6.ts b/tests/cases/conformance/classes/superCallBeforeThisAccessing6.ts new file mode 100644 index 00000000000..8f36f2eb056 --- /dev/null +++ b/tests/cases/conformance/classes/superCallBeforeThisAccessing6.ts @@ -0,0 +1,9 @@ +class Base { + constructor(c) { } +} +class D extends Base { + private _t; + constructor() { + super(this); + } +} diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing7.ts b/tests/cases/conformance/classes/superCallBeforeThisAccessing7.ts new file mode 100644 index 00000000000..d40c96a60f3 --- /dev/null +++ b/tests/cases/conformance/classes/superCallBeforeThisAccessing7.ts @@ -0,0 +1,12 @@ +class Base { + constructor(c) { } +} +class D extends Base { + private _t; + constructor() { + let x = { + j: this._t, + } + super(undefined); + } +} diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing8.ts b/tests/cases/conformance/classes/superCallBeforeThisAccessing8.ts new file mode 100644 index 00000000000..5742cdab845 --- /dev/null +++ b/tests/cases/conformance/classes/superCallBeforeThisAccessing8.ts @@ -0,0 +1,12 @@ +class Base { + constructor(c) { } +} +class D extends Base { + private _t; + constructor() { + let x = { + k: super(undefined), + j: this._t, // no error + } + } +} From 76b6bff3d7a2d13cbda05cca1b6372323db7ead4 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 2 Feb 2016 16:32:10 -0800 Subject: [PATCH 02/10] Update baselines add baselines Update baseline --- .../superCallBeforeThisAccessing1.errors.txt | 20 ++++++++++ .../superCallBeforeThisAccessing1.js | 38 ++++++++++++++++++ .../superCallBeforeThisAccessing2.js | 31 +++++++++++++++ .../superCallBeforeThisAccessing2.symbols | 23 +++++++++++ .../superCallBeforeThisAccessing2.types | 25 ++++++++++++ .../superCallBeforeThisAccessing3.errors.txt | 19 +++++++++ .../superCallBeforeThisAccessing3.js | 37 ++++++++++++++++++ .../superCallBeforeThisAccessing4.errors.txt | 30 ++++++++++++++ .../superCallBeforeThisAccessing4.js | 39 +++++++++++++++++++ .../superCallBeforeThisAccessing5.js | 22 +++++++++++ .../superCallBeforeThisAccessing5.symbols | 15 +++++++ .../superCallBeforeThisAccessing5.types | 16 ++++++++ .../superCallBeforeThisAccessing6.errors.txt | 16 ++++++++ .../superCallBeforeThisAccessing6.js | 30 ++++++++++++++ .../superCallBeforeThisAccessing7.errors.txt | 19 +++++++++ .../superCallBeforeThisAccessing7.js | 36 +++++++++++++++++ .../superCallBeforeThisAccessing8.js | 36 +++++++++++++++++ .../superCallBeforeThisAccessing8.symbols | 32 +++++++++++++++ .../superCallBeforeThisAccessing8.types | 34 ++++++++++++++++ 19 files changed, 518 insertions(+) create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing1.errors.txt create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing1.js create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing2.js create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing2.symbols create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing2.types create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing3.errors.txt create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing3.js create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing4.errors.txt create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing4.js create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing5.js create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing5.symbols create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing5.types create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing6.errors.txt create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing6.js create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing7.errors.txt create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing7.js create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing8.js create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing8.symbols create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing8.types diff --git a/tests/baselines/reference/superCallBeforeThisAccessing1.errors.txt b/tests/baselines/reference/superCallBeforeThisAccessing1.errors.txt new file mode 100644 index 00000000000..40bbe62f714 --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing1.errors.txt @@ -0,0 +1,20 @@ +tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts(11,17): error TS2304: Cannot find name 'Factory'. + + +==== tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts (1 errors) ==== + class Base { + constructor(c) { } + } + class D extends Base { + private _t; + constructor() { + super(i); + var s = { + t: this._t + } + var i = Factory.create(s); + ~~~~~~~ +!!! error TS2304: Cannot find name 'Factory'. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/superCallBeforeThisAccessing1.js b/tests/baselines/reference/superCallBeforeThisAccessing1.js new file mode 100644 index 00000000000..f7187fa6618 --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing1.js @@ -0,0 +1,38 @@ +//// [superCallBeforeThisAccessing1.ts] +class Base { + constructor(c) { } +} +class D extends Base { + private _t; + constructor() { + super(i); + var s = { + t: this._t + } + var i = Factory.create(s); + } +} + + +//// [superCallBeforeThisAccessing1.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var Base = (function () { + function Base(c) { + } + return Base; +}()); +var D = (function (_super) { + __extends(D, _super); + function D() { + _super.call(this, i); + var s = { + t: this._t + }; + var i = Factory.create(s); + } + return D; +}(Base)); diff --git a/tests/baselines/reference/superCallBeforeThisAccessing2.js b/tests/baselines/reference/superCallBeforeThisAccessing2.js new file mode 100644 index 00000000000..e5acf06bbfd --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing2.js @@ -0,0 +1,31 @@ +//// [superCallBeforeThisAccessing2.ts] +class Base { + constructor(c) { } +} +class D extends Base { + private _t; + constructor() { + super(() => { this._t }); // no error. only check when this is directly accessing in constructor + } +} + + +//// [superCallBeforeThisAccessing2.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var Base = (function () { + function Base(c) { + } + return Base; +}()); +var D = (function (_super) { + __extends(D, _super); + function D() { + var _this = this; + _super.call(this, function () { _this._t; }); // no error. only check when this is directly accessing in constructor + } + return D; +}(Base)); diff --git a/tests/baselines/reference/superCallBeforeThisAccessing2.symbols b/tests/baselines/reference/superCallBeforeThisAccessing2.symbols new file mode 100644 index 00000000000..9e0e11dd2ac --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing2.symbols @@ -0,0 +1,23 @@ +=== tests/cases/conformance/classes/superCallBeforeThisAccessing2.ts === +class Base { +>Base : Symbol(Base, Decl(superCallBeforeThisAccessing2.ts, 0, 0)) + + constructor(c) { } +>c : Symbol(c, Decl(superCallBeforeThisAccessing2.ts, 1, 16)) +} +class D extends Base { +>D : Symbol(D, Decl(superCallBeforeThisAccessing2.ts, 2, 1)) +>Base : Symbol(Base, Decl(superCallBeforeThisAccessing2.ts, 0, 0)) + + private _t; +>_t : Symbol(_t, Decl(superCallBeforeThisAccessing2.ts, 3, 22)) + + constructor() { + super(() => { this._t }); // no error. only check when this is directly accessing in constructor +>super : Symbol(Base, Decl(superCallBeforeThisAccessing2.ts, 0, 0)) +>this._t : Symbol(_t, Decl(superCallBeforeThisAccessing2.ts, 3, 22)) +>this : Symbol(D, Decl(superCallBeforeThisAccessing2.ts, 2, 1)) +>_t : Symbol(_t, Decl(superCallBeforeThisAccessing2.ts, 3, 22)) + } +} + diff --git a/tests/baselines/reference/superCallBeforeThisAccessing2.types b/tests/baselines/reference/superCallBeforeThisAccessing2.types new file mode 100644 index 00000000000..e6307a977da --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing2.types @@ -0,0 +1,25 @@ +=== tests/cases/conformance/classes/superCallBeforeThisAccessing2.ts === +class Base { +>Base : Base + + constructor(c) { } +>c : any +} +class D extends Base { +>D : D +>Base : Base + + private _t; +>_t : any + + constructor() { + super(() => { this._t }); // no error. only check when this is directly accessing in constructor +>super(() => { this._t }) : void +>super : typeof Base +>() => { this._t } : () => void +>this._t : any +>this : this +>_t : any + } +} + diff --git a/tests/baselines/reference/superCallBeforeThisAccessing3.errors.txt b/tests/baselines/reference/superCallBeforeThisAccessing3.errors.txt new file mode 100644 index 00000000000..526c43d735c --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing3.errors.txt @@ -0,0 +1,19 @@ +tests/cases/conformance/classes/superCallBeforeThisAccessing3.ts(9,9): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. + + +==== tests/cases/conformance/classes/superCallBeforeThisAccessing3.ts (1 errors) ==== + class Base { + constructor(c) { } + } + class D extends Base { + private _t; + constructor() { + let x = () => { this._t }; + x(); // no error; we only check super is called before this when the container is a constructor + this._t; // error + ~~~~ +!!! error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. + super(undefined); + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/superCallBeforeThisAccessing3.js b/tests/baselines/reference/superCallBeforeThisAccessing3.js new file mode 100644 index 00000000000..101d74e4bc7 --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing3.js @@ -0,0 +1,37 @@ +//// [superCallBeforeThisAccessing3.ts] +class Base { + constructor(c) { } +} +class D extends Base { + private _t; + constructor() { + let x = () => { this._t }; + x(); // no error; we only check super is called before this when the container is a constructor + this._t; // error + super(undefined); + } +} + + +//// [superCallBeforeThisAccessing3.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var Base = (function () { + function Base(c) { + } + return Base; +}()); +var D = (function (_super) { + __extends(D, _super); + function D() { + var _this = this; + var x = function () { _this._t; }; + x(); // no error; we only check super is called before this when the container is a constructor + this._t; // error + _super.call(this, undefined); + } + return D; +}(Base)); diff --git a/tests/baselines/reference/superCallBeforeThisAccessing4.errors.txt b/tests/baselines/reference/superCallBeforeThisAccessing4.errors.txt new file mode 100644 index 00000000000..d3211eca14f --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing4.errors.txt @@ -0,0 +1,30 @@ +tests/cases/conformance/classes/superCallBeforeThisAccessing4.ts(3,5): error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' +tests/cases/conformance/classes/superCallBeforeThisAccessing4.ts(11,5): error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' + + +==== tests/cases/conformance/classes/superCallBeforeThisAccessing4.ts (2 errors) ==== + class D extends null { + private _t; + constructor() { + ~~~~~~~~~~~~~~~ + this._t; + ~~~~~~~~~~~~~~~~ + super(); + ~~~~~~~~~~~~~~~~ + } + ~~~~~ +!!! error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' + } + + class E extends null { + private _t; + constructor() { + ~~~~~~~~~~~~~~~ + super(); + ~~~~~~~~~~~~~~~~ + this._t; + ~~~~~~~~~~~~~~~~ + } + ~~~~~ +!!! error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' + } \ No newline at end of file diff --git a/tests/baselines/reference/superCallBeforeThisAccessing4.js b/tests/baselines/reference/superCallBeforeThisAccessing4.js new file mode 100644 index 00000000000..9c3c5ab60c4 --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing4.js @@ -0,0 +1,39 @@ +//// [superCallBeforeThisAccessing4.ts] +class D extends null { + private _t; + constructor() { + this._t; + super(); + } +} + +class E extends null { + private _t; + constructor() { + super(); + this._t; + } +} + +//// [superCallBeforeThisAccessing4.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var D = (function (_super) { + __extends(D, _super); + function D() { + this._t; + _super.call(this); + } + return D; +}(null)); +var E = (function (_super) { + __extends(E, _super); + function E() { + _super.call(this); + this._t; + } + return E; +}(null)); diff --git a/tests/baselines/reference/superCallBeforeThisAccessing5.js b/tests/baselines/reference/superCallBeforeThisAccessing5.js new file mode 100644 index 00000000000..3281a3f8b55 --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing5.js @@ -0,0 +1,22 @@ +//// [superCallBeforeThisAccessing5.ts] +class D extends null { + private _t; + constructor() { + this._t; // No error + } +} + + +//// [superCallBeforeThisAccessing5.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var D = (function (_super) { + __extends(D, _super); + function D() { + this._t; // No error + } + return D; +}(null)); diff --git a/tests/baselines/reference/superCallBeforeThisAccessing5.symbols b/tests/baselines/reference/superCallBeforeThisAccessing5.symbols new file mode 100644 index 00000000000..002d6e1ff77 --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing5.symbols @@ -0,0 +1,15 @@ +=== tests/cases/conformance/classes/superCallBeforeThisAccessing5.ts === +class D extends null { +>D : Symbol(D, Decl(superCallBeforeThisAccessing5.ts, 0, 0)) + + private _t; +>_t : Symbol(_t, Decl(superCallBeforeThisAccessing5.ts, 0, 22)) + + constructor() { + this._t; // No error +>this._t : Symbol(_t, Decl(superCallBeforeThisAccessing5.ts, 0, 22)) +>this : Symbol(D, Decl(superCallBeforeThisAccessing5.ts, 0, 0)) +>_t : Symbol(_t, Decl(superCallBeforeThisAccessing5.ts, 0, 22)) + } +} + diff --git a/tests/baselines/reference/superCallBeforeThisAccessing5.types b/tests/baselines/reference/superCallBeforeThisAccessing5.types new file mode 100644 index 00000000000..543e453ffe3 --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing5.types @@ -0,0 +1,16 @@ +=== tests/cases/conformance/classes/superCallBeforeThisAccessing5.ts === +class D extends null { +>D : D +>null : null + + private _t; +>_t : any + + constructor() { + this._t; // No error +>this._t : any +>this : this +>_t : any + } +} + diff --git a/tests/baselines/reference/superCallBeforeThisAccessing6.errors.txt b/tests/baselines/reference/superCallBeforeThisAccessing6.errors.txt new file mode 100644 index 00000000000..534b3605fc9 --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing6.errors.txt @@ -0,0 +1,16 @@ +tests/cases/conformance/classes/superCallBeforeThisAccessing6.ts(7,15): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. + + +==== tests/cases/conformance/classes/superCallBeforeThisAccessing6.ts (1 errors) ==== + class Base { + constructor(c) { } + } + class D extends Base { + private _t; + constructor() { + super(this); + ~~~~ +!!! error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/superCallBeforeThisAccessing6.js b/tests/baselines/reference/superCallBeforeThisAccessing6.js new file mode 100644 index 00000000000..746ce9f2791 --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing6.js @@ -0,0 +1,30 @@ +//// [superCallBeforeThisAccessing6.ts] +class Base { + constructor(c) { } +} +class D extends Base { + private _t; + constructor() { + super(this); + } +} + + +//// [superCallBeforeThisAccessing6.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var Base = (function () { + function Base(c) { + } + return Base; +}()); +var D = (function (_super) { + __extends(D, _super); + function D() { + _super.call(this, this); + } + return D; +}(Base)); diff --git a/tests/baselines/reference/superCallBeforeThisAccessing7.errors.txt b/tests/baselines/reference/superCallBeforeThisAccessing7.errors.txt new file mode 100644 index 00000000000..73997db3b25 --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing7.errors.txt @@ -0,0 +1,19 @@ +tests/cases/conformance/classes/superCallBeforeThisAccessing7.ts(8,16): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. + + +==== tests/cases/conformance/classes/superCallBeforeThisAccessing7.ts (1 errors) ==== + class Base { + constructor(c) { } + } + class D extends Base { + private _t; + constructor() { + let x = { + j: this._t, + ~~~~ +!!! error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. + } + super(undefined); + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/superCallBeforeThisAccessing7.js b/tests/baselines/reference/superCallBeforeThisAccessing7.js new file mode 100644 index 00000000000..c3aa1655cf7 --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing7.js @@ -0,0 +1,36 @@ +//// [superCallBeforeThisAccessing7.ts] +class Base { + constructor(c) { } +} +class D extends Base { + private _t; + constructor() { + let x = { + j: this._t, + } + super(undefined); + } +} + + +//// [superCallBeforeThisAccessing7.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var Base = (function () { + function Base(c) { + } + return Base; +}()); +var D = (function (_super) { + __extends(D, _super); + function D() { + var x = { + j: this._t + }; + _super.call(this, undefined); + } + return D; +}(Base)); diff --git a/tests/baselines/reference/superCallBeforeThisAccessing8.js b/tests/baselines/reference/superCallBeforeThisAccessing8.js new file mode 100644 index 00000000000..0865c4305a5 --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing8.js @@ -0,0 +1,36 @@ +//// [superCallBeforeThisAccessing8.ts] +class Base { + constructor(c) { } +} +class D extends Base { + private _t; + constructor() { + let x = { + k: super(undefined), + j: this._t, // no error + } + } +} + + +//// [superCallBeforeThisAccessing8.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var Base = (function () { + function Base(c) { + } + return Base; +}()); +var D = (function (_super) { + __extends(D, _super); + function D() { + var x = { + k: _super.call(this, undefined), + j: this._t + }; + } + return D; +}(Base)); diff --git a/tests/baselines/reference/superCallBeforeThisAccessing8.symbols b/tests/baselines/reference/superCallBeforeThisAccessing8.symbols new file mode 100644 index 00000000000..e29284be43b --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing8.symbols @@ -0,0 +1,32 @@ +=== tests/cases/conformance/classes/superCallBeforeThisAccessing8.ts === +class Base { +>Base : Symbol(Base, Decl(superCallBeforeThisAccessing8.ts, 0, 0)) + + constructor(c) { } +>c : Symbol(c, Decl(superCallBeforeThisAccessing8.ts, 1, 16)) +} +class D extends Base { +>D : Symbol(D, Decl(superCallBeforeThisAccessing8.ts, 2, 1)) +>Base : Symbol(Base, Decl(superCallBeforeThisAccessing8.ts, 0, 0)) + + private _t; +>_t : Symbol(_t, Decl(superCallBeforeThisAccessing8.ts, 3, 22)) + + constructor() { + let x = { +>x : Symbol(x, Decl(superCallBeforeThisAccessing8.ts, 6, 11)) + + k: super(undefined), +>k : Symbol(k, Decl(superCallBeforeThisAccessing8.ts, 6, 17)) +>super : Symbol(Base, Decl(superCallBeforeThisAccessing8.ts, 0, 0)) +>undefined : Symbol(undefined) + + j: this._t, // no error +>j : Symbol(j, Decl(superCallBeforeThisAccessing8.ts, 7, 32)) +>this._t : Symbol(_t, Decl(superCallBeforeThisAccessing8.ts, 3, 22)) +>this : Symbol(D, Decl(superCallBeforeThisAccessing8.ts, 2, 1)) +>_t : Symbol(_t, Decl(superCallBeforeThisAccessing8.ts, 3, 22)) + } + } +} + diff --git a/tests/baselines/reference/superCallBeforeThisAccessing8.types b/tests/baselines/reference/superCallBeforeThisAccessing8.types new file mode 100644 index 00000000000..7378a1fed23 --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing8.types @@ -0,0 +1,34 @@ +=== tests/cases/conformance/classes/superCallBeforeThisAccessing8.ts === +class Base { +>Base : Base + + constructor(c) { } +>c : any +} +class D extends Base { +>D : D +>Base : Base + + private _t; +>_t : any + + constructor() { + let x = { +>x : { k: void; j: any; } +>{ k: super(undefined), j: this._t, // no error } : { k: void; j: any; } + + k: super(undefined), +>k : void +>super(undefined) : void +>super : typeof Base +>undefined : undefined + + j: this._t, // no error +>j : any +>this._t : any +>this : this +>_t : any + } + } +} + From ed0962883b9711f0f4c324c3e904bd776c5c9305 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 2 Feb 2016 13:06:07 -0800 Subject: [PATCH 03/10] Check using "super" before "this" lexically instead of using the NodeCheckFlags Remove "type-checking" way of checking if super is used before this. Instead check using whether super occurs before this syntactically Refactor the code Dive down to get super call --- src/compiler/checker.ts | 99 +++++++++++++++++++++++++---------------- src/compiler/types.ts | 6 +-- 2 files changed, 64 insertions(+), 41 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e0caf84fa9d..71cd41522f0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7262,6 +7262,47 @@ namespace ts { } } + function isSuperCallExpression(n: Node): boolean { + return n.kind === SyntaxKind.CallExpression && (n).expression.kind === SyntaxKind.SuperKeyword; + } + + /** + * Return a cached result if super-statement is already found. + * Otherwise, find a super statement in a given constructor function and cache the result in the node-links of the constructor + * + * @param constructor constructor-function to look for super statement + */ + function getSuperStatementInConstructor(constructor: ConstructorDeclaration): ExpressionStatement { + function getContainingSuperCall(n: Node): Node { + if (isSuperCallExpression(n)) { + return n; + } + else if (isFunctionLike(n)) { + return undefined; + } + return forEachChild(n, getContainingSuperCall); + } + + const links = getNodeLinks(constructor); + if (!links.superStatement) { + links.superStatement = getContainingSuperCall(constructor.body); + } + return links.superStatement; + } + + /** + * Check if the given class-declaration extends null then return true. + * Otherwise, return false + * @param classDecl a class declaration to check if it extends null + */ + function isClassDeclarationExtendNull(classDecl: ClassDeclaration): boolean { + const classSymbol = getSymbolOfNode(classDecl); + const classInstanceType = getDeclaredTypeOfSymbol(classSymbol); + const baseConstructorType = getBaseConstructorTypeOfClass(classInstanceType); + + return baseConstructorType === nullType; + } + function checkThisExpression(node: Node): Type { // Stop at the first arrow function so that we can // tell whether 'this' needs to be captured. @@ -7269,10 +7310,17 @@ namespace ts { let needToCaptureLexicalThis = false; if (container.kind === SyntaxKind.Constructor) { - const baseTypeNode = getClassExtendsHeritageClauseElement(container.parent); - if (baseTypeNode && !(getNodeCheckFlags(container) & NodeCheckFlags.HasSeenSuperCall)) { - // In ES6, super inside constructor of class-declaration has to precede "this" accessing - error(node, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class); + const containingClassDecl = container.parent; + const baseTypeNode = getClassExtendsHeritageClauseElement(containingClassDecl); + + // If a containing class does not have extends clause or the class extends null + // skip checking whether super statement is called before "this" accessing. + if (baseTypeNode && !isClassDeclarationExtendNull(containingClassDecl)) { + const superStatement = getSuperStatementInConstructor(container); + if (!superStatement || (superStatement && superStatement.pos > node.pos || superStatement.end > node.pos)) { + // In ES6, super inside constructor of class-declaration has to precede "this" accessing + error(node, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class); + } } } @@ -10219,14 +10267,11 @@ namespace ts { checkGrammarTypeArguments(node, node.typeArguments) || checkGrammarArguments(node, node.arguments); const signature = getResolvedSignature(node); - if (node.expression.kind === SyntaxKind.SuperKeyword) { - const containgFunction = getContainingFunction(node.expression); - if (containgFunction && containgFunction.kind === SyntaxKind.Constructor) { - getNodeLinks(containgFunction).flags |= NodeCheckFlags.HasSeenSuperCall; - } + if (node.expression.kind === SyntaxKind.SuperKeyword) { return voidType; } + if (node.kind === SyntaxKind.NewExpression) { const declaration = signature.declaration; @@ -11766,27 +11811,6 @@ namespace ts { return; } - function isSuperCallExpression(n: Node): boolean { - return n.kind === SyntaxKind.CallExpression && (n).expression.kind === SyntaxKind.SuperKeyword; - } - - function containsSuperCallAsComputedPropertyName(n: Declaration): boolean { - return n.name && containsSuperCall(n.name); - } - - function containsSuperCall(n: Node): boolean { - if (isSuperCallExpression(n)) { - return true; - } - else if (isFunctionLike(n)) { - return false; - } - else if (isClassLike(n)) { - return forEach((n).members, containsSuperCallAsComputedPropertyName); - } - return forEachChild(n, containsSuperCall); - } - function markThisReferencesAsErrors(n: Node): void { if (n.kind === SyntaxKind.ThisKeyword) { error(n, Diagnostics.this_cannot_be_referenced_in_current_location); @@ -11803,16 +11827,14 @@ namespace ts { } // TS 1.0 spec (April 2014): 8.3.2 - // Constructors of classes with no extends clause may not contain super calls, whereas - // constructors of derived classes must contain at least one super call somewhere in their function body. + // Constructors of classes with no extends clause and constructors of classes that extends null may not contain super calls, + // whereas constructors of derived classes must contain at least one super call somewhere in their function body. const containingClassDecl = node.parent; if (getClassExtendsHeritageClauseElement(containingClassDecl)) { - const containingClassSymbol = getSymbolOfNode(containingClassDecl); - const containingClassInstanceType = getDeclaredTypeOfSymbol(containingClassSymbol); - const baseConstructorType = getBaseConstructorTypeOfClass(containingClassInstanceType); + const isClassExtendNull = isClassDeclarationExtendNull(containingClassDecl); - if (containsSuperCall(node.body)) { - if (baseConstructorType === nullType) { + if (getSuperStatementInConstructor(node)) { + if (isClassExtendNull) { error(node, Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null); } @@ -11830,6 +11852,7 @@ namespace ts { if (superCallShouldBeFirst) { const statements = (node.body).statements; let superCallStatement: ExpressionStatement; + for (const statement of statements) { if (statement.kind === SyntaxKind.ExpressionStatement && isSuperCallExpression((statement).expression)) { superCallStatement = statement; @@ -11844,7 +11867,7 @@ namespace ts { } } } - else if (baseConstructorType !== nullType) { + else if (!isClassExtendNull) { error(node, Diagnostics.Constructors_for_derived_classes_must_contain_a_super_call); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ce3dbe7f459..5fdd40c14a1 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2068,9 +2068,8 @@ namespace ts { LoopWithCapturedBlockScopedBinding = 0x00010000, // Loop that contains block scoped variable captured in closure CapturedBlockScopedBinding = 0x00020000, // Block-scoped binding that is captured in some function BlockScopedBindingInLoop = 0x00040000, // Block-scoped binding with declaration nested inside iteration statement - HasSeenSuperCall = 0x00080000, // Set during the binding when encounter 'super' - ClassWithBodyScopedClassBinding = 0x00100000, // Decorated class that contains a binding to itself inside of the class body. - BodyScopedClassBinding = 0x00200000, // Binding to a decorated class inside of the class's body. + ClassWithBodyScopedClassBinding = 0x0080000, // Decorated class that contains a binding to itself inside of the class body. + BodyScopedClassBinding = 0x00100000, // Binding to a decorated class inside of the class's body. } /* @internal */ @@ -2089,6 +2088,7 @@ namespace ts { importOnRightSide?: Symbol; // for import declarations - import that appear on the right side jsxFlags?: JsxFlags; // flags for knowning what kind of element/attributes we're dealing with resolvedJsxType?: Type; // resolved element attributes type of a JSX openinglike element + superStatement?: ExpressionStatement; // Cached super-statement found in the constructor. Used in checking whether super is called before this-accessing } export const enum TypeFlags { From 7e1088bb50d9c374a18af14388049fbcae080183 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 3 Feb 2016 11:51:29 -0800 Subject: [PATCH 04/10] Address PR --- src/compiler/checker.ts | 42 ++++++++++++++++++++++++----------------- src/compiler/types.ts | 2 +- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 71cd41522f0..f3273c6e614 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7266,28 +7266,28 @@ namespace ts { return n.kind === SyntaxKind.CallExpression && (n).expression.kind === SyntaxKind.SuperKeyword; } + function findFirstSuperCall(n: Node): Node { + if (isSuperCallExpression(n)) { + return n; + } + else if (isFunctionLike(n)) { + return undefined; + } + return forEachChild(n, findFirstSuperCall); + } + /** * Return a cached result if super-statement is already found. * Otherwise, find a super statement in a given constructor function and cache the result in the node-links of the constructor * * @param constructor constructor-function to look for super statement */ - function getSuperStatementInConstructor(constructor: ConstructorDeclaration): ExpressionStatement { - function getContainingSuperCall(n: Node): Node { - if (isSuperCallExpression(n)) { - return n; - } - else if (isFunctionLike(n)) { - return undefined; - } - return forEachChild(n, getContainingSuperCall); - } - + function getSuperCallInConstructor(constructor: ConstructorDeclaration): ExpressionStatement { const links = getNodeLinks(constructor); - if (!links.superStatement) { - links.superStatement = getContainingSuperCall(constructor.body); + if (!links.superCall) { + links.superCall = findFirstSuperCall(constructor.body); } - return links.superStatement; + return links.superCall; } /** @@ -7316,8 +7316,16 @@ namespace ts { // If a containing class does not have extends clause or the class extends null // skip checking whether super statement is called before "this" accessing. if (baseTypeNode && !isClassDeclarationExtendNull(containingClassDecl)) { - const superStatement = getSuperStatementInConstructor(container); - if (!superStatement || (superStatement && superStatement.pos > node.pos || superStatement.end > node.pos)) { + const superCall = getSuperCallInConstructor(container); + + // We should give an error in the following cases: + // - No super-call + // - "this" is accessing before super-call. + // i.e super(this) + // this.x; super(); + // We want to make sure that super-call is done before accessing "this" so that + // "this" is not accessed as a parameter of the super-call. + if (!superCall || superCall.end > node.pos) { // In ES6, super inside constructor of class-declaration has to precede "this" accessing error(node, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class); } @@ -11833,7 +11841,7 @@ namespace ts { if (getClassExtendsHeritageClauseElement(containingClassDecl)) { const isClassExtendNull = isClassDeclarationExtendNull(containingClassDecl); - if (getSuperStatementInConstructor(node)) { + if (getSuperCallInConstructor(node)) { if (isClassExtendNull) { error(node, Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5fdd40c14a1..b99b7a29518 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2088,7 +2088,7 @@ namespace ts { importOnRightSide?: Symbol; // for import declarations - import that appear on the right side jsxFlags?: JsxFlags; // flags for knowning what kind of element/attributes we're dealing with resolvedJsxType?: Type; // resolved element attributes type of a JSX openinglike element - superStatement?: ExpressionStatement; // Cached super-statement found in the constructor. Used in checking whether super is called before this-accessing + superCall?: ExpressionStatement; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing } export const enum TypeFlags { From 2dbc998da4778fece33cbf0cb3ad4fb556d3b318 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 3 Feb 2016 12:55:38 -0800 Subject: [PATCH 05/10] Address PR about tests --- .../superCallBeforeThisAccessing1.errors.txt | 20 --------- .../superCallBeforeThisAccessing1.js | 2 + .../superCallBeforeThisAccessing1.symbols | 38 ++++++++++++++++ .../superCallBeforeThisAccessing1.types | 43 +++++++++++++++++++ .../classes/superCallBeforeThisAccessing1.ts | 4 +- 5 files changed, 86 insertions(+), 21 deletions(-) delete mode 100644 tests/baselines/reference/superCallBeforeThisAccessing1.errors.txt create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing1.symbols create mode 100644 tests/baselines/reference/superCallBeforeThisAccessing1.types diff --git a/tests/baselines/reference/superCallBeforeThisAccessing1.errors.txt b/tests/baselines/reference/superCallBeforeThisAccessing1.errors.txt deleted file mode 100644 index 40bbe62f714..00000000000 --- a/tests/baselines/reference/superCallBeforeThisAccessing1.errors.txt +++ /dev/null @@ -1,20 +0,0 @@ -tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts(11,17): error TS2304: Cannot find name 'Factory'. - - -==== tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts (1 errors) ==== - class Base { - constructor(c) { } - } - class D extends Base { - private _t; - constructor() { - super(i); - var s = { - t: this._t - } - var i = Factory.create(s); - ~~~~~~~ -!!! error TS2304: Cannot find name 'Factory'. - } - } - \ No newline at end of file diff --git a/tests/baselines/reference/superCallBeforeThisAccessing1.js b/tests/baselines/reference/superCallBeforeThisAccessing1.js index f7187fa6618..1fc7ab39c91 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing1.js +++ b/tests/baselines/reference/superCallBeforeThisAccessing1.js @@ -1,4 +1,6 @@ //// [superCallBeforeThisAccessing1.ts] +declare var Factory: any + class Base { constructor(c) { } } diff --git a/tests/baselines/reference/superCallBeforeThisAccessing1.symbols b/tests/baselines/reference/superCallBeforeThisAccessing1.symbols new file mode 100644 index 00000000000..b30d46c5b30 --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing1.symbols @@ -0,0 +1,38 @@ +=== tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts === +declare var Factory: any +>Factory : Symbol(Factory, Decl(superCallBeforeThisAccessing1.ts, 0, 11)) + +class Base { +>Base : Symbol(Base, Decl(superCallBeforeThisAccessing1.ts, 0, 24)) + + constructor(c) { } +>c : Symbol(c, Decl(superCallBeforeThisAccessing1.ts, 3, 16)) +} +class D extends Base { +>D : Symbol(D, Decl(superCallBeforeThisAccessing1.ts, 4, 1)) +>Base : Symbol(Base, Decl(superCallBeforeThisAccessing1.ts, 0, 24)) + + private _t; +>_t : Symbol(_t, Decl(superCallBeforeThisAccessing1.ts, 5, 22)) + + constructor() { + super(i); +>super : Symbol(Base, Decl(superCallBeforeThisAccessing1.ts, 0, 24)) +>i : Symbol(i, Decl(superCallBeforeThisAccessing1.ts, 12, 11)) + + var s = { +>s : Symbol(s, Decl(superCallBeforeThisAccessing1.ts, 9, 11)) + + t: this._t +>t : Symbol(t, Decl(superCallBeforeThisAccessing1.ts, 9, 17)) +>this._t : Symbol(_t, Decl(superCallBeforeThisAccessing1.ts, 5, 22)) +>this : Symbol(D, Decl(superCallBeforeThisAccessing1.ts, 4, 1)) +>_t : Symbol(_t, Decl(superCallBeforeThisAccessing1.ts, 5, 22)) + } + var i = Factory.create(s); +>i : Symbol(i, Decl(superCallBeforeThisAccessing1.ts, 12, 11)) +>Factory : Symbol(Factory, Decl(superCallBeforeThisAccessing1.ts, 0, 11)) +>s : Symbol(s, Decl(superCallBeforeThisAccessing1.ts, 9, 11)) + } +} + diff --git a/tests/baselines/reference/superCallBeforeThisAccessing1.types b/tests/baselines/reference/superCallBeforeThisAccessing1.types new file mode 100644 index 00000000000..641d49efdda --- /dev/null +++ b/tests/baselines/reference/superCallBeforeThisAccessing1.types @@ -0,0 +1,43 @@ +=== tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts === +declare var Factory: any +>Factory : any + +class Base { +>Base : Base + + constructor(c) { } +>c : any +} +class D extends Base { +>D : D +>Base : Base + + private _t; +>_t : any + + constructor() { + super(i); +>super(i) : void +>super : typeof Base +>i : any + + var s = { +>s : { t: any; } +>{ t: this._t } : { t: any; } + + t: this._t +>t : any +>this._t : any +>this : this +>_t : any + } + var i = Factory.create(s); +>i : any +>Factory.create(s) : any +>Factory.create : any +>Factory : any +>create : any +>s : { t: any; } + } +} + diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts b/tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts index 13b8fb8ed4d..e5d63f2e930 100644 --- a/tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts +++ b/tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts @@ -1,4 +1,6 @@ -class Base { +declare var Factory: any + +class Base { constructor(c) { } } class D extends Base { From aff6775a3688b0da97d61dc60a5b0d764e6aa265 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 3 Feb 2016 14:47:39 -0800 Subject: [PATCH 06/10] Add a flag so we don't repeatedly finding super call --- src/compiler/checker.ts | 5 ++++- src/compiler/types.ts | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f3273c6e614..a3772ac78f0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7284,8 +7284,11 @@ namespace ts { */ function getSuperCallInConstructor(constructor: ConstructorDeclaration): ExpressionStatement { const links = getNodeLinks(constructor); - if (!links.superCall) { + + // Only trying to find super-call if we haven't yet tried to find one. Once we try, we will record the result + if (links.hasSuperCall === undefined) { links.superCall = findFirstSuperCall(constructor.body); + links.hasSuperCall = links.superCall ? true : false; } return links.superCall; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index b99b7a29518..d0f1deff584 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -459,7 +459,6 @@ namespace ts { IntrinsicElement = IntrinsicNamedElement | IntrinsicIndexedElement, } - /* @internal */ export const enum RelationComparisonResult { Succeeded = 1, // Should be truthy @@ -2088,6 +2087,7 @@ namespace ts { importOnRightSide?: Symbol; // for import declarations - import that appear on the right side jsxFlags?: JsxFlags; // flags for knowning what kind of element/attributes we're dealing with resolvedJsxType?: Type; // resolved element attributes type of a JSX openinglike element + hasSuperCall?: boolean; // recorded result when we try to find super-call. We only try to find one if this flag is undefined, indicating that we haven't made an attempt. superCall?: ExpressionStatement; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing } From 1d4c1d15d5b22a085a9fc1f957a04bc0b384bbb2 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Thu, 4 Feb 2016 11:12:31 -0800 Subject: [PATCH 07/10] rename function --- src/compiler/checker.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a3772ac78f0..6404a766738 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7298,7 +7298,7 @@ namespace ts { * Otherwise, return false * @param classDecl a class declaration to check if it extends null */ - function isClassDeclarationExtendNull(classDecl: ClassDeclaration): boolean { + function classDeclarationExtendsNull(classDecl: ClassDeclaration): boolean { const classSymbol = getSymbolOfNode(classDecl); const classInstanceType = getDeclaredTypeOfSymbol(classSymbol); const baseConstructorType = getBaseConstructorTypeOfClass(classInstanceType); @@ -7318,7 +7318,7 @@ namespace ts { // If a containing class does not have extends clause or the class extends null // skip checking whether super statement is called before "this" accessing. - if (baseTypeNode && !isClassDeclarationExtendNull(containingClassDecl)) { + if (baseTypeNode && !classDeclarationExtendsNull(containingClassDecl)) { const superCall = getSuperCallInConstructor(container); // We should give an error in the following cases: @@ -11842,7 +11842,7 @@ namespace ts { // whereas constructors of derived classes must contain at least one super call somewhere in their function body. const containingClassDecl = node.parent; if (getClassExtendsHeritageClauseElement(containingClassDecl)) { - const isClassExtendNull = isClassDeclarationExtendNull(containingClassDecl); + const isClassExtendNull = classDeclarationExtendsNull(containingClassDecl); if (getSuperCallInConstructor(node)) { if (isClassExtendNull) { From 47a2f3be1ffc4f10d8f6743527086fe4766826a2 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Thu, 4 Feb 2016 13:12:16 -0800 Subject: [PATCH 08/10] Move tests into correct location --- .../reference/superCallBeforeThisAccessing1.symbols | 2 +- .../baselines/reference/superCallBeforeThisAccessing1.types | 2 +- .../reference/superCallBeforeThisAccessing2.symbols | 2 +- .../baselines/reference/superCallBeforeThisAccessing2.types | 2 +- .../reference/superCallBeforeThisAccessing3.errors.txt | 4 ++-- .../reference/superCallBeforeThisAccessing4.errors.txt | 6 +++--- .../reference/superCallBeforeThisAccessing5.symbols | 2 +- .../baselines/reference/superCallBeforeThisAccessing5.types | 2 +- .../reference/superCallBeforeThisAccessing6.errors.txt | 4 ++-- .../reference/superCallBeforeThisAccessing7.errors.txt | 4 ++-- .../reference/superCallBeforeThisAccessing8.symbols | 2 +- .../baselines/reference/superCallBeforeThisAccessing8.types | 2 +- .../classDeclaration}/superCallBeforeThisAccessing1.ts | 0 .../classDeclaration}/superCallBeforeThisAccessing2.ts | 0 .../classDeclaration}/superCallBeforeThisAccessing3.ts | 0 .../classDeclaration}/superCallBeforeThisAccessing4.ts | 0 .../classDeclaration}/superCallBeforeThisAccessing5.ts | 0 .../classDeclaration}/superCallBeforeThisAccessing6.ts | 0 .../classDeclaration}/superCallBeforeThisAccessing7.ts | 0 .../classDeclaration}/superCallBeforeThisAccessing8.ts | 0 20 files changed, 17 insertions(+), 17 deletions(-) rename tests/cases/conformance/{classes => es6/classDeclaration}/superCallBeforeThisAccessing1.ts (100%) rename tests/cases/conformance/{classes => es6/classDeclaration}/superCallBeforeThisAccessing2.ts (100%) rename tests/cases/conformance/{classes => es6/classDeclaration}/superCallBeforeThisAccessing3.ts (100%) rename tests/cases/conformance/{classes => es6/classDeclaration}/superCallBeforeThisAccessing4.ts (100%) rename tests/cases/conformance/{classes => es6/classDeclaration}/superCallBeforeThisAccessing5.ts (100%) rename tests/cases/conformance/{classes => es6/classDeclaration}/superCallBeforeThisAccessing6.ts (100%) rename tests/cases/conformance/{classes => es6/classDeclaration}/superCallBeforeThisAccessing7.ts (100%) rename tests/cases/conformance/{classes => es6/classDeclaration}/superCallBeforeThisAccessing8.ts (100%) diff --git a/tests/baselines/reference/superCallBeforeThisAccessing1.symbols b/tests/baselines/reference/superCallBeforeThisAccessing1.symbols index b30d46c5b30..5a153728a73 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing1.symbols +++ b/tests/baselines/reference/superCallBeforeThisAccessing1.symbols @@ -1,4 +1,4 @@ -=== tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts === +=== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing1.ts === declare var Factory: any >Factory : Symbol(Factory, Decl(superCallBeforeThisAccessing1.ts, 0, 11)) diff --git a/tests/baselines/reference/superCallBeforeThisAccessing1.types b/tests/baselines/reference/superCallBeforeThisAccessing1.types index 641d49efdda..e947653584a 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing1.types +++ b/tests/baselines/reference/superCallBeforeThisAccessing1.types @@ -1,4 +1,4 @@ -=== tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts === +=== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing1.ts === declare var Factory: any >Factory : any diff --git a/tests/baselines/reference/superCallBeforeThisAccessing2.symbols b/tests/baselines/reference/superCallBeforeThisAccessing2.symbols index 9e0e11dd2ac..2df2e62354a 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing2.symbols +++ b/tests/baselines/reference/superCallBeforeThisAccessing2.symbols @@ -1,4 +1,4 @@ -=== tests/cases/conformance/classes/superCallBeforeThisAccessing2.ts === +=== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing2.ts === class Base { >Base : Symbol(Base, Decl(superCallBeforeThisAccessing2.ts, 0, 0)) diff --git a/tests/baselines/reference/superCallBeforeThisAccessing2.types b/tests/baselines/reference/superCallBeforeThisAccessing2.types index e6307a977da..cf0f54b6246 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing2.types +++ b/tests/baselines/reference/superCallBeforeThisAccessing2.types @@ -1,4 +1,4 @@ -=== tests/cases/conformance/classes/superCallBeforeThisAccessing2.ts === +=== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing2.ts === class Base { >Base : Base diff --git a/tests/baselines/reference/superCallBeforeThisAccessing3.errors.txt b/tests/baselines/reference/superCallBeforeThisAccessing3.errors.txt index 526c43d735c..90b9b034263 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing3.errors.txt +++ b/tests/baselines/reference/superCallBeforeThisAccessing3.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/classes/superCallBeforeThisAccessing3.ts(9,9): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. +tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing3.ts(9,9): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. -==== tests/cases/conformance/classes/superCallBeforeThisAccessing3.ts (1 errors) ==== +==== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing3.ts (1 errors) ==== class Base { constructor(c) { } } diff --git a/tests/baselines/reference/superCallBeforeThisAccessing4.errors.txt b/tests/baselines/reference/superCallBeforeThisAccessing4.errors.txt index d3211eca14f..ca419b30858 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing4.errors.txt +++ b/tests/baselines/reference/superCallBeforeThisAccessing4.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/classes/superCallBeforeThisAccessing4.ts(3,5): error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' -tests/cases/conformance/classes/superCallBeforeThisAccessing4.ts(11,5): error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' +tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing4.ts(3,5): error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' +tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing4.ts(11,5): error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' -==== tests/cases/conformance/classes/superCallBeforeThisAccessing4.ts (2 errors) ==== +==== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing4.ts (2 errors) ==== class D extends null { private _t; constructor() { diff --git a/tests/baselines/reference/superCallBeforeThisAccessing5.symbols b/tests/baselines/reference/superCallBeforeThisAccessing5.symbols index 002d6e1ff77..a7628e3b8df 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing5.symbols +++ b/tests/baselines/reference/superCallBeforeThisAccessing5.symbols @@ -1,4 +1,4 @@ -=== tests/cases/conformance/classes/superCallBeforeThisAccessing5.ts === +=== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing5.ts === class D extends null { >D : Symbol(D, Decl(superCallBeforeThisAccessing5.ts, 0, 0)) diff --git a/tests/baselines/reference/superCallBeforeThisAccessing5.types b/tests/baselines/reference/superCallBeforeThisAccessing5.types index 543e453ffe3..2c0fc33c4dc 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing5.types +++ b/tests/baselines/reference/superCallBeforeThisAccessing5.types @@ -1,4 +1,4 @@ -=== tests/cases/conformance/classes/superCallBeforeThisAccessing5.ts === +=== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing5.ts === class D extends null { >D : D >null : null diff --git a/tests/baselines/reference/superCallBeforeThisAccessing6.errors.txt b/tests/baselines/reference/superCallBeforeThisAccessing6.errors.txt index 534b3605fc9..346b2d58bec 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing6.errors.txt +++ b/tests/baselines/reference/superCallBeforeThisAccessing6.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/classes/superCallBeforeThisAccessing6.ts(7,15): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. +tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing6.ts(7,15): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. -==== tests/cases/conformance/classes/superCallBeforeThisAccessing6.ts (1 errors) ==== +==== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing6.ts (1 errors) ==== class Base { constructor(c) { } } diff --git a/tests/baselines/reference/superCallBeforeThisAccessing7.errors.txt b/tests/baselines/reference/superCallBeforeThisAccessing7.errors.txt index 73997db3b25..4e374fd96ea 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing7.errors.txt +++ b/tests/baselines/reference/superCallBeforeThisAccessing7.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/classes/superCallBeforeThisAccessing7.ts(8,16): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. +tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing7.ts(8,16): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class. -==== tests/cases/conformance/classes/superCallBeforeThisAccessing7.ts (1 errors) ==== +==== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing7.ts (1 errors) ==== class Base { constructor(c) { } } diff --git a/tests/baselines/reference/superCallBeforeThisAccessing8.symbols b/tests/baselines/reference/superCallBeforeThisAccessing8.symbols index e29284be43b..65341ee9fe3 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing8.symbols +++ b/tests/baselines/reference/superCallBeforeThisAccessing8.symbols @@ -1,4 +1,4 @@ -=== tests/cases/conformance/classes/superCallBeforeThisAccessing8.ts === +=== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing8.ts === class Base { >Base : Symbol(Base, Decl(superCallBeforeThisAccessing8.ts, 0, 0)) diff --git a/tests/baselines/reference/superCallBeforeThisAccessing8.types b/tests/baselines/reference/superCallBeforeThisAccessing8.types index 7378a1fed23..dd92d924ceb 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing8.types +++ b/tests/baselines/reference/superCallBeforeThisAccessing8.types @@ -1,4 +1,4 @@ -=== tests/cases/conformance/classes/superCallBeforeThisAccessing8.ts === +=== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing8.ts === class Base { >Base : Base diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts b/tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing1.ts similarity index 100% rename from tests/cases/conformance/classes/superCallBeforeThisAccessing1.ts rename to tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing1.ts diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing2.ts b/tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing2.ts similarity index 100% rename from tests/cases/conformance/classes/superCallBeforeThisAccessing2.ts rename to tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing2.ts diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing3.ts b/tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing3.ts similarity index 100% rename from tests/cases/conformance/classes/superCallBeforeThisAccessing3.ts rename to tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing3.ts diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing4.ts b/tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing4.ts similarity index 100% rename from tests/cases/conformance/classes/superCallBeforeThisAccessing4.ts rename to tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing4.ts diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing5.ts b/tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing5.ts similarity index 100% rename from tests/cases/conformance/classes/superCallBeforeThisAccessing5.ts rename to tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing5.ts diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing6.ts b/tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing6.ts similarity index 100% rename from tests/cases/conformance/classes/superCallBeforeThisAccessing6.ts rename to tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing6.ts diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing7.ts b/tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing7.ts similarity index 100% rename from tests/cases/conformance/classes/superCallBeforeThisAccessing7.ts rename to tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing7.ts diff --git a/tests/cases/conformance/classes/superCallBeforeThisAccessing8.ts b/tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing8.ts similarity index 100% rename from tests/cases/conformance/classes/superCallBeforeThisAccessing8.ts rename to tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing8.ts From dc8e0ccd3d21744ca3678ade3d97d60da47cb6e3 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Mon, 8 Feb 2016 13:04:48 -0800 Subject: [PATCH 09/10] Address PR --- src/compiler/checker.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 925aae2783b..4a824e3bbb4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7306,10 +7306,6 @@ namespace ts { } } - function isSuperCallExpression(n: Node): boolean { - return n.kind === SyntaxKind.CallExpression && (n).expression.kind === SyntaxKind.SuperKeyword; - } - function findFirstSuperCall(n: Node): Node { if (isSuperCallExpression(n)) { return n; @@ -11885,14 +11881,14 @@ namespace ts { } // TS 1.0 spec (April 2014): 8.3.2 - // Constructors of classes with no extends clause and constructors of classes that extends null may not contain super calls, - // whereas constructors of derived classes must contain at least one super call somewhere in their function body. + // Constructors of classes with no extends clause may not contain super calls, whereas + // constructors of derived classes must contain at least one super call somewhere in their function body. const containingClassDecl = node.parent; if (getClassExtendsHeritageClauseElement(containingClassDecl)) { - const isClassExtendNull = classDeclarationExtendsNull(containingClassDecl); + const classExtendsNull = classDeclarationExtendsNull(containingClassDecl); if (getSuperCallInConstructor(node)) { - if (isClassExtendNull) { + if (classExtendsNull) { error(node, Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null); } @@ -11925,7 +11921,7 @@ namespace ts { } } } - else if (!isClassExtendNull) { + else if (!classExtendsNull) { error(node, Diagnostics.Constructors_for_derived_classes_must_contain_a_super_call); } } From 61e954bbc6a18ae21609d93221672b34d238ce9a Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Thu, 11 Feb 2016 10:11:39 -0800 Subject: [PATCH 10/10] Address PR: report error on super call instead of entire constructor node --- src/compiler/checker.ts | 6 +++--- .../reference/classExtendsNull.errors.txt | 11 ++++------ .../superCallBeforeThisAccessing4.errors.txt | 20 +++++++------------ 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4a824e3bbb4..67f200ceeb7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11886,10 +11886,10 @@ namespace ts { const containingClassDecl = node.parent; if (getClassExtendsHeritageClauseElement(containingClassDecl)) { const classExtendsNull = classDeclarationExtendsNull(containingClassDecl); - - if (getSuperCallInConstructor(node)) { + const superCall = getSuperCallInConstructor(node); + if (superCall) { if (classExtendsNull) { - error(node, Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null); + error(superCall, Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null); } // The first statement in the body of a constructor (excluding prologue directives) must be a super call diff --git a/tests/baselines/reference/classExtendsNull.errors.txt b/tests/baselines/reference/classExtendsNull.errors.txt index 7bb44774826..905c90c42fd 100644 --- a/tests/baselines/reference/classExtendsNull.errors.txt +++ b/tests/baselines/reference/classExtendsNull.errors.txt @@ -1,17 +1,14 @@ -tests/cases/compiler/classExtendsNull.ts(2,5): error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' +tests/cases/compiler/classExtendsNull.ts(3,9): error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' ==== tests/cases/compiler/classExtendsNull.ts (1 errors) ==== class C extends null { constructor() { - ~~~~~~~~~~~~~~~ super(); - ~~~~~~~~~~~~~~~~ - return Object.create(null); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - } - ~~~~~ + ~~~~~~~ !!! error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' + return Object.create(null); + } } class D extends null { diff --git a/tests/baselines/reference/superCallBeforeThisAccessing4.errors.txt b/tests/baselines/reference/superCallBeforeThisAccessing4.errors.txt index ca419b30858..91c3e7763f6 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing4.errors.txt +++ b/tests/baselines/reference/superCallBeforeThisAccessing4.errors.txt @@ -1,30 +1,24 @@ -tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing4.ts(3,5): error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' -tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing4.ts(11,5): error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' +tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing4.ts(5,9): error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' +tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing4.ts(12,9): error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' ==== tests/cases/conformance/es6/classDeclaration/superCallBeforeThisAccessing4.ts (2 errors) ==== class D extends null { private _t; constructor() { - ~~~~~~~~~~~~~~~ this._t; - ~~~~~~~~~~~~~~~~ super(); - ~~~~~~~~~~~~~~~~ - } - ~~~~~ + ~~~~~~~ !!! error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' + } } class E extends null { private _t; constructor() { - ~~~~~~~~~~~~~~~ super(); - ~~~~~~~~~~~~~~~~ - this._t; - ~~~~~~~~~~~~~~~~ - } - ~~~~~ + ~~~~~~~ !!! error TS17005: A constructor cannot contain a 'super' call when its class extends 'null' + this._t; + } } \ No newline at end of file