From 2cf51e4639af6722dbb8e41525c97a6fef5c4dde Mon Sep 17 00:00:00 2001 From: Yui T Date: Sat, 13 Dec 2014 13:55:16 -0800 Subject: [PATCH] Move grammar checking: objectLiteralExpression; there are still error from incomplete grammar migration --- src/compiler/checker.ts | 81 +++++++++++++++++-- src/compiler/parser.ts | 2 +- .../duplicateObjectLiteralProperty.errors.txt | 2 +- ...duplicatePropertiesInStrictMode.errors.txt | 2 +- .../twoAccessorsWithSameName.errors.txt | 2 +- 5 files changed, 78 insertions(+), 11 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7b99f32e839..513e47e0747 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5360,18 +5360,14 @@ module ts { } function checkObjectLiteral(node: ObjectLiteralExpression, contextualMapper?: TypeMapper): Type { + // Grammar checking + checkGrammarObjectLiteralExpression(node); + var members = node.symbol.members; var properties: SymbolTable = {}; var contextualType = getContextualType(node); var typeFlags: TypeFlags; - // Grammar checking for computedPropertyName - forEach(node.properties, property => { - if (property.name.kind === SyntaxKind.ComputedPropertyName) { - checkGrammarComputedPropertyName(property.name); - } - }); - for (var id in members) { if (hasProperty(members, id)) { var member = members[id]; @@ -10146,6 +10142,77 @@ module ts { } } + function checkGrammarObjectLiteralExpression(node: ObjectLiteralExpression) { + var seen: Map = {}; + var Property = 1; + var GetAccessor = 2; + var SetAccesor = 4; + var GetOrSetAccessor = GetAccessor | SetAccesor; + var inStrictMode = (node.parserContextFlags & ParserContextFlags.StrictMode) !== 0; + + for (var i = 0, n = node.properties.length; i < n; i++) { + var prop = node.properties[i]; + var name = prop.name; + if (prop.kind === SyntaxKind.OmittedExpression || name.kind === SyntaxKind.ComputedPropertyName) { + continue; + } + + // ECMA-262 11.1.5 Object Initialiser + // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true + // a.This production is contained in strict code and IsDataDescriptor(previous) is true and + // IsDataDescriptor(propId.descriptor) is true. + // b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true. + // c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true. + // d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true + // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields + var currentKind: number; + if (prop.kind === SyntaxKind.PropertyAssignment || + prop.kind === SyntaxKind.ShorthandPropertyAssignment || + prop.kind === SyntaxKind.MethodDeclaration) { + currentKind = Property; + } + else if (prop.kind === SyntaxKind.GetAccessor) { + currentKind = GetAccessor; + } + else if (prop.kind === SyntaxKind.SetAccessor) { + currentKind = SetAccesor; + } + else { + Debug.fail("Unexpected syntax kind:" + prop.kind); + } + + if (!hasProperty(seen, (name).text)) { + seen[(name).text] = currentKind; + } + else { + var existingKind = seen[(name).text]; + if (currentKind === Property && existingKind === Property) { + if (inStrictMode) { + grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode); + } + } + else if ((currentKind & GetOrSetAccessor) && (existingKind & GetOrSetAccessor)) { + if (existingKind !== GetOrSetAccessor && currentKind !== existingKind) { + seen[(name).text] = currentKind | existingKind; + } + else { + return grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name); + } + } + else { + return grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name); + } + } + } + + // Grammar checking for computedPropertName + forEach(node.properties, prop => { + if (prop.name.kind === SyntaxKind.ComputedPropertyName) { + checkGrammarComputedPropertyName(prop.name); + } + }); + } + function hasParseDiagnostics(sourceFile: SourceFile): boolean { return sourceFile.parseDiagnostics.length > 0; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 1674af935ca..a740c5f9cb4 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4657,7 +4657,7 @@ module ts { case SyntaxKind.MethodSignature: return checkMethod(node); case SyntaxKind.ModuleDeclaration: return checkModuleDeclaration(node); - case SyntaxKind.ObjectLiteralExpression: return checkObjectLiteralExpression(node); + //case SyntaxKind.ObjectLiteralExpression: return checkObjectLiteralExpression(node); case SyntaxKind.NumericLiteral: return checkNumericLiteral(node); case SyntaxKind.Parameter: return checkParameter(node); case SyntaxKind.PostfixUnaryExpression: return checkPostfixUnaryExpression(node); diff --git a/tests/baselines/reference/duplicateObjectLiteralProperty.errors.txt b/tests/baselines/reference/duplicateObjectLiteralProperty.errors.txt index 05dfdc82404..0dd5febe496 100644 --- a/tests/baselines/reference/duplicateObjectLiteralProperty.errors.txt +++ b/tests/baselines/reference/duplicateObjectLiteralProperty.errors.txt @@ -1,4 +1,3 @@ -tests/cases/compiler/duplicateObjectLiteralProperty.ts(16,9): error TS1118: An object literal cannot have multiple get/set accessors with the same name. tests/cases/compiler/duplicateObjectLiteralProperty.ts(2,5): error TS2300: Duplicate identifier 'a'. tests/cases/compiler/duplicateObjectLiteralProperty.ts(4,5): error TS2300: Duplicate identifier 'a'. tests/cases/compiler/duplicateObjectLiteralProperty.ts(5,5): error TS2300: Duplicate identifier '\u0061'. @@ -7,6 +6,7 @@ tests/cases/compiler/duplicateObjectLiteralProperty.ts(7,9): error TS2300: Dupli tests/cases/compiler/duplicateObjectLiteralProperty.ts(8,9): error TS2300: Duplicate identifier '"c"'. tests/cases/compiler/duplicateObjectLiteralProperty.ts(14,9): error TS2300: Duplicate identifier 'a'. tests/cases/compiler/duplicateObjectLiteralProperty.ts(15,9): error TS2300: Duplicate identifier 'a'. +tests/cases/compiler/duplicateObjectLiteralProperty.ts(16,9): error TS1118: An object literal cannot have multiple get/set accessors with the same name. tests/cases/compiler/duplicateObjectLiteralProperty.ts(16,9): error TS2300: Duplicate identifier 'a'. diff --git a/tests/baselines/reference/duplicatePropertiesInStrictMode.errors.txt b/tests/baselines/reference/duplicatePropertiesInStrictMode.errors.txt index 6ae8518677d..b3d868dbe7e 100644 --- a/tests/baselines/reference/duplicatePropertiesInStrictMode.errors.txt +++ b/tests/baselines/reference/duplicatePropertiesInStrictMode.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/duplicatePropertiesInStrictMode.ts(4,3): error TS1117: An object literal cannot have multiple properties with the same name in strict mode. tests/cases/compiler/duplicatePropertiesInStrictMode.ts(3,3): error TS2300: Duplicate identifier 'x'. +tests/cases/compiler/duplicatePropertiesInStrictMode.ts(4,3): error TS1117: An object literal cannot have multiple properties with the same name in strict mode. tests/cases/compiler/duplicatePropertiesInStrictMode.ts(4,3): error TS2300: Duplicate identifier 'x'. diff --git a/tests/baselines/reference/twoAccessorsWithSameName.errors.txt b/tests/baselines/reference/twoAccessorsWithSameName.errors.txt index 73261bfa072..2909db66af1 100644 --- a/tests/baselines/reference/twoAccessorsWithSameName.errors.txt +++ b/tests/baselines/reference/twoAccessorsWithSameName.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/classes/propertyMemberDeclarations/twoAccessorsWithSameName.ts(24,9): error TS1118: An object literal cannot have multiple get/set accessors with the same name. tests/cases/conformance/classes/propertyMemberDeclarations/twoAccessorsWithSameName.ts(2,9): error TS2300: Duplicate identifier 'x'. tests/cases/conformance/classes/propertyMemberDeclarations/twoAccessorsWithSameName.ts(3,9): error TS2300: Duplicate identifier 'x'. tests/cases/conformance/classes/propertyMemberDeclarations/twoAccessorsWithSameName.ts(7,9): error TS2300: Duplicate identifier 'x'. tests/cases/conformance/classes/propertyMemberDeclarations/twoAccessorsWithSameName.ts(8,9): error TS2300: Duplicate identifier 'x'. tests/cases/conformance/classes/propertyMemberDeclarations/twoAccessorsWithSameName.ts(19,9): error TS2300: Duplicate identifier 'x'. +tests/cases/conformance/classes/propertyMemberDeclarations/twoAccessorsWithSameName.ts(24,9): error TS1118: An object literal cannot have multiple get/set accessors with the same name. tests/cases/conformance/classes/propertyMemberDeclarations/twoAccessorsWithSameName.ts(24,9): error TS2300: Duplicate identifier 'x'.