From a4a7669a4ba37c13afe3f1d41404681e98945f94 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 31 Mar 2017 14:17:37 -0700 Subject: [PATCH 1/2] Add super to control flow. It is handled the same way as 'this' --- src/compiler/binder.ts | 1 + src/compiler/checker.ts | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 45e8efdf512..2d346bc9d1b 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -703,6 +703,7 @@ namespace ts { function isNarrowableReference(expr: Expression): boolean { return expr.kind === SyntaxKind.Identifier || expr.kind === SyntaxKind.ThisKeyword || + expr.kind === SyntaxKind.SuperKeyword || expr.kind === SyntaxKind.PropertyAccessExpression && isNarrowableReference((expr).expression); } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d36aae6bdd2..e5271d882ce 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10347,6 +10347,8 @@ namespace ts { getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(source)) === getSymbolOfNode(target); case SyntaxKind.ThisKeyword: return target.kind === SyntaxKind.ThisKeyword; + case SyntaxKind.SuperKeyword: + return target.kind === SyntaxKind.SuperKeyword; case SyntaxKind.PropertyAccessExpression: return target.kind === SyntaxKind.PropertyAccessExpression && (source).name.text === (target).name.text && @@ -11483,6 +11485,7 @@ namespace ts { switch (expr.kind) { case SyntaxKind.Identifier: case SyntaxKind.ThisKeyword: + case SyntaxKind.SuperKeyword: case SyntaxKind.PropertyAccessExpression: return narrowTypeByTruthiness(type, expr, assumeTrue); case SyntaxKind.CallExpression: From b28975dc030f8862f628238b28aad2a87c7579a9 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 31 Mar 2017 14:18:42 -0700 Subject: [PATCH 2/2] Test that super is tracked in control flow --- .../controlFlowSuperPropertyAccess.js | 37 +++++++++++++++++++ .../controlFlowSuperPropertyAccess.symbols | 24 ++++++++++++ .../controlFlowSuperPropertyAccess.types | 26 +++++++++++++ .../controlFlowSuperPropertyAccess.ts | 9 +++++ 4 files changed, 96 insertions(+) create mode 100644 tests/baselines/reference/controlFlowSuperPropertyAccess.js create mode 100644 tests/baselines/reference/controlFlowSuperPropertyAccess.symbols create mode 100644 tests/baselines/reference/controlFlowSuperPropertyAccess.types create mode 100644 tests/cases/conformance/controlFlow/controlFlowSuperPropertyAccess.ts diff --git a/tests/baselines/reference/controlFlowSuperPropertyAccess.js b/tests/baselines/reference/controlFlowSuperPropertyAccess.js new file mode 100644 index 00000000000..c2f947d5687 --- /dev/null +++ b/tests/baselines/reference/controlFlowSuperPropertyAccess.js @@ -0,0 +1,37 @@ +//// [controlFlowSuperPropertyAccess.ts] +class B { + protected m?(): void; +} +class C extends B { + body() { + super.m && super.m(); + } +} + + +//// [controlFlowSuperPropertyAccess.js] +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var B = (function () { + function B() { + } + return B; +}()); +var C = (function (_super) { + __extends(C, _super); + function C() { + return _super !== null && _super.apply(this, arguments) || this; + } + C.prototype.body = function () { + _super.prototype.m && _super.prototype.m.call(this); + }; + return C; +}(B)); diff --git a/tests/baselines/reference/controlFlowSuperPropertyAccess.symbols b/tests/baselines/reference/controlFlowSuperPropertyAccess.symbols new file mode 100644 index 00000000000..7b7053f96fa --- /dev/null +++ b/tests/baselines/reference/controlFlowSuperPropertyAccess.symbols @@ -0,0 +1,24 @@ +=== tests/cases/conformance/controlFlow/controlFlowSuperPropertyAccess.ts === +class B { +>B : Symbol(B, Decl(controlFlowSuperPropertyAccess.ts, 0, 0)) + + protected m?(): void; +>m : Symbol(B.m, Decl(controlFlowSuperPropertyAccess.ts, 0, 9)) +} +class C extends B { +>C : Symbol(C, Decl(controlFlowSuperPropertyAccess.ts, 2, 1)) +>B : Symbol(B, Decl(controlFlowSuperPropertyAccess.ts, 0, 0)) + + body() { +>body : Symbol(C.body, Decl(controlFlowSuperPropertyAccess.ts, 3, 19)) + + super.m && super.m(); +>super.m : Symbol(B.m, Decl(controlFlowSuperPropertyAccess.ts, 0, 9)) +>super : Symbol(B, Decl(controlFlowSuperPropertyAccess.ts, 0, 0)) +>m : Symbol(B.m, Decl(controlFlowSuperPropertyAccess.ts, 0, 9)) +>super.m : Symbol(B.m, Decl(controlFlowSuperPropertyAccess.ts, 0, 9)) +>super : Symbol(B, Decl(controlFlowSuperPropertyAccess.ts, 0, 0)) +>m : Symbol(B.m, Decl(controlFlowSuperPropertyAccess.ts, 0, 9)) + } +} + diff --git a/tests/baselines/reference/controlFlowSuperPropertyAccess.types b/tests/baselines/reference/controlFlowSuperPropertyAccess.types new file mode 100644 index 00000000000..87e7b3f00d0 --- /dev/null +++ b/tests/baselines/reference/controlFlowSuperPropertyAccess.types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/controlFlow/controlFlowSuperPropertyAccess.ts === +class B { +>B : B + + protected m?(): void; +>m : (() => void) | undefined +} +class C extends B { +>C : C +>B : B + + body() { +>body : () => void + + super.m && super.m(); +>super.m && super.m() : void | undefined +>super.m : (() => void) | undefined +>super : B +>m : (() => void) | undefined +>super.m() : void +>super.m : () => void +>super : B +>m : () => void + } +} + diff --git a/tests/cases/conformance/controlFlow/controlFlowSuperPropertyAccess.ts b/tests/cases/conformance/controlFlow/controlFlowSuperPropertyAccess.ts new file mode 100644 index 00000000000..b42af687c0c --- /dev/null +++ b/tests/cases/conformance/controlFlow/controlFlowSuperPropertyAccess.ts @@ -0,0 +1,9 @@ +// @strictNullChecks: true +class B { + protected m?(): void; +} +class C extends B { + body() { + super.m && super.m(); + } +}