From bcf73a8207db16ae281cf87b1ec88b8b5a94d5dd Mon Sep 17 00:00:00 2001 From: Yui T Date: Mon, 15 Dec 2014 15:26:08 -0800 Subject: [PATCH] Move grammar checking: enumDeclaration; there are still erros from incomplete grammar migration --- src/compiler/checker.ts | 54 +++++++++++++++++++ src/compiler/parser.ts | 2 +- .../reference/ambientErrors.errors.txt | 4 +- 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a77da719e52..a259e3a5aa4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8779,6 +8779,9 @@ module ts { } function checkEnumDeclaration(node: EnumDeclaration) { + // Grammar checking + checkGrammarModifiers(node) || checkGrammarEnumDeclaration(node); + if (!fullTypeCheck) { return; } @@ -10382,6 +10385,57 @@ module ts { } } + function isIntegerLiteral(expression: Expression): boolean { + if (expression.kind === SyntaxKind.PrefixUnaryExpression) { + var unaryExpression = expression; + if (unaryExpression.operator === SyntaxKind.PlusToken || unaryExpression.operator === SyntaxKind.MinusToken) { + expression = unaryExpression.operand; + } + } + if (expression.kind === SyntaxKind.NumericLiteral) { + // Allows for scientific notation since literalExpression.text was formed by + // coercing a number to a string. Sometimes this coercion can yield a string + // in scientific notation. + // We also don't need special logic for hex because a hex integer is converted + // to decimal when it is coerced. + return /^[0-9]+([eE]\+?[0-9]+)?$/.test((expression).text); + } + + return false; + } + + function checkGrammarEnumDeclaration(enumDecl: EnumDeclaration): boolean { + var enumIsConst = (enumDecl.flags & NodeFlags.Const) !== 0; + + var hasError = false; + + // skip checks below for const enums - they allow arbitrary initializers as long as they can be evaluated to constant expressions. + // since all values are known in compile time - it is not necessary to check that constant enum section precedes computed enum members. + if (!enumIsConst) { + var inConstantEnumMemberSection = true; + var inAmbientContext = isInAmbientContext(enumDecl); + for (var i = 0, n = enumDecl.members.length; i < n; i++) { + var node = enumDecl.members[i]; + if (node.name.kind === SyntaxKind.ComputedPropertyName) { + hasError = grammarErrorOnNode(node.name, Diagnostics.Computed_property_names_are_not_allowed_in_enums); + } + else if (inAmbientContext) { + if (node.initializer && !isIntegerLiteral(node.initializer)) { + hasError = grammarErrorOnNode(node.name, Diagnostics.Ambient_enum_elements_can_only_have_integer_literal_initializers) || hasError; + } + } + else if (node.initializer) { + inConstantEnumMemberSection = isIntegerLiteral(node.initializer); + } + else if (!inConstantEnumMemberSection) { + hasError = grammarErrorOnNode(node.name, Diagnostics.Enum_member_must_have_initializer) || hasError; + } + } + } + + return hasError; + } + function hasParseDiagnostics(sourceFile: SourceFile): boolean { return sourceFile.parseDiagnostics.length > 0; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b2fbe11fcb5..c823469c7a0 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4633,7 +4633,7 @@ module ts { //case SyntaxKind.NewExpression: //return checkCallOrNewExpression(node); - case SyntaxKind.EnumDeclaration: return checkEnumDeclaration(node); + //case SyntaxKind.EnumDeclaration: return checkEnumDeclaration(node); //case SyntaxKind.BinaryExpression: return checkBinaryExpression(node); //case SyntaxKind.BindingElement: return checkBindingElement(node); //case SyntaxKind.CatchClause: return checkCatchClause(node); diff --git a/tests/baselines/reference/ambientErrors.errors.txt b/tests/baselines/reference/ambientErrors.errors.txt index 6fe7a25dfe9..834c35e541c 100644 --- a/tests/baselines/reference/ambientErrors.errors.txt +++ b/tests/baselines/reference/ambientErrors.errors.txt @@ -1,7 +1,5 @@ tests/cases/conformance/ambient/ambientErrors.ts(2,15): error TS1039: Initializers are not allowed in ambient contexts. tests/cases/conformance/ambient/ambientErrors.ts(20,24): error TS1037: A function implementation cannot be declared in an ambient context. -tests/cases/conformance/ambient/ambientErrors.ts(24,5): error TS1066: Ambient enum elements can only have integer literal initializers. -tests/cases/conformance/ambient/ambientErrors.ts(29,5): error TS1066: Ambient enum elements can only have integer literal initializers. tests/cases/conformance/ambient/ambientErrors.ts(34,11): error TS1039: Initializers are not allowed in ambient contexts. tests/cases/conformance/ambient/ambientErrors.ts(35,19): error TS1037: A function implementation cannot be declared in an ambient context. tests/cases/conformance/ambient/ambientErrors.ts(37,20): error TS1039: Initializers are not allowed in ambient contexts. @@ -11,6 +9,8 @@ tests/cases/conformance/ambient/ambientErrors.ts(40,14): error TS1037: A functio tests/cases/conformance/ambient/ambientErrors.ts(41,22): error TS1037: A function implementation cannot be declared in an ambient context. tests/cases/conformance/ambient/ambientErrors.ts(6,1): error TS2382: Specialized overload signature is not assignable to any non-specialized signature. tests/cases/conformance/ambient/ambientErrors.ts(17,22): error TS2371: A parameter initializer is only allowed in a function or constructor implementation. +tests/cases/conformance/ambient/ambientErrors.ts(24,5): error TS1066: Ambient enum elements can only have integer literal initializers. +tests/cases/conformance/ambient/ambientErrors.ts(29,5): error TS1066: Ambient enum elements can only have integer literal initializers. tests/cases/conformance/ambient/ambientErrors.ts(47,20): error TS2435: Ambient external modules cannot be nested in other modules. tests/cases/conformance/ambient/ambientErrors.ts(51,16): error TS2436: Ambient external module declaration cannot specify relative module name. tests/cases/conformance/ambient/ambientErrors.ts(57,5): error TS2309: An export assignment cannot be used in a module with other exported elements.