Everything works so far

Need to test properties initialised in constructor
This commit is contained in:
Nathan Shively-Sanders 2019-09-16 13:36:04 -07:00
parent 70a15bdeeb
commit feb0fb6dc4
12 changed files with 297 additions and 51 deletions

View file

@ -29206,6 +29206,11 @@ namespace ts {
}
}
function getClassOrInterfaceDeclarationsOfSymbol(symbol: Symbol) {
return filter(symbol.declarations, (d: Declaration): d is ClassDeclaration | InterfaceDeclaration =>
d.kind === SyntaxKind.ClassDeclaration || d.kind === SyntaxKind.InterfaceDeclaration);
}
function areTypeParametersIdentical(declarations: readonly (ClassDeclaration | InterfaceDeclaration)[], targetParameters: TypeParameter[]) {
const maxTypeArgumentCount = length(targetParameters);
const minTypeArgumentCount = getMinTypeArgumentCount(targetParameters);
@ -29299,6 +29304,7 @@ namespace ts {
checkClassForStaticPropertyNameConflicts(node);
}
let baseType: BaseType | undefined;
const baseTypeNode = getEffectiveBaseTypeNode(node);
if (baseTypeNode) {
if (languageVersion < ScriptTarget.ES2015) {
@ -29312,7 +29318,7 @@ namespace ts {
const baseTypes = getBaseTypes(type);
if (baseTypes.length && produceDiagnostics) {
const baseType = baseTypes[0];
baseType = baseTypes[0];
const baseConstructorType = getBaseConstructorTypeOfClass(type);
const staticBaseType = getApparentType(baseConstructorType);
checkBaseTypeAccessibility(staticBaseType, baseTypeNode);
@ -29352,6 +29358,7 @@ namespace ts {
checkKindsOfPropertyMemberOverrides(type, baseType);
}
}
checkAmbientPropertyMemberOverrides(type, baseType);
const implementedTypeNodes = getClassImplementsHeritageClauseElements(node);
if (implementedTypeNodes) {
@ -29437,11 +29444,6 @@ namespace ts {
return getCheckFlags(s) & CheckFlags.Instantiated ? (<TransientSymbol>s).target! : s;
}
function getClassOrInterfaceDeclarationsOfSymbol(symbol: Symbol) {
return filter(symbol.declarations, (d: Declaration): d is ClassDeclaration | InterfaceDeclaration =>
d.kind === SyntaxKind.ClassDeclaration || d.kind === SyntaxKind.InterfaceDeclaration);
}
/**
* TypeScript 1.0 spec (April 2014): 8.2.3
* A derived class inherits all members from its base class it doesn't override.
@ -29529,11 +29531,6 @@ namespace ts {
}
continue;
}
if (derivedDeclarationFlags & ModifiersFlags.Ambient) {
const errorMessage = Diagnostics.Class_0_defines_instance_member_property_1_so_extended_class_2_must_provide_an_initializer_with_this_override;
error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type));
continue;
}
let errorMessage: DiagnosticMessage;
if (isPrototypeProperty(base)) {
@ -29556,6 +29553,20 @@ namespace ts {
}
}
function checkAmbientPropertyMemberOverrides(type: Type, baseType?: Type) {
for (const derivedProperty of getPropertiesOfType(type)) {
const derived = getTargetSymbol(derivedProperty);
if (derived.flags & SymbolFlags.Prototype) {
continue;
}
const base = baseType && getPropertyOfObjectType(baseType, derived.escapedName);
if (!base && getDeclarationModifierFlagsFromSymbol(derived) & ModifierFlags.Ambient) {
const errorMessage = Diagnostics.Ambient_property_declarations_must_override_a_property_in_a_base_class;
error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage);
}
}
}
function checkInheritedPropertiesAreIdentical(type: InterfaceType, typeNode: Node): boolean {
const baseTypes = getBaseTypes(type);
if (baseTypes.length < 2) {
@ -29599,6 +29610,9 @@ namespace ts {
}
const constructor = findConstructorDeclaration(node);
for (const member of node.members) {
if (getModifierFlags(member) & ModifierFlags.Ambient) {
continue;
}
if (isInstancePropertyWithoutInitializer(member)) {
const propName = (<PropertyDeclaration>member).name;
if (isIdentifier(propName)) {

View file

@ -2208,6 +2208,10 @@
"category": "Error",
"code": 2610
},
"Ambient property declarations must override a property in a base class.": {
"category": "Error",
"code": 2611
},
"Cannot augment module '{0}' with value exports because it resolves to a non-module entity.": {
"category": "Error",
"code": 2649

View file

@ -1,12 +1,15 @@
tests/cases/compiler/classExpressionPropertyModifiers.ts(2,5): error TS1031: 'declare' modifier cannot appear on a class element.
tests/cases/compiler/classExpressionPropertyModifiers.ts(2,13): error TS2611: Ambient property declarations must override a property in a base class.
tests/cases/compiler/classExpressionPropertyModifiers.ts(2,36): error TS1039: Initializers are not allowed in ambient contexts.
tests/cases/compiler/classExpressionPropertyModifiers.ts(3,5): error TS1031: 'export' modifier cannot appear on a class element.
==== tests/cases/compiler/classExpressionPropertyModifiers.ts (2 errors) ====
==== tests/cases/compiler/classExpressionPropertyModifiers.ts (3 errors) ====
const a = class Cat {
declare [Symbol.toStringTag] = "uh";
~~~~~~~
!!! error TS1031: 'declare' modifier cannot appear on a class element.
~~~~~~~~~~~~~~~~~~~~
!!! error TS2611: Ambient property declarations must override a property in a base class.
~~~~
!!! error TS1039: Initializers are not allowed in ambient contexts.
export foo = 1;
~~~~~~
!!! error TS1031: 'export' modifier cannot appear on a class element.

View file

@ -1,28 +1,72 @@
tests/cases/conformance/classes/propertyMemberDeclarations/derivedUninitializedPropertyDeclaration.ts(5,5): error TS2610: Class 'A' defines instance member property 'property', so extended class 'B' must provide an initializer with this override.
tests/cases/conformance/classes/propertyMemberDeclarations/derivedUninitializedPropertyDeclaration.ts(14,5): error TS2610: Class 'C' defines instance member property 'p', so extended class 'D' must provide an initializer with this override.
tests/cases/conformance/classes/propertyMemberDeclarations/derivedUninitializedPropertyDeclaration.ts(6,5): error TS2610: Class 'A' defines instance member property 'property', so extended class 'B' must provide an initializer with this override.
tests/cases/conformance/classes/propertyMemberDeclarations/derivedUninitializedPropertyDeclaration.ts(15,5): error TS1031: 'declare' modifier cannot appear on a class element.
tests/cases/conformance/classes/propertyMemberDeclarations/derivedUninitializedPropertyDeclaration.ts(16,13): error TS2611: Ambient property declarations must override a property in a base class.
tests/cases/conformance/classes/propertyMemberDeclarations/derivedUninitializedPropertyDeclaration.ts(17,24): error TS1039: Initializers are not allowed in ambient contexts.
tests/cases/conformance/classes/propertyMemberDeclarations/derivedUninitializedPropertyDeclaration.ts(20,13): error TS2611: Ambient property declarations must override a property in a base class.
tests/cases/conformance/classes/propertyMemberDeclarations/derivedUninitializedPropertyDeclaration.ts(24,5): error TS2564: Property 'p' has no initializer and is not definitely assigned in the constructor.
tests/cases/conformance/classes/propertyMemberDeclarations/derivedUninitializedPropertyDeclaration.ts(27,5): error TS2564: Property 'p' has no initializer and is not definitely assigned in the constructor.
tests/cases/conformance/classes/propertyMemberDeclarations/derivedUninitializedPropertyDeclaration.ts(27,5): error TS2610: Class 'C' defines instance member property 'p', so extended class 'D' must provide an initializer with this override.
tests/cases/conformance/classes/propertyMemberDeclarations/derivedUninitializedPropertyDeclaration.ts(39,5): error TS2610: Class 'E' defines instance member property 'p1', so extended class 'F' must provide an initializer with this override.
==== tests/cases/conformance/classes/propertyMemberDeclarations/derivedUninitializedPropertyDeclaration.ts (2 errors) ====
==== tests/cases/conformance/classes/propertyMemberDeclarations/derivedUninitializedPropertyDeclaration.ts (9 errors) ====
class A {
property = 'x';
m() { return 1 }
}
class B extends A {
property; // error
property: any; // error
~~~~~~~~
!!! error TS2610: Class 'A' defines instance member property 'property', so extended class 'B' must provide an initializer with this override.
}
class BD extends A {
declare property; // still has implicit any
declare property: any; // ok because it's implicitly initialised
}
class BDBang extends A {
declare property!: any; // doesn't need !, but is still allowed
}
class BOther extends A {
declare m() { return 2 } // not allowed on methods
~~~~~~~
!!! error TS1031: 'declare' modifier cannot appear on a class element.
declare nonce: any; // only allowed when exists in base
~~~~~
!!! error TS2611: Ambient property declarations must override a property in a base class.
declare property = 'y' // initialiser not allowed with declare
~~~
!!! error TS1039: Initializers are not allowed in ambient contexts.
}
class U {
declare nonce: any; // ambient declaration only allowed when an override
~~~~~
!!! error TS2611: Ambient property declarations must override a property in a base class.
}
class C {
p: string;
~
!!! error TS2564: Property 'p' has no initializer and is not definitely assigned in the constructor.
}
class D extends C {
p: 'hi'; // error
~
!!! error TS2564: Property 'p' has no initializer and is not definitely assigned in the constructor.
~
!!! error TS2610: Class 'C' defines instance member property 'p', so extended class 'D' must provide an initializer with this override.
}
class DD extends C {
declare p: 'bye'; // ok
}
declare class E {
p1: string
p2: string
}
class F extends E {
p1!: 'z'
~~
!!! error TS2610: Class 'E' defines instance member property 'p1', so extended class 'F' must provide an initializer with this override.
declare p2: 'alpha'
}

View file

@ -1,13 +1,26 @@
//// [derivedUninitializedPropertyDeclaration.ts]
class A {
property = 'x';
m() { return 1 }
}
class B extends A {
property; // error
property: any; // error
}
class BD extends A {
declare property; // still has implicit any
declare property: any; // ok because it's implicitly initialised
}
class BDBang extends A {
declare property!: any; // doesn't need !, but is still allowed
}
class BOther extends A {
declare m() { return 2 } // not allowed on methods
declare nonce: any; // only allowed when exists in base
declare property = 'y' // initialiser not allowed with declare
}
class U {
declare nonce: any; // ambient declaration only allowed when an override
}
class C {
p: string;
}
@ -17,9 +30,20 @@ class D extends C {
class DD extends C {
declare p: 'bye'; // ok
}
declare class E {
p1: string
p2: string
}
class F extends E {
p1!: 'z'
declare p2: 'alpha'
}
//// [derivedUninitializedPropertyDeclaration.js]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
@ -37,6 +61,7 @@ var A = /** @class */ (function () {
function A() {
this.property = 'x';
}
A.prototype.m = function () { return 1; };
return A;
}());
var B = /** @class */ (function (_super) {
@ -53,6 +78,28 @@ var BD = /** @class */ (function (_super) {
}
return BD;
}(A));
var BDBang = /** @class */ (function (_super) {
__extends(BDBang, _super);
function BDBang() {
return _super !== null && _super.apply(this, arguments) || this;
}
return BDBang;
}(A));
var BOther = /** @class */ (function (_super) {
__extends(BOther, _super);
function BOther() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.property = 'y'; // initialiser not allowed with declare
return _this;
}
BOther.prototype.m = function () { return 2; }; // not allowed on methods
return BOther;
}(A));
var U = /** @class */ (function () {
function U() {
}
return U;
}());
var C = /** @class */ (function () {
function C() {
}
@ -72,3 +119,10 @@ var DD = /** @class */ (function (_super) {
}
return DD;
}(C));
var F = /** @class */ (function (_super) {
__extends(F, _super);
function F() {
return _super !== null && _super.apply(this, arguments) || this;
}
return F;
}(E));

View file

@ -4,39 +4,90 @@ class A {
property = 'x';
>property : Symbol(A.property, Decl(derivedUninitializedPropertyDeclaration.ts, 0, 9))
m() { return 1 }
>m : Symbol(A.m, Decl(derivedUninitializedPropertyDeclaration.ts, 1, 19))
}
class B extends A {
>B : Symbol(B, Decl(derivedUninitializedPropertyDeclaration.ts, 2, 1))
>B : Symbol(B, Decl(derivedUninitializedPropertyDeclaration.ts, 3, 1))
>A : Symbol(A, Decl(derivedUninitializedPropertyDeclaration.ts, 0, 0))
property; // error
>property : Symbol(B.property, Decl(derivedUninitializedPropertyDeclaration.ts, 3, 19))
property: any; // error
>property : Symbol(B.property, Decl(derivedUninitializedPropertyDeclaration.ts, 4, 19))
}
class BD extends A {
>BD : Symbol(BD, Decl(derivedUninitializedPropertyDeclaration.ts, 5, 1))
>BD : Symbol(BD, Decl(derivedUninitializedPropertyDeclaration.ts, 6, 1))
>A : Symbol(A, Decl(derivedUninitializedPropertyDeclaration.ts, 0, 0))
declare property; // still has implicit any
>property : Symbol(BD.property, Decl(derivedUninitializedPropertyDeclaration.ts, 6, 20))
declare property: any; // ok because it's implicitly initialised
>property : Symbol(BD.property, Decl(derivedUninitializedPropertyDeclaration.ts, 7, 20))
}
class BDBang extends A {
>BDBang : Symbol(BDBang, Decl(derivedUninitializedPropertyDeclaration.ts, 9, 1))
>A : Symbol(A, Decl(derivedUninitializedPropertyDeclaration.ts, 0, 0))
declare property!: any; // doesn't need !, but is still allowed
>property : Symbol(BDBang.property, Decl(derivedUninitializedPropertyDeclaration.ts, 10, 24))
}
class BOther extends A {
>BOther : Symbol(BOther, Decl(derivedUninitializedPropertyDeclaration.ts, 12, 1))
>A : Symbol(A, Decl(derivedUninitializedPropertyDeclaration.ts, 0, 0))
declare m() { return 2 } // not allowed on methods
>m : Symbol(BOther.m, Decl(derivedUninitializedPropertyDeclaration.ts, 13, 24))
declare nonce: any; // only allowed when exists in base
>nonce : Symbol(BOther.nonce, Decl(derivedUninitializedPropertyDeclaration.ts, 14, 28))
declare property = 'y' // initialiser not allowed with declare
>property : Symbol(BOther.property, Decl(derivedUninitializedPropertyDeclaration.ts, 15, 23))
}
class U {
>U : Symbol(U, Decl(derivedUninitializedPropertyDeclaration.ts, 17, 1))
declare nonce: any; // ambient declaration only allowed when an override
>nonce : Symbol(U.nonce, Decl(derivedUninitializedPropertyDeclaration.ts, 18, 9))
}
class C {
>C : Symbol(C, Decl(derivedUninitializedPropertyDeclaration.ts, 8, 1))
>C : Symbol(C, Decl(derivedUninitializedPropertyDeclaration.ts, 20, 1))
p: string;
>p : Symbol(C.p, Decl(derivedUninitializedPropertyDeclaration.ts, 9, 9))
>p : Symbol(C.p, Decl(derivedUninitializedPropertyDeclaration.ts, 22, 9))
}
class D extends C {
>D : Symbol(D, Decl(derivedUninitializedPropertyDeclaration.ts, 11, 1))
>C : Symbol(C, Decl(derivedUninitializedPropertyDeclaration.ts, 8, 1))
>D : Symbol(D, Decl(derivedUninitializedPropertyDeclaration.ts, 24, 1))
>C : Symbol(C, Decl(derivedUninitializedPropertyDeclaration.ts, 20, 1))
p: 'hi'; // error
>p : Symbol(D.p, Decl(derivedUninitializedPropertyDeclaration.ts, 12, 19))
>p : Symbol(D.p, Decl(derivedUninitializedPropertyDeclaration.ts, 25, 19))
}
class DD extends C {
>DD : Symbol(DD, Decl(derivedUninitializedPropertyDeclaration.ts, 14, 1))
>C : Symbol(C, Decl(derivedUninitializedPropertyDeclaration.ts, 8, 1))
>DD : Symbol(DD, Decl(derivedUninitializedPropertyDeclaration.ts, 27, 1))
>C : Symbol(C, Decl(derivedUninitializedPropertyDeclaration.ts, 20, 1))
declare p: 'bye'; // ok
>p : Symbol(DD.p, Decl(derivedUninitializedPropertyDeclaration.ts, 15, 20))
>p : Symbol(DD.p, Decl(derivedUninitializedPropertyDeclaration.ts, 28, 20))
}
declare class E {
>E : Symbol(E, Decl(derivedUninitializedPropertyDeclaration.ts, 30, 1))
p1: string
>p1 : Symbol(E.p1, Decl(derivedUninitializedPropertyDeclaration.ts, 33, 17))
p2: string
>p2 : Symbol(E.p2, Decl(derivedUninitializedPropertyDeclaration.ts, 34, 14))
}
class F extends E {
>F : Symbol(F, Decl(derivedUninitializedPropertyDeclaration.ts, 36, 1))
>E : Symbol(E, Decl(derivedUninitializedPropertyDeclaration.ts, 30, 1))
p1!: 'z'
>p1 : Symbol(F.p1, Decl(derivedUninitializedPropertyDeclaration.ts, 37, 19))
declare p2: 'alpha'
>p2 : Symbol(F.p2, Decl(derivedUninitializedPropertyDeclaration.ts, 38, 12))
}

View file

@ -5,21 +5,54 @@ class A {
property = 'x';
>property : string
>'x' : "x"
m() { return 1 }
>m : () => number
>1 : 1
}
class B extends A {
>B : B
>A : A
property; // error
property: any; // error
>property : any
}
class BD extends A {
>BD : BD
>A : A
declare property; // still has implicit any
declare property: any; // ok because it's implicitly initialised
>property : any
}
class BDBang extends A {
>BDBang : BDBang
>A : A
declare property!: any; // doesn't need !, but is still allowed
>property : any
}
class BOther extends A {
>BOther : BOther
>A : A
declare m() { return 2 } // not allowed on methods
>m : () => number
>2 : 2
declare nonce: any; // only allowed when exists in base
>nonce : any
declare property = 'y' // initialiser not allowed with declare
>property : string
>'y' : "y"
}
class U {
>U : U
declare nonce: any; // ambient declaration only allowed when an override
>nonce : any
}
class C {
>C : C
@ -41,3 +74,24 @@ class DD extends C {
>p : "bye"
}
declare class E {
>E : E
p1: string
>p1 : string
p2: string
>p2 : string
}
class F extends E {
>F : F
>E : E
p1!: 'z'
>p1 : "z"
declare p2: 'alpha'
>p2 : "alpha"
}

View file

@ -1,12 +1,15 @@
tests/cases/compiler/illegalModifiersOnClassElements.ts(2,5): error TS1031: 'declare' modifier cannot appear on a class element.
tests/cases/compiler/illegalModifiersOnClassElements.ts(2,13): error TS2611: Ambient property declarations must override a property in a base class.
tests/cases/compiler/illegalModifiersOnClassElements.ts(2,19): error TS1039: Initializers are not allowed in ambient contexts.
tests/cases/compiler/illegalModifiersOnClassElements.ts(3,5): error TS1031: 'export' modifier cannot appear on a class element.
==== tests/cases/compiler/illegalModifiersOnClassElements.ts (2 errors) ====
==== tests/cases/compiler/illegalModifiersOnClassElements.ts (3 errors) ====
class C {
declare foo = 1;
~~~~~~~
!!! error TS1031: 'declare' modifier cannot appear on a class element.
~~~
!!! error TS2611: Ambient property declarations must override a property in a base class.
~
!!! error TS1039: Initializers are not allowed in ambient contexts.
export bar = 1;
~~~~~~
!!! error TS1031: 'export' modifier cannot appear on a class element.

View file

@ -1,12 +1,15 @@
tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration11.ts(2,5): error TS1031: 'declare' modifier cannot appear on a class element.
tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration11.ts(2,17): error TS2378: A 'get' accessor must return a value.
tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration11.ts(2,17): error TS2611: Ambient property declarations must override a property in a base class.
==== tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration11.ts (2 errors) ====
==== tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration11.ts (3 errors) ====
class C {
declare get Foo() { }
~~~~~~~
!!! error TS1031: 'declare' modifier cannot appear on a class element.
~~~
!!! error TS2378: A 'get' accessor must return a value.
~~~
!!! error TS2611: Ambient property declarations must override a property in a base class.
}

View file

@ -1,9 +1,12 @@
tests/cases/conformance/parser/ecmascript5/MemberFunctionDeclarations/parserMemberFunctionDeclaration5.ts(2,5): error TS1031: 'declare' modifier cannot appear on a class element.
tests/cases/conformance/parser/ecmascript5/MemberFunctionDeclarations/parserMemberFunctionDeclaration5.ts(2,13): error TS2611: Ambient property declarations must override a property in a base class.
==== tests/cases/conformance/parser/ecmascript5/MemberFunctionDeclarations/parserMemberFunctionDeclaration5.ts (1 errors) ====
==== tests/cases/conformance/parser/ecmascript5/MemberFunctionDeclarations/parserMemberFunctionDeclaration5.ts (2 errors) ====
class C {
declare Foo() { }
~~~~~~~
!!! error TS1031: 'declare' modifier cannot appear on a class element.
~~~
!!! error TS2611: Ambient property declarations must override a property in a base class.
}

View file

@ -1,9 +1,9 @@
tests/cases/conformance/parser/ecmascript5/MemberVariableDeclarations/parserMemberVariableDeclaration5.ts(2,3): error TS1031: 'declare' modifier cannot appear on a class element.
tests/cases/conformance/parser/ecmascript5/MemberVariableDeclarations/parserMemberVariableDeclaration5.ts(2,11): error TS2611: Ambient property declarations must override a property in a base class.
==== tests/cases/conformance/parser/ecmascript5/MemberVariableDeclarations/parserMemberVariableDeclaration5.ts (1 errors) ====
class C {
declare Foo;
~~~~~~~
!!! error TS1031: 'declare' modifier cannot appear on a class element.
~~~
!!! error TS2611: Ambient property declarations must override a property in a base class.
}

View file

@ -4,19 +4,22 @@ class A {
m() { return 1 }
}
class B extends A {
property; // error
property: any; // error
}
class BD extends A {
declare property; // still has implicit any, but is implicitly initialised
declare property: any; // ok because it's implicitly initialised
}
class BDBang extends A {
declare property!; // still has implicit any, doesn't need !, but has it anyway
declare property!: any; // doesn't need !, but is still allowed
}
class BOther extends A {
declare m() { return 2 } // not allowed on methods
declare nonce; // only allowed when exists in base
declare nonce: any; // only allowed when exists in base
declare property = 'y' // initialiser not allowed with declare
}
class U {
declare nonce: any; // ambient declaration only allowed when an override
}
class C {
p: string;
@ -27,3 +30,13 @@ class D extends C {
class DD extends C {
declare p: 'bye'; // ok
}
declare class E {
p1: string
p2: string
}
class F extends E {
p1!: 'z'
declare p2: 'alpha'
}