diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index fe3009da3aa..fe00830ae51 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -350,6 +350,7 @@ module ts { break; case SyntaxKind.Property: case SyntaxKind.PropertyAssignment: + case SyntaxKind.ShortHandPropertyAssignment: bindDeclaration(node, SymbolFlags.Property, SymbolFlags.PropertyExcludes, /*isBlockScopeContainer*/ false); break; case SyntaxKind.EnumMember: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2567b54de4a..5bd2e1f8ec8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4968,7 +4968,14 @@ module ts { if (hasProperty(members, id)) { var member = members[id]; if (member.flags & SymbolFlags.Property) { - var type = checkExpression((member.declarations[0]).initializer, contextualMapper); + var memberDecl = member.declarations[0]; + var type: Type; + if (memberDecl.kind === SyntaxKind.PropertyAssignment) { + type = checkExpression(memberDecl.initializer, contextualMapper); + } + else { + type = checkExpression(memberDecl.name, contextualMapper); + } var prop = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name); prop.declarations = member.declarations; prop.parent = member.parent; diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 349601a6db8..19d5f0c5f6b 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -122,6 +122,7 @@ module ts { let_declarations_can_only_be_declared_inside_a_block: { code: 1157, category: DiagnosticCategory.Error, key: "'let' declarations can only be declared inside a block." }, Invalid_template_literal_expected: { code: 1158, category: DiagnosticCategory.Error, key: "Invalid template literal; expected '}'" }, Tagged_templates_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1159, category: DiagnosticCategory.Error, key: "Tagged templates are only available when targeting ECMAScript 6 and higher." }, + A_object_member_cannot_be_declared_optional: { code: 1159, category: DiagnosticCategory.Error, key: "A object member cannot be declared optional." }, Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." }, Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." }, Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 7359abefb60..52235a0848e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -480,6 +480,11 @@ "code": 1159 }, + "A object member cannot be declared optional.": { + "category": "Error", + "code": 1159 + }, + "Duplicate identifier '{0}'.": { "category": "Error", "code": 2300 diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index f61d4403eec..d23380b4fb1 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1033,6 +1033,16 @@ module ts { emitTrailingComments(node); } + function emitShortHandPropertyAssignment(node: ShortHandPropertyDeclaration) { + emitLeadingComments(node); + emit(node.name); + if (compilerOptions.target !== ScriptTarget.ES6) { + write(": "); + emit(node.name); + } + emitTrailingComments(node); + } + function tryEmitConstantValue(node: PropertyAccess | IndexedAccess): boolean { var constantValue = resolver.getConstantValue(node); if (constantValue !== undefined) { @@ -2250,6 +2260,8 @@ module ts { return emitObjectLiteral(node); case SyntaxKind.PropertyAssignment: return emitPropertyAssignment(node); + case SyntaxKind.ShortHandPropertyAssignment: + return emitShortHandPropertyAssignment(node); case SyntaxKind.PropertyAccess: return emitPropertyAccess(node); case SyntaxKind.IndexedAccess: diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 65fada8e134..75ff2993609 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -198,6 +198,7 @@ module ts { child((node).initializer); case SyntaxKind.Property: case SyntaxKind.PropertyAssignment: + case SyntaxKind.ShortHandPropertyAssignment: return child((node).name) || child((node).type) || child((node).initializer); @@ -2669,9 +2670,11 @@ module ts { function parsePropertyAssignment(): PropertyDeclaration { var nodePos = scanner.getStartPos(); + var nameToken = token; var propertyName = parsePropertyName(); + var node: PropertyDeclaration; if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) { - var node = createNode(SyntaxKind.PropertyAssignment, nodePos); + node = createNode(SyntaxKind.PropertyAssignment, nodePos); node.name = propertyName; var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false); var body = parseBody(/* ignoreMissingOpenBrace */ false); @@ -2683,8 +2686,19 @@ module ts { node.initializer = makeFunctionExpression(SyntaxKind.FunctionExpression, node.pos, undefined, sig, body); return finishNode(node); } + if (token === SyntaxKind.QuestionToken) { + var questionStart = scanner.getTokenPos(); + errorAtPos(questionStart, scanner.getStartPos() - questionStart, Diagnostics.A_object_member_cannot_be_declared_optional); + nextToken(); + } + + // Parse to check if it is short-hand property assignment or normal property assignment + if (token !== SyntaxKind.ColonToken && nameToken === SyntaxKind.Identifier) { + node = createNode(SyntaxKind.ShortHandPropertyAssignment, nodePos); + node.name = propertyName; + } else { - var node = createNode(SyntaxKind.PropertyAssignment, nodePos); + node = createNode(SyntaxKind.PropertyAssignment, nodePos); node.name = propertyName; parseExpected(SyntaxKind.ColonToken); node.initializer = parseAssignmentExpression(false); @@ -2737,6 +2751,9 @@ module ts { if (p.kind === SyntaxKind.PropertyAssignment) { currentKind = Property; } + else if (p.kind === SyntaxKind.ShortHandPropertyAssignment) { + currentKind = Property; + } else if (p.kind === SyntaxKind.GetAccessor) { currentKind = GetAccessor; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 973c06d6e2d..51b93821d69 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -165,6 +165,7 @@ module ts { ArrayLiteral, ObjectLiteral, PropertyAssignment, + ShortHandPropertyAssignment, PropertyAccess, IndexedAccess, CallExpression, @@ -329,6 +330,10 @@ module ts { initializer?: Expression; } + export interface ShortHandPropertyDeclaration extends PropertyDeclaration { + name: Identifier; + } + export interface ParameterDeclaration extends VariableDeclaration { } /** diff --git a/tests/cases/compiler/objectLiteralShorthandProperties.ts b/tests/cases/compiler/objectLiteralShorthandProperties.ts new file mode 100644 index 00000000000..95b380308e9 --- /dev/null +++ b/tests/cases/compiler/objectLiteralShorthandProperties.ts @@ -0,0 +1,19 @@ +var a, b, c; + +var x1 = { + a +}; + +var x2 = { + a, +} + +var x3 = { + a: 0, + b, + c, + d() { }, + x3, + parent: x3 +}; + diff --git a/tests/cases/compiler/objectLiteralShorthandProperties2.ts b/tests/cases/compiler/objectLiteralShorthandProperties2.ts new file mode 100644 index 00000000000..38081e7d691 --- /dev/null +++ b/tests/cases/compiler/objectLiteralShorthandProperties2.ts @@ -0,0 +1,18 @@ +// errors +var y = { + "stringLiteral", + 42, + get e, + set f, + this, + super, + var, + class, + typeof +}; + +var x = { + a.b, + a["ss"], + a[1], +}; \ No newline at end of file diff --git a/tests/cases/compiler/objectLiteralShorthandProperties3.ts b/tests/cases/compiler/objectLiteralShorthandProperties3.ts new file mode 100644 index 00000000000..005885bb901 --- /dev/null +++ b/tests/cases/compiler/objectLiteralShorthandProperties3.ts @@ -0,0 +1,13 @@ +// module export + +module m { + export var x; +} + +module m { + var z = x; + var y = { + a: x, + x + }; +} diff --git a/tests/cases/compiler/objectLiteralShorthandProperties4.ts b/tests/cases/compiler/objectLiteralShorthandProperties4.ts new file mode 100644 index 00000000000..1f44dc18ae8 --- /dev/null +++ b/tests/cases/compiler/objectLiteralShorthandProperties4.ts @@ -0,0 +1,4 @@ +var x = { + x, // OK + undefinedVariable // Error +}