From 6cd5a4dac9599122eff78d016a82ac0d362850ab Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 11:03:45 -0800 Subject: [PATCH 01/12] Compare enums semi-structurally. 1. Unqualified names must match. 2. Target contains members with same names as all source members. --- src/compiler/checker.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 50a3aee995528..0f04daf29830a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5040,6 +5040,11 @@ namespace ts { if (source === undefinedType) return Ternary.True; if (source === nullType && target !== undefinedType) return Ternary.True; if (source.flags & TypeFlags.Enum && target === numberType) return Ternary.True; + if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) { + if (result = enumRelatedTo(source, target)) { + return result; + } + } if (source.flags & TypeFlags.StringLiteral && target === stringType) return Ternary.True; if (relation === assignableRelation) { if (isTypeAny(source)) return Ternary.True; @@ -5750,6 +5755,25 @@ namespace ts { } return Ternary.False; } + + function enumRelatedTo(source: Type, target: Type) { + if (source.symbol.name !== target.symbol.name) { + return Ternary.False; + } + const sourceDecl = getMergedSymbol(source.symbol).valueDeclaration; + const targetDecl = getMergedSymbol(target.symbol).valueDeclaration; + const targetMembers = arrayToMap(targetDecl.members, member => getTextOfPropertyName(member.name)); + for (const member of sourceDecl.members) { + const name = getTextOfPropertyName(member.name); + if (!targetMembers[name]) { + reportError(Diagnostics.Property_0_is_missing_in_type_1, + name, + typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); + return Ternary.False; + } + } + return Ternary.True; + } } // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case From 6ed5b59f751f57532e43cbc0ac71ff097bcc899b Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 11:05:25 -0800 Subject: [PATCH 02/12] Add test case and accept baseline --- .../enumAssignmentCompat3.errors.txt | 75 ++++++++++++ .../reference/enumAssignmentCompat3.js | 115 ++++++++++++++++++ tests/cases/compiler/enumAssignmentCompat3.ts | 45 +++++++ 3 files changed, 235 insertions(+) create mode 100644 tests/baselines/reference/enumAssignmentCompat3.errors.txt create mode 100644 tests/baselines/reference/enumAssignmentCompat3.js create mode 100644 tests/cases/compiler/enumAssignmentCompat3.ts diff --git a/tests/baselines/reference/enumAssignmentCompat3.errors.txt b/tests/baselines/reference/enumAssignmentCompat3.errors.txt new file mode 100644 index 0000000000000..d82a4b7d490b9 --- /dev/null +++ b/tests/baselines/reference/enumAssignmentCompat3.errors.txt @@ -0,0 +1,75 @@ +tests/cases/compiler/enumAssignmentCompat3.ts(37,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. + Property 'd' is missing in type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(39,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. + Property 'd' is missing in type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(40,1): error TS2322: Type 'Nope' is not assignable to type 'E'. +tests/cases/compiler/enumAssignmentCompat3.ts(43,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. + Property 'c' is missing in type 'Ab.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(44,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. + Property 'a' is missing in type 'Cd.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(45,1): error TS2322: Type 'E' is not assignable to type 'Nope'. + + +==== tests/cases/compiler/enumAssignmentCompat3.ts (6 errors) ==== + namespace First { + export enum E { + a, b, c, + } + } + namespace Abc { + export enum E { + a, b, c, + } + export enum Nope { + a, b, c, + } + } + namespace Abcd { + export enum E { + a, b, c, d, + } + } + namespace Ab { + export enum E { + a, b, + } + } + namespace Cd { + export enum E { + c, d, + } + } + + var abc: First.E; + var secondAbc: Abc.E; + var secondAbcd: Abcd.E; + var secondAb: Ab.E; + var secondCd: Cd.E; + var nope: Abc.Nope; + abc = secondAbc; // ok + abc = secondAbcd; // missing 'd' + ~~~ +!!! error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. +!!! error TS2322: Property 'd' is missing in type 'First.E'. + abc = secondAb; // ok + abc = secondCd; // missing 'd' + ~~~ +!!! error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. +!!! error TS2322: Property 'd' is missing in type 'First.E'. + abc = nope; // nope! + ~~~ +!!! error TS2322: Type 'Nope' is not assignable to type 'E'. + secondAbc = abc; // ok + secondAbcd = abc; // ok + secondAb = abc; // missing 'c' + ~~~~~~~~ +!!! error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. +!!! error TS2322: Property 'c' is missing in type 'Ab.E'. + secondCd = abc; // missing 'a' and 'b' + ~~~~~~~~ +!!! error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. +!!! error TS2322: Property 'a' is missing in type 'Cd.E'. + nope = abc; // nope! + ~~~~ +!!! error TS2322: Type 'E' is not assignable to type 'Nope'. + \ No newline at end of file diff --git a/tests/baselines/reference/enumAssignmentCompat3.js b/tests/baselines/reference/enumAssignmentCompat3.js new file mode 100644 index 0000000000000..33cfdd28e888d --- /dev/null +++ b/tests/baselines/reference/enumAssignmentCompat3.js @@ -0,0 +1,115 @@ +//// [enumAssignmentCompat3.ts] +namespace First { + export enum E { + a, b, c, + } +} +namespace Abc { + export enum E { + a, b, c, + } + export enum Nope { + a, b, c, + } +} +namespace Abcd { + export enum E { + a, b, c, d, + } +} +namespace Ab { + export enum E { + a, b, + } +} +namespace Cd { + export enum E { + c, d, + } +} + +var abc: First.E; +var secondAbc: Abc.E; +var secondAbcd: Abcd.E; +var secondAb: Ab.E; +var secondCd: Cd.E; +var nope: Abc.Nope; +abc = secondAbc; // ok +abc = secondAbcd; // missing 'd' +abc = secondAb; // ok +abc = secondCd; // missing 'd' +abc = nope; // nope! +secondAbc = abc; // ok +secondAbcd = abc; // ok +secondAb = abc; // missing 'c' +secondCd = abc; // missing 'a' and 'b' +nope = abc; // nope! + + +//// [enumAssignmentCompat3.js] +var First; +(function (First) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + E[E["c"] = 2] = "c"; + })(First.E || (First.E = {})); + var E = First.E; +})(First || (First = {})); +var Abc; +(function (Abc) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + E[E["c"] = 2] = "c"; + })(Abc.E || (Abc.E = {})); + var E = Abc.E; + (function (Nope) { + Nope[Nope["a"] = 0] = "a"; + Nope[Nope["b"] = 1] = "b"; + Nope[Nope["c"] = 2] = "c"; + })(Abc.Nope || (Abc.Nope = {})); + var Nope = Abc.Nope; +})(Abc || (Abc = {})); +var Abcd; +(function (Abcd) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + E[E["c"] = 2] = "c"; + E[E["d"] = 3] = "d"; + })(Abcd.E || (Abcd.E = {})); + var E = Abcd.E; +})(Abcd || (Abcd = {})); +var Ab; +(function (Ab) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + })(Ab.E || (Ab.E = {})); + var E = Ab.E; +})(Ab || (Ab = {})); +var Cd; +(function (Cd) { + (function (E) { + E[E["c"] = 0] = "c"; + E[E["d"] = 1] = "d"; + })(Cd.E || (Cd.E = {})); + var E = Cd.E; +})(Cd || (Cd = {})); +var abc; +var secondAbc; +var secondAbcd; +var secondAb; +var secondCd; +var nope; +abc = secondAbc; // ok +abc = secondAbcd; // missing 'd' +abc = secondAb; // ok +abc = secondCd; // missing 'd' +abc = nope; // nope! +secondAbc = abc; // ok +secondAbcd = abc; // ok +secondAb = abc; // missing 'c' +secondCd = abc; // missing 'a' and 'b' +nope = abc; // nope! diff --git a/tests/cases/compiler/enumAssignmentCompat3.ts b/tests/cases/compiler/enumAssignmentCompat3.ts new file mode 100644 index 0000000000000..94a22c7f3465a --- /dev/null +++ b/tests/cases/compiler/enumAssignmentCompat3.ts @@ -0,0 +1,45 @@ +namespace First { + export enum E { + a, b, c, + } +} +namespace Abc { + export enum E { + a, b, c, + } + export enum Nope { + a, b, c, + } +} +namespace Abcd { + export enum E { + a, b, c, d, + } +} +namespace Ab { + export enum E { + a, b, + } +} +namespace Cd { + export enum E { + c, d, + } +} + +var abc: First.E; +var secondAbc: Abc.E; +var secondAbcd: Abcd.E; +var secondAb: Ab.E; +var secondCd: Cd.E; +var nope: Abc.Nope; +abc = secondAbc; // ok +abc = secondAbcd; // missing 'd' +abc = secondAb; // ok +abc = secondCd; // missing 'd' +abc = nope; // nope! +secondAbc = abc; // ok +secondAbcd = abc; // ok +secondAb = abc; // missing 'c' +secondCd = abc; // missing 'a' and 'b' +nope = abc; // nope! From cc1d8cf395eebdf5e1f6e2f9ddb90111fbad95b7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 13:47:18 -0800 Subject: [PATCH 03/12] Address review comments --- src/compiler/checker.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0f04daf29830a..857fa97ca06a6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5757,15 +5757,17 @@ namespace ts { } function enumRelatedTo(source: Type, target: Type) { - if (source.symbol.name !== target.symbol.name) { + if (source.symbol.name !== target.symbol.name || + source.symbol.flags & SymbolFlags.ConstEnum || + target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } - const sourceDecl = getMergedSymbol(source.symbol).valueDeclaration; - const targetDecl = getMergedSymbol(target.symbol).valueDeclaration; + const sourceDecl = getDeclarationOfKind(source.symbol, SyntaxKind.EnumDeclaration); + const targetDecl = getDeclarationOfKind(target.symbol, SyntaxKind.EnumDeclaration); const targetMembers = arrayToMap(targetDecl.members, member => getTextOfPropertyName(member.name)); for (const member of sourceDecl.members) { const name = getTextOfPropertyName(member.name); - if (!targetMembers[name]) { + if (!hasProperty(targetMembers, name)) { reportError(Diagnostics.Property_0_is_missing_in_type_1, name, typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); From ff0138878ddbe5823df3d37073e875758f23ec18 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 13:47:31 -0800 Subject: [PATCH 04/12] Add tests from review --- .../enumAssignmentCompat3.errors.txt | 38 +++++++++++++++---- .../reference/enumAssignmentCompat3.js | 28 ++++++++++++++ tests/cases/compiler/enumAssignmentCompat3.ts | 18 +++++++++ 3 files changed, 77 insertions(+), 7 deletions(-) diff --git a/tests/baselines/reference/enumAssignmentCompat3.errors.txt b/tests/baselines/reference/enumAssignmentCompat3.errors.txt index d82a4b7d490b9..b9ab92adec148 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.errors.txt +++ b/tests/baselines/reference/enumAssignmentCompat3.errors.txt @@ -1,16 +1,18 @@ -tests/cases/compiler/enumAssignmentCompat3.ts(37,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(49,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. Property 'd' is missing in type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(39,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(51,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. Property 'd' is missing in type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(40,1): error TS2322: Type 'Nope' is not assignable to type 'E'. -tests/cases/compiler/enumAssignmentCompat3.ts(43,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(52,1): error TS2322: Type 'Nope' is not assignable to type 'E'. +tests/cases/compiler/enumAssignmentCompat3.ts(56,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. Property 'c' is missing in type 'Ab.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(44,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(57,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. Property 'a' is missing in type 'Cd.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(45,1): error TS2322: Type 'E' is not assignable to type 'Nope'. +tests/cases/compiler/enumAssignmentCompat3.ts(58,1): error TS2322: Type 'E' is not assignable to type 'Nope'. +tests/cases/compiler/enumAssignmentCompat3.ts(62,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(63,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'. -==== tests/cases/compiler/enumAssignmentCompat3.ts (6 errors) ==== +==== tests/cases/compiler/enumAssignmentCompat3.ts (8 errors) ==== namespace First { export enum E { a, b, c, @@ -39,6 +41,16 @@ tests/cases/compiler/enumAssignmentCompat3.ts(45,1): error TS2322: Type 'E' is n c, d, } } + namespace Const { + export const enum E { + a, b, c, + } + } + namespace Decl { + export declare enum E { + a, b, c = 3, + } + } var abc: First.E; var secondAbc: Abc.E; @@ -46,6 +58,8 @@ tests/cases/compiler/enumAssignmentCompat3.ts(45,1): error TS2322: Type 'E' is n var secondAb: Ab.E; var secondCd: Cd.E; var nope: Abc.Nope; + var k: Const.E; + var decl: Decl.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' ~~~ @@ -59,6 +73,7 @@ tests/cases/compiler/enumAssignmentCompat3.ts(45,1): error TS2322: Type 'E' is n abc = nope; // nope! ~~~ !!! error TS2322: Type 'Nope' is not assignable to type 'E'. + abc = decl; // ok secondAbc = abc; // ok secondAbcd = abc; // ok secondAb = abc; // missing 'c' @@ -72,4 +87,13 @@ tests/cases/compiler/enumAssignmentCompat3.ts(45,1): error TS2322: Type 'E' is n nope = abc; // nope! ~~~~ !!! error TS2322: Type 'E' is not assignable to type 'Nope'. + decl = abc; // ok + + k = k; // const is only assignable to itself + abc = k; // error + ~~~ +!!! error TS2322: Type 'Const.E' is not assignable to type 'First.E'. + k = abc; + ~ +!!! error TS2322: Type 'First.E' is not assignable to type 'Const.E'. \ No newline at end of file diff --git a/tests/baselines/reference/enumAssignmentCompat3.js b/tests/baselines/reference/enumAssignmentCompat3.js index 33cfdd28e888d..1173bfa1812f5 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.js +++ b/tests/baselines/reference/enumAssignmentCompat3.js @@ -27,6 +27,16 @@ namespace Cd { c, d, } } +namespace Const { + export const enum E { + a, b, c, + } +} +namespace Decl { + export declare enum E { + a, b, c = 3, + } +} var abc: First.E; var secondAbc: Abc.E; @@ -34,16 +44,24 @@ var secondAbcd: Abcd.E; var secondAb: Ab.E; var secondCd: Cd.E; var nope: Abc.Nope; +var k: Const.E; +var decl: Decl.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok abc = secondCd; // missing 'd' abc = nope; // nope! +abc = decl; // ok secondAbc = abc; // ok secondAbcd = abc; // ok secondAb = abc; // missing 'c' secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! +decl = abc; // ok + +k = k; // const is only assignable to itself +abc = k; // error +k = abc; //// [enumAssignmentCompat3.js] @@ -97,19 +115,29 @@ var Cd; })(Cd.E || (Cd.E = {})); var E = Cd.E; })(Cd || (Cd = {})); +var Decl; +(function (Decl) { +})(Decl || (Decl = {})); var abc; var secondAbc; var secondAbcd; var secondAb; var secondCd; var nope; +var k; +var decl; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok abc = secondCd; // missing 'd' abc = nope; // nope! +abc = decl; // ok secondAbc = abc; // ok secondAbcd = abc; // ok secondAb = abc; // missing 'c' secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! +decl = abc; // ok +k = k; // const is only assignable to itself +abc = k; // error +k = abc; diff --git a/tests/cases/compiler/enumAssignmentCompat3.ts b/tests/cases/compiler/enumAssignmentCompat3.ts index 94a22c7f3465a..aaaf96b69c8e8 100644 --- a/tests/cases/compiler/enumAssignmentCompat3.ts +++ b/tests/cases/compiler/enumAssignmentCompat3.ts @@ -26,6 +26,16 @@ namespace Cd { c, d, } } +namespace Const { + export const enum E { + a, b, c, + } +} +namespace Decl { + export declare enum E { + a, b, c = 3, + } +} var abc: First.E; var secondAbc: Abc.E; @@ -33,13 +43,21 @@ var secondAbcd: Abcd.E; var secondAb: Ab.E; var secondCd: Cd.E; var nope: Abc.Nope; +var k: Const.E; +var decl: Decl.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok abc = secondCd; // missing 'd' abc = nope; // nope! +abc = decl; // ok secondAbc = abc; // ok secondAbcd = abc; // ok secondAb = abc; // missing 'c' secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! +decl = abc; // ok + +k = k; // const is only assignable to itself +abc = k; // error +k = abc; From a995b23e4a00e252de81cdf0d1685700314eefa6 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 14:28:29 -0800 Subject: [PATCH 05/12] Handle merged enums --- src/compiler/checker.ts | 23 ++++++++++++++++++----- src/compiler/utilities.ts | 15 +++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 857fa97ca06a6..2fb0296c1c7be 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5762,12 +5762,11 @@ namespace ts { target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } - const sourceDecl = getDeclarationOfKind(source.symbol, SyntaxKind.EnumDeclaration); - const targetDecl = getDeclarationOfKind(target.symbol, SyntaxKind.EnumDeclaration); - const targetMembers = arrayToMap(targetDecl.members, member => getTextOfPropertyName(member.name)); - for (const member of sourceDecl.members) { + const targetMembers = getEnumMembers(target.symbol); + const targetNames = arrayToMap(targetMembers, member => getTextOfPropertyName(member.name)); + for (const member of getEnumMembers(source.symbol)) { const name = getTextOfPropertyName(member.name); - if (!hasProperty(targetMembers, name)) { + if (!hasProperty(targetNames, name)) { reportError(Diagnostics.Property_0_is_missing_in_type_1, name, typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); @@ -5778,6 +5777,20 @@ namespace ts { } } + function getEnumMembers(symbol: Symbol): EnumMember[] { + const declarations = getDeclarationsOfKind(symbol, SyntaxKind.EnumDeclaration); + if (!declarations) { + return emptyArray; + } + const members: EnumMember[] = []; + for (const declaration of declarations) { + for (const member of (declaration).members) { + members.push(member); + } + } + return members; + } + // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case // when structural type comparisons have been started for 10 or more instantiations of the same generic type. It is possible, // though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely expanding. diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 95bf4ff7fa32b..24e2149ab3e13 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -27,6 +27,21 @@ namespace ts { return undefined; } + export function getDeclarationsOfKind(symbol: Symbol, kind: SyntaxKind): Declaration[] { + const declarations = symbol.declarations; + if (declarations) { + const declarationsOfKind: Declaration[] = []; + for (const declaration of declarations) { + if (declaration.kind === kind) { + declarationsOfKind.push(declaration); + } + } + return declarationsOfKind; + } + + return undefined; + } + export interface StringSymbolWriter extends SymbolWriter { string(): string; } From 75304096959652551cdeed4140753f44940e45b6 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 14:28:46 -0800 Subject: [PATCH 06/12] Add merged enum test --- .../enumAssignmentCompat3.errors.txt | 40 ++++++++++++++----- .../reference/enumAssignmentCompat3.js | 37 +++++++++++++++-- tests/cases/compiler/enumAssignmentCompat3.ts | 16 +++++++- 3 files changed, 78 insertions(+), 15 deletions(-) diff --git a/tests/baselines/reference/enumAssignmentCompat3.errors.txt b/tests/baselines/reference/enumAssignmentCompat3.errors.txt index b9ab92adec148..c34ad434347ea 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.errors.txt +++ b/tests/baselines/reference/enumAssignmentCompat3.errors.txt @@ -1,18 +1,20 @@ -tests/cases/compiler/enumAssignmentCompat3.ts(49,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(58,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. Property 'd' is missing in type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(51,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(60,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. Property 'd' is missing in type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(52,1): error TS2322: Type 'Nope' is not assignable to type 'E'. -tests/cases/compiler/enumAssignmentCompat3.ts(56,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(61,1): error TS2322: Type 'Nope' is not assignable to type 'E'. +tests/cases/compiler/enumAssignmentCompat3.ts(65,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. Property 'c' is missing in type 'Ab.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(57,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(66,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. Property 'a' is missing in type 'Cd.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(58,1): error TS2322: Type 'E' is not assignable to type 'Nope'. -tests/cases/compiler/enumAssignmentCompat3.ts(62,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(63,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(67,1): error TS2322: Type 'E' is not assignable to type 'Nope'. +tests/cases/compiler/enumAssignmentCompat3.ts(72,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(73,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'Merged.E' is not assignable to type 'First.E'. + Property 'd' is missing in type 'First.E'. -==== tests/cases/compiler/enumAssignmentCompat3.ts (8 errors) ==== +==== tests/cases/compiler/enumAssignmentCompat3.ts (9 errors) ==== namespace First { export enum E { a, b, c, @@ -51,6 +53,14 @@ tests/cases/compiler/enumAssignmentCompat3.ts(63,1): error TS2322: Type 'First.E a, b, c = 3, } } + namespace Merged { + export enum E { + a, b, + } + export enum E { + c = 3, d, + } + } var abc: First.E; var secondAbc: Abc.E; @@ -60,6 +70,7 @@ tests/cases/compiler/enumAssignmentCompat3.ts(63,1): error TS2322: Type 'First.E var nope: Abc.Nope; var k: Const.E; var decl: Decl.E; + var merged: Merged.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' ~~~ @@ -89,11 +100,18 @@ tests/cases/compiler/enumAssignmentCompat3.ts(63,1): error TS2322: Type 'First.E !!! error TS2322: Type 'E' is not assignable to type 'Nope'. decl = abc; // ok - k = k; // const is only assignable to itself + // const is only assignable to itself + k = k; abc = k; // error ~~~ !!! error TS2322: Type 'Const.E' is not assignable to type 'First.E'. k = abc; ~ !!! error TS2322: Type 'First.E' is not assignable to type 'Const.E'. - \ No newline at end of file + + // merged enums compare all their members + abc = merged; // missing 'd' + ~~~ +!!! error TS2322: Type 'Merged.E' is not assignable to type 'First.E'. +!!! error TS2322: Property 'd' is missing in type 'First.E'. + merged = abc; // ok \ No newline at end of file diff --git a/tests/baselines/reference/enumAssignmentCompat3.js b/tests/baselines/reference/enumAssignmentCompat3.js index 1173bfa1812f5..e43874911ce63 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.js +++ b/tests/baselines/reference/enumAssignmentCompat3.js @@ -37,6 +37,14 @@ namespace Decl { a, b, c = 3, } } +namespace Merged { + export enum E { + a, b, + } + export enum E { + c = 3, d, + } +} var abc: First.E; var secondAbc: Abc.E; @@ -46,6 +54,7 @@ var secondCd: Cd.E; var nope: Abc.Nope; var k: Const.E; var decl: Decl.E; +var merged: Merged.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -59,10 +68,14 @@ secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! decl = abc; // ok -k = k; // const is only assignable to itself +// const is only assignable to itself +k = k; abc = k; // error k = abc; - + +// merged enums compare all their members +abc = merged; // missing 'd' +merged = abc; // ok //// [enumAssignmentCompat3.js] var First; @@ -118,6 +131,19 @@ var Cd; var Decl; (function (Decl) { })(Decl || (Decl = {})); +var Merged; +(function (Merged) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + })(Merged.E || (Merged.E = {})); + var E = Merged.E; + (function (E) { + E[E["c"] = 3] = "c"; + E[E["d"] = 4] = "d"; + })(Merged.E || (Merged.E = {})); + var E = Merged.E; +})(Merged || (Merged = {})); var abc; var secondAbc; var secondAbcd; @@ -126,6 +152,7 @@ var secondCd; var nope; var k; var decl; +var merged; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -138,6 +165,10 @@ secondAb = abc; // missing 'c' secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! decl = abc; // ok -k = k; // const is only assignable to itself +// const is only assignable to itself +k = k; abc = k; // error k = abc; +// merged enums compare all their members +abc = merged; // missing 'd' +merged = abc; // ok diff --git a/tests/cases/compiler/enumAssignmentCompat3.ts b/tests/cases/compiler/enumAssignmentCompat3.ts index aaaf96b69c8e8..33070572661f2 100644 --- a/tests/cases/compiler/enumAssignmentCompat3.ts +++ b/tests/cases/compiler/enumAssignmentCompat3.ts @@ -36,6 +36,14 @@ namespace Decl { a, b, c = 3, } } +namespace Merged { + export enum E { + a, b, + } + export enum E { + c = 3, d, + } +} var abc: First.E; var secondAbc: Abc.E; @@ -45,6 +53,7 @@ var secondCd: Cd.E; var nope: Abc.Nope; var k: Const.E; var decl: Decl.E; +var merged: Merged.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -58,6 +67,11 @@ secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! decl = abc; // ok -k = k; // const is only assignable to itself +// const is only assignable to itself +k = k; abc = k; // error k = abc; + +// merged enums compare all their members +abc = merged; // missing 'd' +merged = abc; // ok \ No newline at end of file From da8e19e191ef508d18f400db62c9297e44002da7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 15:25:01 -0800 Subject: [PATCH 07/12] Use typeof enum to resolve members. Use getTypeOfSymbol >> resolveStructuredTypeMembers >> properties instead of looking at declarations. --- src/compiler/checker.ts | 26 ++++++-------------------- src/compiler/utilities.ts | 15 --------------- 2 files changed, 6 insertions(+), 35 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2fb0296c1c7be..bccbede909ba0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5762,13 +5762,13 @@ namespace ts { target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } - const targetMembers = getEnumMembers(target.symbol); - const targetNames = arrayToMap(targetMembers, member => getTextOfPropertyName(member.name)); - for (const member of getEnumMembers(source.symbol)) { - const name = getTextOfPropertyName(member.name); - if (!hasProperty(targetNames, name)) { + const sourceMembers = resolveStructuredTypeMembers(getTypeOfSymbol(source.symbol)).properties; + const targetMembers = resolveStructuredTypeMembers(getTypeOfSymbol(target.symbol)).properties; + const targetNames = arrayToMap(targetMembers, member => member.name); + for (const member of sourceMembers) { + if (!hasProperty(targetNames, member.name)) { reportError(Diagnostics.Property_0_is_missing_in_type_1, - name, + member.name, typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); return Ternary.False; } @@ -5777,20 +5777,6 @@ namespace ts { } } - function getEnumMembers(symbol: Symbol): EnumMember[] { - const declarations = getDeclarationsOfKind(symbol, SyntaxKind.EnumDeclaration); - if (!declarations) { - return emptyArray; - } - const members: EnumMember[] = []; - for (const declaration of declarations) { - for (const member of (declaration).members) { - members.push(member); - } - } - return members; - } - // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case // when structural type comparisons have been started for 10 or more instantiations of the same generic type. It is possible, // though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely expanding. diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 24e2149ab3e13..95bf4ff7fa32b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -27,21 +27,6 @@ namespace ts { return undefined; } - export function getDeclarationsOfKind(symbol: Symbol, kind: SyntaxKind): Declaration[] { - const declarations = symbol.declarations; - if (declarations) { - const declarationsOfKind: Declaration[] = []; - for (const declaration of declarations) { - if (declaration.kind === kind) { - declarationsOfKind.push(declaration); - } - } - return declarationsOfKind; - } - - return undefined; - } - export interface StringSymbolWriter extends SymbolWriter { string(): string; } From 8202576ab2d503258dbd18b7ebc1035607ebd173 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 11 Dec 2015 09:56:13 -0800 Subject: [PATCH 08/12] Filter for enum members only. --- src/compiler/checker.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bccbede909ba0..9944cebf54a47 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5762,10 +5762,8 @@ namespace ts { target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } - const sourceMembers = resolveStructuredTypeMembers(getTypeOfSymbol(source.symbol)).properties; - const targetMembers = resolveStructuredTypeMembers(getTypeOfSymbol(target.symbol)).properties; - const targetNames = arrayToMap(targetMembers, member => member.name); - for (const member of sourceMembers) { + const targetNames = arrayToMap(getEnumMembersOfEnumType(target), member => member.name); + for (const member of getEnumMembersOfEnumType(source)) { if (!hasProperty(targetNames, member.name)) { reportError(Diagnostics.Property_0_is_missing_in_type_1, member.name, @@ -5775,6 +5773,11 @@ namespace ts { } return Ternary.True; } + + function getEnumMembersOfEnumType(type: Type) { + return filter(resolveStructuredTypeMembers(getTypeOfSymbol(type.symbol)).properties, + property => !!(property.flags & SymbolFlags.EnumMember)); + } } // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case From dc9d307f137dc2a7b812cea42aac6927711b419a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 11 Dec 2015 10:08:01 -0800 Subject: [PATCH 09/12] Fix lint --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9944cebf54a47..8d9fe1f7ba50a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5775,7 +5775,7 @@ namespace ts { } function getEnumMembersOfEnumType(type: Type) { - return filter(resolveStructuredTypeMembers(getTypeOfSymbol(type.symbol)).properties, + return filter(resolveStructuredTypeMembers(getTypeOfSymbol(type.symbol)).properties, property => !!(property.flags & SymbolFlags.EnumMember)); } } From aa1a7664e73c444a5c9ecf147d85b856f94eee79 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 16 Dec 2015 12:11:24 -0800 Subject: [PATCH 10/12] Add enum/module merge test --- .../enumAssignmentCompat3.errors.txt | 32 +++++++++++++------ .../reference/enumAssignmentCompat3.js | 30 ++++++++++++++++- tests/cases/compiler/enumAssignmentCompat3.ts | 14 +++++++- 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/tests/baselines/reference/enumAssignmentCompat3.errors.txt b/tests/baselines/reference/enumAssignmentCompat3.errors.txt index c34ad434347ea..02cb4314777f9 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.errors.txt +++ b/tests/baselines/reference/enumAssignmentCompat3.errors.txt @@ -1,16 +1,16 @@ -tests/cases/compiler/enumAssignmentCompat3.ts(58,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(68,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. Property 'd' is missing in type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(60,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(70,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. Property 'd' is missing in type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(61,1): error TS2322: Type 'Nope' is not assignable to type 'E'. -tests/cases/compiler/enumAssignmentCompat3.ts(65,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(71,1): error TS2322: Type 'Nope' is not assignable to type 'E'. +tests/cases/compiler/enumAssignmentCompat3.ts(75,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. Property 'c' is missing in type 'Ab.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(66,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. Property 'a' is missing in type 'Cd.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(67,1): error TS2322: Type 'E' is not assignable to type 'Nope'. -tests/cases/compiler/enumAssignmentCompat3.ts(72,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(73,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'Merged.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(77,1): error TS2322: Type 'E' is not assignable to type 'Nope'. +tests/cases/compiler/enumAssignmentCompat3.ts(82,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(83,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(86,1): error TS2322: Type 'Merged.E' is not assignable to type 'First.E'. Property 'd' is missing in type 'First.E'. @@ -62,6 +62,15 @@ tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'Merged. } } + namespace Merged2 { + export enum E { + a, b, c + } + export module E { + export let d = 5; + } + } + var abc: First.E; var secondAbc: Abc.E; var secondAbcd: Abcd.E; @@ -71,6 +80,7 @@ tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'Merged. var k: Const.E; var decl: Decl.E; var merged: Merged.E; + var merged2: Merged2.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' ~~~ @@ -114,4 +124,6 @@ tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'Merged. ~~~ !!! error TS2322: Type 'Merged.E' is not assignable to type 'First.E'. !!! error TS2322: Property 'd' is missing in type 'First.E'. - merged = abc; // ok \ No newline at end of file + merged = abc; // ok + abc = merged2; // ok + merged2 = abc; // ok \ No newline at end of file diff --git a/tests/baselines/reference/enumAssignmentCompat3.js b/tests/baselines/reference/enumAssignmentCompat3.js index e43874911ce63..74f74ab165280 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.js +++ b/tests/baselines/reference/enumAssignmentCompat3.js @@ -46,6 +46,15 @@ namespace Merged { } } +namespace Merged2 { + export enum E { + a, b, c + } + export module E { + export let d = 5; + } +} + var abc: First.E; var secondAbc: Abc.E; var secondAbcd: Abcd.E; @@ -55,6 +64,7 @@ var nope: Abc.Nope; var k: Const.E; var decl: Decl.E; var merged: Merged.E; +var merged2: Merged2.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -75,7 +85,9 @@ k = abc; // merged enums compare all their members abc = merged; // missing 'd' -merged = abc; // ok +merged = abc; // ok +abc = merged2; // ok +merged2 = abc; // ok //// [enumAssignmentCompat3.js] var First; @@ -144,6 +156,19 @@ var Merged; })(Merged.E || (Merged.E = {})); var E = Merged.E; })(Merged || (Merged = {})); +var Merged2; +(function (Merged2) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + E[E["c"] = 2] = "c"; + })(Merged2.E || (Merged2.E = {})); + var E = Merged2.E; + var E; + (function (E) { + E.d = 5; + })(E = Merged2.E || (Merged2.E = {})); +})(Merged2 || (Merged2 = {})); var abc; var secondAbc; var secondAbcd; @@ -153,6 +178,7 @@ var nope; var k; var decl; var merged; +var merged2; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -172,3 +198,5 @@ k = abc; // merged enums compare all their members abc = merged; // missing 'd' merged = abc; // ok +abc = merged2; // ok +merged2 = abc; // ok diff --git a/tests/cases/compiler/enumAssignmentCompat3.ts b/tests/cases/compiler/enumAssignmentCompat3.ts index 33070572661f2..97a136468e3ee 100644 --- a/tests/cases/compiler/enumAssignmentCompat3.ts +++ b/tests/cases/compiler/enumAssignmentCompat3.ts @@ -45,6 +45,15 @@ namespace Merged { } } +namespace Merged2 { + export enum E { + a, b, c + } + export module E { + export let d = 5; + } +} + var abc: First.E; var secondAbc: Abc.E; var secondAbcd: Abcd.E; @@ -54,6 +63,7 @@ var nope: Abc.Nope; var k: Const.E; var decl: Decl.E; var merged: Merged.E; +var merged2: Merged2.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -74,4 +84,6 @@ k = abc; // merged enums compare all their members abc = merged; // missing 'd' -merged = abc; // ok \ No newline at end of file +merged = abc; // ok +abc = merged2; // ok +merged2 = abc; // ok \ No newline at end of file From d59831b4e86b102a28ca045ee0a61778873df1c8 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 17 Dec 2015 15:38:02 -0800 Subject: [PATCH 11/12] Get rid of list and map abstractions to reduce GC pressure --- src/compiler/checker.ts | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8d9fe1f7ba50a..488549cb18048 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5762,22 +5762,19 @@ namespace ts { target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } - const targetNames = arrayToMap(getEnumMembersOfEnumType(target), member => member.name); - for (const member of getEnumMembersOfEnumType(source)) { - if (!hasProperty(targetNames, member.name)) { - reportError(Diagnostics.Property_0_is_missing_in_type_1, - member.name, - typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); - return Ternary.False; + for (const property of getPropertiesOfType(getTypeOfSymbol(source.symbol))) { + if (property.flags & SymbolFlags.EnumMember) { + const targetProperty = getPropertyOfType(getTypeOfSymbol(target.symbol), property.name); + if (!targetProperty || !(targetProperty.flags & SymbolFlags.EnumMember)) { + reportError(Diagnostics.Property_0_is_missing_in_type_1, + property.name, + typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); + return Ternary.False; + } } } return Ternary.True; } - - function getEnumMembersOfEnumType(type: Type) { - return filter(resolveStructuredTypeMembers(getTypeOfSymbol(type.symbol)).properties, - property => !!(property.flags & SymbolFlags.EnumMember)); - } } // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case From b04bd66bb2a11ddfe7a7c17d35ea87ea4e9160cb Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 17 Dec 2015 16:18:55 -0800 Subject: [PATCH 12/12] Get type of target enum outside the lookup loop --- src/compiler/checker.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 488549cb18048..f65a10b266a60 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5762,9 +5762,10 @@ namespace ts { target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } + const targetEnumType = getTypeOfSymbol(target.symbol); for (const property of getPropertiesOfType(getTypeOfSymbol(source.symbol))) { if (property.flags & SymbolFlags.EnumMember) { - const targetProperty = getPropertyOfType(getTypeOfSymbol(target.symbol), property.name); + const targetProperty = getPropertyOfType(targetEnumType, property.name); if (!targetProperty || !(targetProperty.flags & SymbolFlags.EnumMember)) { reportError(Diagnostics.Property_0_is_missing_in_type_1, property.name,