mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-30 10:29:18 -05:00
Merge pull request #12690 from Microsoft/fix12669
Add error for super property before super
This commit is contained in:
@@ -10405,6 +10405,29 @@ namespace ts {
|
||||
return baseConstructorType === nullWideningType;
|
||||
}
|
||||
|
||||
function checkThisBeforeSuper(node: Node, container: Node, diagnosticMessage: DiagnosticMessage) {
|
||||
const containingClassDecl = <ClassDeclaration>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 && !classDeclarationExtendsNull(containingClassDecl)) {
|
||||
const superCall = getSuperCallInConstructor(<ConstructorDeclaration>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, diagnosticMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkThisExpression(node: Node): Type {
|
||||
// Stop at the first arrow function so that we can
|
||||
// tell whether 'this' needs to be captured.
|
||||
@@ -10412,26 +10435,7 @@ namespace ts {
|
||||
let needToCaptureLexicalThis = false;
|
||||
|
||||
if (container.kind === SyntaxKind.Constructor) {
|
||||
const containingClassDecl = <ClassDeclaration>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 && !classDeclarationExtendsNull(containingClassDecl)) {
|
||||
const superCall = getSuperCallInConstructor(<ConstructorDeclaration>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);
|
||||
}
|
||||
}
|
||||
checkThisBeforeSuper(node, container, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class);
|
||||
}
|
||||
|
||||
// Now skip arrow functions to get the "real" owner of 'this'.
|
||||
@@ -10579,6 +10583,10 @@ namespace ts {
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
if (!isCallExpression && container.kind === SyntaxKind.Constructor) {
|
||||
checkThisBeforeSuper(node, container, Diagnostics.super_must_be_called_before_accessing_a_property_of_super_in_the_constructor_of_a_derived_class);
|
||||
}
|
||||
|
||||
if ((getModifierFlags(container) & ModifierFlags.Static) || isCallExpression) {
|
||||
nodeCheckFlag = NodeCheckFlags.SuperStatic;
|
||||
}
|
||||
|
||||
@@ -3165,6 +3165,10 @@
|
||||
"category": "Error",
|
||||
"code": 17010
|
||||
},
|
||||
"'super' must be called before accessing a property of 'super' in the constructor of a derived class.": {
|
||||
"category": "Error",
|
||||
"code": 17011
|
||||
},
|
||||
|
||||
"Circularity detected while resolving configuration: {0}": {
|
||||
"category": "Error",
|
||||
|
||||
@@ -2837,7 +2837,6 @@ namespace ts {
|
||||
// _super.call(this, a)
|
||||
// _super.m.call(this, a)
|
||||
// _super.prototype.m.call(this, a)
|
||||
|
||||
resultingCall = createFunctionCall(
|
||||
visitNode(target, visitor, isExpression),
|
||||
visitNode(thisArg, visitor, isExpression),
|
||||
|
||||
@@ -7,6 +7,7 @@ tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(26,9): error T
|
||||
tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(30,16): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors.
|
||||
tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(34,9): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors.
|
||||
tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(38,9): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors.
|
||||
tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(46,9): error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class.
|
||||
tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(46,14): error TS1034: 'super' must be followed by an argument list or member access.
|
||||
tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(58,9): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors.
|
||||
tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(62,9): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors.
|
||||
@@ -14,7 +15,7 @@ tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(67,9): error T
|
||||
tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(71,9): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors.
|
||||
|
||||
|
||||
==== tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts (14 errors) ====
|
||||
==== tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts (15 errors) ====
|
||||
//super call in class constructor with no base type
|
||||
class NoBase {
|
||||
constructor() {
|
||||
@@ -79,6 +80,8 @@ tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(71,9): error T
|
||||
//super call with type arguments
|
||||
constructor() {
|
||||
super<string>();
|
||||
~~~~~
|
||||
!!! 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.
|
||||
super();
|
||||
|
||||
@@ -2,10 +2,13 @@ tests/cases/compiler/superAccess2.ts(7,15): error TS1034: 'super' must be follow
|
||||
tests/cases/compiler/superAccess2.ts(8,17): error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class.
|
||||
tests/cases/compiler/superAccess2.ts(8,22): error TS1034: 'super' must be followed by an argument list or member access.
|
||||
tests/cases/compiler/superAccess2.ts(11,28): error TS2336: 'super' cannot be referenced in constructor arguments.
|
||||
tests/cases/compiler/superAccess2.ts(11,28): 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,33): error TS1034: 'super' must be followed by an argument list or member access.
|
||||
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.
|
||||
tests/cases/compiler/superAccess2.ts(17,15): error TS2339: Property 'y' does not exist on type 'P'.
|
||||
@@ -13,7 +16,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 (13 errors) ====
|
||||
==== tests/cases/compiler/superAccess2.ts (16 errors) ====
|
||||
class P {
|
||||
x() { }
|
||||
static y() { }
|
||||
@@ -33,14 +36,20 @@ tests/cases/compiler/superAccess2.ts(21,15): error TS2339: Property 'x' does not
|
||||
constructor(public z = super, zz = super, zzz = () => super) {
|
||||
~~~~~
|
||||
!!! 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.
|
||||
~~~~~
|
||||
!!! 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.
|
||||
~~~~~
|
||||
!!! 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.
|
||||
super();
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
tests/cases/compiler/superInConstructorParam1.ts(8,3): error TS2377: Constructors for derived classes must contain a 'super' call.
|
||||
tests/cases/compiler/superInConstructorParam1.ts(8,19): error TS2336: 'super' cannot be referenced in constructor arguments.
|
||||
tests/cases/compiler/superInConstructorParam1.ts(8,19): error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class.
|
||||
|
||||
|
||||
==== tests/cases/compiler/superInConstructorParam1.ts (2 errors) ====
|
||||
==== tests/cases/compiler/superInConstructorParam1.ts (3 errors) ====
|
||||
class B {
|
||||
public foo(): number {
|
||||
return 0;
|
||||
@@ -14,6 +15,8 @@ tests/cases/compiler/superInConstructorParam1.ts(8,19): error TS2336: 'super' ca
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~
|
||||
!!! 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 TS2377: Constructors for derived classes must contain a 'super' call.
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
tests/cases/compiler/superNewCall1.ts(9,5): error TS2377: Constructors for derived classes must contain a 'super' call.
|
||||
tests/cases/compiler/superNewCall1.ts(10,9): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
|
||||
tests/cases/compiler/superNewCall1.ts(10,13): error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class.
|
||||
|
||||
|
||||
==== tests/cases/compiler/superNewCall1.ts (2 errors) ====
|
||||
==== tests/cases/compiler/superNewCall1.ts (3 errors) ====
|
||||
|
||||
class A<T1, T2> {
|
||||
constructor(private map: (value: T1) => T2) {
|
||||
@@ -17,6 +18,8 @@ tests/cases/compiler/superNewCall1.ts(10,9): error TS2351: Cannot use 'new' with
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
|
||||
~~~~~
|
||||
!!! error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class.
|
||||
}
|
||||
~~~~~
|
||||
!!! error TS2377: Constructors for derived classes must contain a 'super' call.
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
tests/cases/conformance/classes/constructorDeclarations/superCalls/superPropertyInConstructorBeforeSuperCall.ts(7,9): error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class.
|
||||
tests/cases/conformance/classes/constructorDeclarations/superCalls/superPropertyInConstructorBeforeSuperCall.ts(13,15): error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class.
|
||||
|
||||
|
||||
==== tests/cases/conformance/classes/constructorDeclarations/superCalls/superPropertyInConstructorBeforeSuperCall.ts (2 errors) ====
|
||||
class B {
|
||||
constructor(x?: string) {}
|
||||
x(): string { return ""; }
|
||||
}
|
||||
class C1 extends B {
|
||||
constructor() {
|
||||
super.x();
|
||||
~~~~~
|
||||
!!! error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class.
|
||||
super();
|
||||
}
|
||||
}
|
||||
class C2 extends B {
|
||||
constructor() {
|
||||
super(super.x());
|
||||
~~~~~
|
||||
!!! error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
//// [superPropertyInConstructorBeforeSuperCall.ts]
|
||||
class B {
|
||||
constructor(x?: string) {}
|
||||
x(): string { return ""; }
|
||||
}
|
||||
class C1 extends B {
|
||||
constructor() {
|
||||
super.x();
|
||||
super();
|
||||
}
|
||||
}
|
||||
class C2 extends B {
|
||||
constructor() {
|
||||
super(super.x());
|
||||
}
|
||||
}
|
||||
|
||||
//// [superPropertyInConstructorBeforeSuperCall.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 B = (function () {
|
||||
function B(x) {
|
||||
}
|
||||
B.prototype.x = function () { return ""; };
|
||||
return B;
|
||||
}());
|
||||
var C1 = (function (_super) {
|
||||
__extends(C1, _super);
|
||||
function C1() {
|
||||
var _this;
|
||||
_super.prototype.x.call(_this);
|
||||
_this = _super.call(this) || this;
|
||||
return _this;
|
||||
}
|
||||
return C1;
|
||||
}(B));
|
||||
var C2 = (function (_super) {
|
||||
__extends(C2, _super);
|
||||
function C2() {
|
||||
return _super.call(this, _super.x.call(_this)) || this;
|
||||
}
|
||||
return C2;
|
||||
}(B));
|
||||
@@ -1,8 +1,9 @@
|
||||
tests/cases/compiler/superWithTypeArgument.ts(6,5): error TS2377: Constructors for derived classes must contain a 'super' call.
|
||||
tests/cases/compiler/superWithTypeArgument.ts(7,9): error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class.
|
||||
tests/cases/compiler/superWithTypeArgument.ts(7,14): error TS1034: 'super' must be followed by an argument list or member access.
|
||||
|
||||
|
||||
==== tests/cases/compiler/superWithTypeArgument.ts (2 errors) ====
|
||||
==== tests/cases/compiler/superWithTypeArgument.ts (3 errors) ====
|
||||
class C {
|
||||
|
||||
}
|
||||
@@ -12,6 +13,8 @@ tests/cases/compiler/superWithTypeArgument.ts(7,14): error TS1034: 'super' must
|
||||
~~~~~~~~~~~~~~~
|
||||
super<T>();
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~
|
||||
!!! 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.
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
tests/cases/compiler/superWithTypeArgument2.ts(6,5): error TS2377: Constructors for derived classes must contain a 'super' call.
|
||||
tests/cases/compiler/superWithTypeArgument2.ts(7,9): error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class.
|
||||
tests/cases/compiler/superWithTypeArgument2.ts(7,14): error TS1034: 'super' must be followed by an argument list or member access.
|
||||
|
||||
|
||||
==== tests/cases/compiler/superWithTypeArgument2.ts (2 errors) ====
|
||||
==== tests/cases/compiler/superWithTypeArgument2.ts (3 errors) ====
|
||||
class C<T> {
|
||||
foo: T;
|
||||
}
|
||||
@@ -12,6 +13,8 @@ tests/cases/compiler/superWithTypeArgument2.ts(7,14): error TS1034: 'super' must
|
||||
~~~~~~~~~~~~~~~~
|
||||
super<T>(x);
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~
|
||||
!!! 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.
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
tests/cases/compiler/superWithTypeArgument3.ts(7,5): error TS2377: Constructors for derived classes must contain a 'super' call.
|
||||
tests/cases/compiler/superWithTypeArgument3.ts(8,9): error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class.
|
||||
tests/cases/compiler/superWithTypeArgument3.ts(8,14): error TS1034: 'super' must be followed by an argument list or member access.
|
||||
|
||||
|
||||
==== tests/cases/compiler/superWithTypeArgument3.ts (2 errors) ====
|
||||
==== tests/cases/compiler/superWithTypeArgument3.ts (3 errors) ====
|
||||
class C<T> {
|
||||
foo: T;
|
||||
bar<U>(x: U) { }
|
||||
@@ -13,6 +14,8 @@ tests/cases/compiler/superWithTypeArgument3.ts(8,14): error TS1034: 'super' must
|
||||
~~~~~~~~~~~~~~~
|
||||
super<T>();
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~
|
||||
!!! 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.
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
class B {
|
||||
constructor(x?: string) {}
|
||||
x(): string { return ""; }
|
||||
}
|
||||
class C1 extends B {
|
||||
constructor() {
|
||||
super.x();
|
||||
super();
|
||||
}
|
||||
}
|
||||
class C2 extends B {
|
||||
constructor() {
|
||||
super(super.x());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user