From 5d46d434e0fc21b4533f1cd9f3c64648204d85b2 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Mon, 27 Feb 2017 11:21:12 -0800 Subject: [PATCH] Error when used enum before declaration --- src/compiler/checker.ts | 16 ++++++++++------ src/compiler/diagnosticMessages.json | 4 ++++ .../enumUsedBeforeDeclaration.errors.txt | 15 +++++++++++++++ .../reference/enumUsedBeforeDeclaration.js | 17 +++++++++++++++++ .../cases/compiler/enumUsedBeforeDeclaration.ts | 5 +++++ 5 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/enumUsedBeforeDeclaration.errors.txt create mode 100644 tests/baselines/reference/enumUsedBeforeDeclaration.js create mode 100644 tests/cases/compiler/enumUsedBeforeDeclaration.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 57905315d73..ca1ff705413 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1056,9 +1056,10 @@ namespace ts { // block-scoped variable and namespace module. However, only when we // try to resolve name in /*1*/ which is used in variable position, // we want to check for block-scoped - if (meaning & SymbolFlags.BlockScopedVariable || (meaning & SymbolFlags.Class && (meaning & SymbolFlags.Value) === SymbolFlags.Value)) { + if (meaning & SymbolFlags.BlockScopedVariable || + ((meaning & SymbolFlags.Class || meaning & SymbolFlags.Enum) && (meaning & SymbolFlags.Value) === SymbolFlags.Value)) { const exportOrLocalSymbol = getExportSymbolOfValueSymbolIfExported(result); - if (exportOrLocalSymbol.flags & SymbolFlags.BlockScopedVariable || exportOrLocalSymbol.flags & SymbolFlags.Class) { + if (exportOrLocalSymbol.flags & SymbolFlags.BlockScopedVariable || exportOrLocalSymbol.flags & SymbolFlags.Class || exportOrLocalSymbol.flags & SymbolFlags.Enum) { checkResolvedBlockScopedVariable(exportOrLocalSymbol, errorLocation); } } @@ -1171,19 +1172,22 @@ namespace ts { } function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void { - Debug.assert(!!(result.flags & SymbolFlags.BlockScopedVariable || result.flags & SymbolFlags.Class)); + Debug.assert(!!(result.flags & SymbolFlags.BlockScopedVariable || result.flags & SymbolFlags.Class || result.flags & SymbolFlags.Enum)); // Block-scoped variables cannot be used before their definition - const declaration = forEach(result.declarations, d => isBlockOrCatchScoped(d) || isClassLike(d) ? d : undefined); + const declaration = forEach(result.declarations, d => isBlockOrCatchScoped(d) || isClassLike(d) || (d.kind === SyntaxKind.EnumDeclaration) ? d : undefined); - Debug.assert(declaration !== undefined, "Block-scoped variable declaration is undefined"); + Debug.assert(declaration !== undefined, "Declaration to checkResolvedBlockScopedVariable is undefined"); if (!isInAmbientContext(declaration) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) { if (result.flags & SymbolFlags.BlockScopedVariable) { error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationNameToString(declaration.name)); } - else { + else if (result.flags & SymbolFlags.Class) { error(errorLocation, Diagnostics.Class_0_used_before_its_declaration, declarationNameToString(declaration.name)); } + else if (result.flags & SymbolFlags.Enum) { + error(errorLocation, Diagnostics.Enum_0_used_before_its_declaration, declarationNameToString(declaration.name)); + } } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 691f8e8d31b..24cd0c9e671 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1439,6 +1439,10 @@ "category": "Error", "code": 2449 }, + "Enum '{0}' used before its declaration.": { + "category": "Error", + "code": 2450 + }, "Cannot redeclare block-scoped variable '{0}'.": { "category": "Error", "code": 2451 diff --git a/tests/baselines/reference/enumUsedBeforeDeclaration.errors.txt b/tests/baselines/reference/enumUsedBeforeDeclaration.errors.txt new file mode 100644 index 00000000000..aea5366389b --- /dev/null +++ b/tests/baselines/reference/enumUsedBeforeDeclaration.errors.txt @@ -0,0 +1,15 @@ +tests/cases/compiler/enumUsedBeforeDeclaration.ts(1,18): error TS2450: Enum 'Color' used before its declaration. +tests/cases/compiler/enumUsedBeforeDeclaration.ts(2,24): error TS2450: Enum 'ConstColor' used before its declaration. + + +==== tests/cases/compiler/enumUsedBeforeDeclaration.ts (2 errors) ==== + const v: Color = Color.Green; + ~~~~~ +!!! error TS2450: Enum 'Color' used before its declaration. + const v2: ConstColor = ConstColor.Green; + ~~~~~~~~~~ +!!! error TS2450: Enum 'ConstColor' used before its declaration. + enum Color { Red, Green, Blue } + const enum ConstColor { Red, Green, Blue } + + \ No newline at end of file diff --git a/tests/baselines/reference/enumUsedBeforeDeclaration.js b/tests/baselines/reference/enumUsedBeforeDeclaration.js new file mode 100644 index 00000000000..63fc38471b2 --- /dev/null +++ b/tests/baselines/reference/enumUsedBeforeDeclaration.js @@ -0,0 +1,17 @@ +//// [enumUsedBeforeDeclaration.ts] +const v: Color = Color.Green; +const v2: ConstColor = ConstColor.Green; +enum Color { Red, Green, Blue } +const enum ConstColor { Red, Green, Blue } + + + +//// [enumUsedBeforeDeclaration.js] +var v = Color.Green; +var v2 = 1 /* Green */; +var Color; +(function (Color) { + Color[Color["Red"] = 0] = "Red"; + Color[Color["Green"] = 1] = "Green"; + Color[Color["Blue"] = 2] = "Blue"; +})(Color || (Color = {})); diff --git a/tests/cases/compiler/enumUsedBeforeDeclaration.ts b/tests/cases/compiler/enumUsedBeforeDeclaration.ts new file mode 100644 index 00000000000..98f5fca86f1 --- /dev/null +++ b/tests/cases/compiler/enumUsedBeforeDeclaration.ts @@ -0,0 +1,5 @@ +const v: Color = Color.Green; +const v2: ConstColor = ConstColor.Green; +enum Color { Red, Green, Blue } +const enum ConstColor { Red, Green, Blue } +