From d192fea774cda7b39bc56ee8e129f26a53d7b754 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Tue, 6 Jan 2015 15:17:07 -0800 Subject: [PATCH] Switch checkObjectLiteral to iterate over element declarations --- src/compiler/checker.ts | 78 +++++++++---------- .../lastPropertyInLiteralWins.errors.txt | 28 +++---- .../reference/memberOverride.errors.txt | 7 +- ...ypesInImplementationSignatures2.errors.txt | 5 +- 4 files changed, 55 insertions(+), 63 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9a3aa0d2fc3..a52a2765543 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5399,56 +5399,48 @@ module ts { // Grammar checking checkGrammarObjectLiteralExpression(node); - var members = node.symbol.members; var properties: SymbolTable = {}; var contextualType = getContextualType(node); var typeFlags: TypeFlags; - for (var id in members) { - if (hasProperty(members, id)) { - var member = members[id]; - if (member.flags & SymbolFlags.Property || isObjectLiteralMethod(member.declarations[0])) { - var memberDecl = member.declarations[0]; - if (memberDecl.kind === SyntaxKind.PropertyAssignment) { - var type = checkExpression((memberDecl).initializer, contextualMapper); - } - else if (memberDecl.kind === SyntaxKind.MethodDeclaration) { - var type = checkObjectLiteralMethod(memberDecl, contextualMapper); - } - else { - Debug.assert(memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment); - var type = memberDecl.name.kind === SyntaxKind.ComputedPropertyName - ? unknownType - : checkExpression(memberDecl.name, contextualMapper); - } - typeFlags |= type.flags; - var prop = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name); - prop.declarations = member.declarations; - prop.parent = member.parent; - if (member.valueDeclaration) { - prop.valueDeclaration = member.valueDeclaration; - } - - prop.type = type; - prop.target = member; - member = prop; + for (var i = 0; i < node.properties.length; i++) { + var memberDecl = node.properties[i]; + if (memberDecl.kind === SyntaxKind.PropertyAssignment || + memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment || + isObjectLiteralMethod(memberDecl)) { + if (memberDecl.kind === SyntaxKind.PropertyAssignment) { + var type = checkExpression((memberDecl).initializer, contextualMapper); + } + else if (memberDecl.kind === SyntaxKind.MethodDeclaration) { + var type = checkObjectLiteralMethod(memberDecl, contextualMapper); } else { - // TypeScript 1.0 spec (April 2014) - // A get accessor declaration is processed in the same manner as - // an ordinary function declaration(section 6.1) with no parameters. - // A set accessor declaration is processed in the same manner - // as an ordinary function declaration with a single parameter and a Void return type. - var getAccessor = getDeclarationOfKind(member, SyntaxKind.GetAccessor); - if (getAccessor) { - checkAccessorDeclaration(getAccessor); - } - - var setAccessor = getDeclarationOfKind(member, SyntaxKind.SetAccessor); - if (setAccessor) { - checkAccessorDeclaration(setAccessor); - } + Debug.assert(memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment); + var type = memberDecl.name.kind === SyntaxKind.ComputedPropertyName + ? unknownType + : checkExpression(memberDecl.name, contextualMapper); } + typeFlags |= type.flags; + var prop = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name); + var member = memberDecl.symbol; + prop.declarations = member.declarations; + prop.parent = member.parent; + if (member.valueDeclaration) { + prop.valueDeclaration = member.valueDeclaration; + } + + prop.type = type; + prop.target = member; + properties[prop.name] = prop; + } + else { + // TypeScript 1.0 spec (April 2014) + // A get accessor declaration is processed in the same manner as + // an ordinary function declaration(section 6.1) with no parameters. + // A set accessor declaration is processed in the same manner + // as an ordinary function declaration with a single parameter and a Void return type. + Debug.assert(memberDecl.kind === SyntaxKind.GetAccessor || memberDecl.kind === SyntaxKind.SetAccessor); + checkAccessorDeclaration(memberDecl); properties[member.name] = member; } } diff --git a/tests/baselines/reference/lastPropertyInLiteralWins.errors.txt b/tests/baselines/reference/lastPropertyInLiteralWins.errors.txt index 4bf5521d24d..d503f59c602 100644 --- a/tests/baselines/reference/lastPropertyInLiteralWins.errors.txt +++ b/tests/baselines/reference/lastPropertyInLiteralWins.errors.txt @@ -1,8 +1,8 @@ -tests/cases/compiler/lastPropertyInLiteralWins.ts(8,5): error TS2300: Duplicate identifier 'thunk'. -tests/cases/compiler/lastPropertyInLiteralWins.ts(9,5): error TS2300: Duplicate identifier 'thunk'. -tests/cases/compiler/lastPropertyInLiteralWins.ts(12,6): error TS2345: Argument of type '{ thunk: (num: number) => void; }' is not assignable to parameter of type 'Thing'. +tests/cases/compiler/lastPropertyInLiteralWins.ts(7,6): error TS2345: Argument of type '{ thunk: (num: number) => void; }' is not assignable to parameter of type 'Thing'. Types of property 'thunk' are incompatible. Type '(num: number) => void' is not assignable to type '(str: string) => void'. +tests/cases/compiler/lastPropertyInLiteralWins.ts(8,5): error TS2300: Duplicate identifier 'thunk'. +tests/cases/compiler/lastPropertyInLiteralWins.ts(9,5): error TS2300: Duplicate identifier 'thunk'. tests/cases/compiler/lastPropertyInLiteralWins.ts(13,5): error TS2300: Duplicate identifier 'thunk'. tests/cases/compiler/lastPropertyInLiteralWins.ts(14,5): error TS2300: Duplicate identifier 'thunk'. @@ -15,21 +15,12 @@ tests/cases/compiler/lastPropertyInLiteralWins.ts(14,5): error TS2300: Duplicate thing.thunk("str"); } test({ // Should error, as last one wins, and is wrong type + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ thunk: (str: string) => {}, - ~~~~~ -!!! error TS2300: Duplicate identifier 'thunk'. - thunk: (num: number) => {} - ~~~~~ -!!! error TS2300: Duplicate identifier 'thunk'. - }); - - test({ // Should be OK. Last 'thunk' is of correct type - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - thunk: (num: number) => {}, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~ !!! error TS2300: Duplicate identifier 'thunk'. - thunk: (str: string) => {} + thunk: (num: number) => {} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~ !!! error TS2300: Duplicate identifier 'thunk'. @@ -38,4 +29,13 @@ tests/cases/compiler/lastPropertyInLiteralWins.ts(14,5): error TS2300: Duplicate !!! error TS2345: Argument of type '{ thunk: (num: number) => void; }' is not assignable to parameter of type 'Thing'. !!! error TS2345: Types of property 'thunk' are incompatible. !!! error TS2345: Type '(num: number) => void' is not assignable to type '(str: string) => void'. + + test({ // Should be OK. Last 'thunk' is of correct type + thunk: (num: number) => {}, + ~~~~~ +!!! error TS2300: Duplicate identifier 'thunk'. + thunk: (str: string) => {} + ~~~~~ +!!! error TS2300: Duplicate identifier 'thunk'. + }); \ No newline at end of file diff --git a/tests/baselines/reference/memberOverride.errors.txt b/tests/baselines/reference/memberOverride.errors.txt index 0fd0fb57e67..b4974e69e53 100644 --- a/tests/baselines/reference/memberOverride.errors.txt +++ b/tests/baselines/reference/memberOverride.errors.txt @@ -1,9 +1,8 @@ tests/cases/compiler/memberOverride.ts(4,5): error TS2300: Duplicate identifier 'a'. tests/cases/compiler/memberOverride.ts(5,5): error TS2300: Duplicate identifier 'a'. -tests/cases/compiler/memberOverride.ts(8,5): error TS2322: Type 'string' is not assignable to type 'number'. -==== tests/cases/compiler/memberOverride.ts (3 errors) ==== +==== tests/cases/compiler/memberOverride.ts (2 errors) ==== // An object initialiser accepts the first definition for the same property with a different type signature // Should compile, since the second declaration of a overrides the first var x = { @@ -15,6 +14,4 @@ tests/cases/compiler/memberOverride.ts(8,5): error TS2322: Type 'string' is not !!! error TS2300: Duplicate identifier 'a'. } - var n: number = x.a; - ~ -!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file + var n: number = x.a; \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesInImplementationSignatures2.errors.txt b/tests/baselines/reference/stringLiteralTypesInImplementationSignatures2.errors.txt index cbc517e0520..3cc172c96d5 100644 --- a/tests/baselines/reference/stringLiteralTypesInImplementationSignatures2.errors.txt +++ b/tests/baselines/reference/stringLiteralTypesInImplementationSignatures2.errors.txt @@ -11,9 +11,10 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/stringLiteralType tests/cases/conformance/types/objectTypeLiteral/callSignatures/stringLiteralTypesInImplementationSignatures2.ts(26,5): error TS2300: Duplicate identifier 'foo'. tests/cases/conformance/types/objectTypeLiteral/callSignatures/stringLiteralTypesInImplementationSignatures2.ts(26,5): error TS2381: A signature with an implementation cannot use a string literal type. tests/cases/conformance/types/objectTypeLiteral/callSignatures/stringLiteralTypesInImplementationSignatures2.ts(27,5): error TS2300: Duplicate identifier 'foo'. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/stringLiteralTypesInImplementationSignatures2.ts(27,5): error TS2381: A signature with an implementation cannot use a string literal type. -==== tests/cases/conformance/types/objectTypeLiteral/callSignatures/stringLiteralTypesInImplementationSignatures2.ts (13 errors) ==== +==== tests/cases/conformance/types/objectTypeLiteral/callSignatures/stringLiteralTypesInImplementationSignatures2.ts (14 errors) ==== // String literal types are only valid in overload signatures function foo(x: any); @@ -67,5 +68,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/stringLiteralType foo(x: 'a') { }, ~~~ !!! error TS2300: Duplicate identifier 'foo'. + ~~~~~~~~~~~~~~~ +!!! error TS2381: A signature with an implementation cannot use a string literal type. } \ No newline at end of file