8000 Merge pull request #1272 from Microsoft/computedProperties · Nemo157/TypeScript@05fd2e9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 05fd2e9

Browse files
committed
Merge pull request microsoft#1272 from Microsoft/computedProperties
Parsing and emit for computed properties
2 parents 526aed3 + ddebd02 commit 05fd2e9

File tree

167 files changed

+1489
-504
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

167 files changed

+1489
-504
lines changed

src/compiler/binder.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ module ts {
5353
}
5454
}
5555

56+
/**
57+
* Returns false if any of the following are true:
58+
* 1. declaration has no name
59+
* 2. declaration has a literal name (not computed)
60+
* 3. declaration has a computed property name that is a known symbol
61+
*/
62+
export function hasComputedNameButNotSymbol(declaration: Declaration): boolean {
63+
return declaration.name && declaration.name.kind === SyntaxKind.ComputedPropertyName;
64+
}
65+
5666
export function bindSourceFile(file: SourceFile) {
5767

5868
var parent: Node;
@@ -84,13 +94,14 @@ module ts {
8494
if (symbolKind & SymbolFlags.Value && !symbol.valueDeclaration) symbol.valueDeclaration = node;
8595
}
8696

87-
// TODO(jfreeman): Implement getDeclarationName for property name
97+
// Should not be called on a declaration with a computed property name.
8898
function getDeclarationName(node: Declaration): string {
8999
if (node.name) {
90100
if (node.kind === SyntaxKind.ModuleDeclaration && node.name.kind === SyntaxKind.StringLiteral) {
91101
return '"' + (<LiteralExpression>node.name).text + '"';
92102
}
93-
return (<Identifier>node.name).text;
103+
Debug.assert(!hasComputedNameButNotSymbol(node));
104+
return (<Identifier | LiteralExpression>node.name).text;
94105
}
95106
switch (node.kind) {
96107
case SyntaxKind.ConstructorType:
@@ -111,6 +122,12 @@ module ts {
111122
}
112123

113124
function declareSymbol(symbols: SymbolTable, parent: Symbol, node: Decl 10000 aration, includes: SymbolFlags, excludes: SymbolFlags): Symbol {
125+
// Nodes with computed property names will not get symbols, because the type checker
126+
// does not make properties for them.
127+
if (hasComputedNameButNotSymbol(node)) {
128+
return undefined;
129+
}
130+
114131
var name = getDeclarationName(node);
115132
if (name !== undefined) {
116133
var symbol = hasProperty(symbols, name) ? symbols[name] : (symbols[name] = createSymbol(0, name));

src/compiler/checker.ts

Lines changed: 97 additions & 76 deletions
Large diffs are not rendered by default.

src/compiler/diagnosticInformationMap.generated.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,14 @@ module ts {
126126
Unterminated_regular_expression_literal: { code: 1161, category: DiagnosticCategory.Error, key: "Unterminated regular expression literal." },
127127
An_object_member_cannot_be_declared_optional: { code: 1162, category: DiagnosticCategory.Error, key: "An object member cannot be declared optional." },
128128
yield_expression_must_be_contained_within_a_generator_declaration: { code: 1163, category: DiagnosticCategory.Error, key: "'yield' expression must be contained_within a generator declaration." },
129+
Computed_property_names_are_not_allowed_in_enums: { code: 1164, category: DiagnosticCategory.Error, key: "Computed property names are not allowed in enums." },
130+
Computed_property_names_are_not_allowed_in_an_ambient_context: { code: 1165, category: DiagnosticCategory.Error, key: "Computed property names are not allowed in an ambient context." },
131+
Computed_property_names_are_not_allowed_in_class_property_declarations: { code: 1166, category: DiagnosticCategory.Error, key: "Computed property names are not allowed in class property declarations." },
132+
Computed_property_names_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1167, category: DiagnosticCategory.Error, key: "Computed property names are only available when targeting ECMAScript 6 and higher." },
133+
Computed_property_names_are_not_allowed_in_method_overloads: { code: 1168, category: DiagnosticCategory.Error, key: "Computed property names are not allowed in method overloads." },
134+
Computed_property_names_are_not_allowed_in_interfaces: { code: 1169, category: DiagnosticCategory.Error, key: "Computed property names are not allowed in interfaces." },
135+
Computed_property_names_are_not_allowed_in_type_literals: { code: 1170, category: DiagnosticCategory.Error, key: "Computed property names are not allowed in type literals." },
136+
A_comma_expression_is_not_allowed_in_a_computed_property_name: { code: 1171, category: DiagnosticCategory.Error, key: "A comma expression is not allowed in a computed property name." },
129137
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
130138
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." },
131139
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },

src/compiler/diagnosticMessages.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,38 @@
495495
"category": "Error",
496496
"code": 1163
497497
},
498+
"Computed property names are not allowed in enums.": {
499+
"category": "Error",
500+
"code": 1164
501+
},
502+
"Computed property names are not allowed in an ambient context.": {
503+
"category": "Error",
504+
"code": 1165
505+
},
506+
"Computed property names are not allowed in class property declarations.": {
507+
"category": "Error",
508+
"code": 1166
509+
},
510+
"Computed property names are only available when targeting ECMAScript 6 and higher.": {
511+
"category": "Error",
512+
"code": 1167
513+
},
514+
"Computed property names are not allowed in method overloads.": {
515+
"category": "Error",
516+
"code": 1168
517+
},
518+
"Computed property names are not allowed in interfaces.": {
519+
"category": "Error",
520+
"code": 1169
521+
},
522+
"Computed property names are not allowed in type literals.": {
523+
"category": "Error",
524+
"code": 1170
525+
},
526+
"A comma expression is not allowed in a computed property name.": {
527+
"category": "Error",
528+
"code": 1171
529+
},
498530

499531
"Duplicate identifier '{0}'.": {
500532
"category": "Error",

src/compiler/emitter.ts

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -277,24 +277,37 @@ module ts {
277277
var firstAccessor: AccessorDeclaration;
278278
var getAccessor: AccessorDeclaration;
279279
var setAccessor: AccessorDeclaration;
280-
forEach(node.members, (member: Declaration) => {
281-
// TODO(jfreeman): Handle computed names for accessor matching
282-
if ((member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor) &&
283-
(<Identifier>member.name).text === (<Identifier>accessor.name).text &&
284-
(member.flags & NodeFlags.Static) === (accessor.flags & NodeFlags.Static)) {
285-
if (!firstAccessor) {
286-
firstAccessor = <AccessorDeclaration>member;
287-
}
280+
if (accessor.name.kind === SyntaxKind.ComputedPropertyName) {
281+
firstAccessor = accessor;
282+
if (accessor.kind === SyntaxKind.GetAccessor) {
283+
getAccessor = accessor;
284+
}
285+
else if (accessor.kind === SyntaxKind.SetAccessor) {
286+
setAccessor = accessor;
287+
}
288+
else {
289+
Debug.fail("Accessor has wrong kind");
290+
}
291+
}
292+
else {
293+
forEach(node.members,(member: Declaration) => {
294+
if ((member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor) &&
295+
(<Identifier>member.name).text === (<Identifier>accessor.name).text &&
296+
(member.flags & NodeFlags.Static) === (accessor.flags & NodeFlags.Static)) {
297+
if (!firstAccessor) {
298+
firstAccessor = <AccessorDeclaration>member;
299+
}
288300

289-
if (member.kind === SyntaxKind.GetAccessor && !getAccessor) {
290-
getAccessor = <AccessorDeclaration>member;
291-
}
301+
if (member.kind === SyntaxKind.GetAccessor && !getAccessor) {
302+
getAccessor = <AccessorDeclaration>member;
303+
}
292304

293-
if (member.kind === SyntaxKind.SetAccessor && !setAccessor) {
294-
setAccessor = <AccessorDeclaration>member;
305+
if (member.kind === SyntaxKind.SetAccessor && !setAccessor) {
306+
setAccessor = <AccessorDeclaration>member;
307+
}
295308
}
296-
}
297-
});
309+
});
310+
}
298311
return {
299312
firstAccessor,
300313
getAccessor,
@@ -2069,6 +2082,9 @@ module ts {
20692082
if (node.kind === SyntaxKind.StringLiteral) {
20702083
emitLiteral(<LiteralExpression>node);
20712084
}
2085+
else if (node.kind === SyntaxKind.ComputedPropertyName) {
2086+
emit((<ComputedPropertyName>node).expression);
2087+
}
20722088
else {
20732089
write("\"");
20742090

@@ -2189,6 +2205,12 @@ module ts {
21892205
}
21902206
}
21912207

2208+
function emitComputedPropertyName(node: ComputedPropertyName) {
2209+
write("[");
2210+
emit(node.expression);
2211+
write("]");
2212+
}
2213+
21922214
function emitPropertyAssignment(node: PropertyDeclaration) {
21932215
emitLeadingComments(node);
21942216
emit(node.name);
@@ -2864,13 +2886,15 @@ module ts {
28642886
});
28652887
}
28662888

2867-
// TODO(jfreeman): Account for computed property name
2868-
function emitMemberAccess(memberName: DeclarationName) {
2889+
function emitMemberAccessForPropertyName(memberName: DeclarationName) {
28692890
if (memberName.kind === SyntaxKind.StringLiteral || memberName.kind === SyntaxKind.NumericLiteral) {
28702891
write("[");
28712892
emitNode(memberName);
28722893
write("]");
28732894
}
2895+
else if (memberName.kind === SyntaxKind.ComputedPropertyName) {
2896+
emitComputedPropertyName(<ComputedPropertyName>memberName);
2897+
}
28742898
else {
28752899
write(".");
28762900
emitNode(memberName);
@@ -2890,7 +2914,7 @@ module ts {
28902914
else {
28912915
write("this");
28922916
}
2893-
emitMemberAccess((<PropertyDeclaration>member).name);
2917+
emitMemberAccessForPropertyName((<PropertyDeclaration>member).name);
28942918
emitEnd((<PropertyDeclaration>member).name);
28952919
write(" = ");
28962920
emit((<PropertyDeclaration>member).initializer);
@@ -2916,7 +2940,7 @@ module ts {
29162940
if (!(member.flags & NodeFlags.Static)) {
29172941
write(".prototype");
29182942
}
2919-
emitMemberAccess((<MethodDeclaration>member).name);
2943+
emitMemberAccessForPropertyName((<MethodDeclaration>member).name);
29202944
emitEnd((<MethodDeclaration>member).name);
29212945
write(" = ");
29222946
emitStart(member);
@@ -3456,6 +3480,8 @@ module ts {
34563480
return emitPropertyAssignment(<PropertyDeclaration>node);
34573481
case SyntaxKind.ShorthandPropertyAssignment:
34583482
return emitShortHandPropertyAssignment(<ShortHandPropertyDeclaration>node);
3483+
case SyntaxKind.ComputedPropertyName:
3484+
return emitComputedPropertyName(<ComputedPropertyName>node);
34593485
case SyntaxKind.PropertyAccess:
34603486
return emitPropertyAccess(<PropertyAccess>node);
34613487
case SyntaxKind.IndexedAccess:

0 commit comments

Comments
 (0)
0