Skip to content

Commit 742f65c

Browse files
author
Yui T
committed
Merge branch 'master' into parseClassInStrictMode
Conflicts: src/compiler/diagnosticInformationMap.generated.ts src/compiler/diagnosticMessages.json
2 parents aef37f1 + d56f2f6 commit 742f65c

File tree

79 files changed

+1176
-144
lines changed

Some content is hidden

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

79 files changed

+1176
-144
lines changed

src/compiler/binder.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -388,23 +388,28 @@ module ts {
388388
bindChildren(node, /*symbolKind:*/ 0, /*isBlockScopeContainer:*/ true);
389389
}
390390

391-
function bindBlockScopedVariableDeclaration(node: Declaration) {
391+
function bindBlockScopedDeclaration(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags) {
392392
switch (blockScopeContainer.kind) {
393393
case SyntaxKind.ModuleDeclaration:
394-
declareModuleMember(node, SymbolFlags.BlockScopedVariable, SymbolFlags.BlockScopedVariableExcludes);
394+
declareModuleMember(node, symbolKind, symbolExcludes);
395395
break;
396396
case SyntaxKind.SourceFile:
397397
if (isExternalModule(<SourceFile>container)) {
398-
declareModuleMember(node, SymbolFlags.BlockScopedVariable, SymbolFlags.BlockScopedVariableExcludes);
398+
declareModuleMember(node, symbolKind, symbolExcludes);
399399
break;
400400
}
401+
// fall through.
401402
default:
402403
if (!blockScopeContainer.locals) {
403404
blockScopeContainer.locals = {};
404405
}
405-
declareSymbol(blockScopeContainer.locals, undefined, node, SymbolFlags.BlockScopedVariable, SymbolFlags.BlockScopedVariableExcludes);
406+
declareSymbol(blockScopeContainer.locals, undefined, node, symbolKind, symbolExcludes);
406407
}
407-
bindChildren(node, SymbolFlags.BlockScopedVariable, /*isBlockScopeContainer*/ false);
408+
bindChildren(node, symbolKind, /*isBlockScopeContainer*/ false);
409+
}
410+
411+
function bindBlockScopedVariableDeclaration(node: Declaration) {
412+
bindBlockScopedDeclaration(node, SymbolFlags.BlockScopedVariable, SymbolFlags.BlockScopedVariableExcludes);
408413
}
409414

410415
function getDestructuringParameterName(node: Declaration) {
@@ -493,7 +498,7 @@ module ts {
493498
bindCatchVariableDeclaration(<CatchClause>node);
494499
break;
495500
case SyntaxKind.ClassDeclaration:
496-
bindDeclaration(<Declaration>node, SymbolFlags.Class, SymbolFlags.ClassExcludes, /*isBlockScopeContainer*/ false);
501+
bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.Class, SymbolFlags.ClassExcludes);
497502
break;
498503
case SyntaxKind.InterfaceDeclaration:
499504
bindDeclaration(<Declaration>node, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes, /*isBlockScopeContainer*/ false);

src/compiler/checker.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9760,6 +9760,10 @@ module ts {
97609760
grammarErrorOnNode(node, Diagnostics.class_declarations_are_only_supported_directly_inside_a_module_or_as_a_top_level_declaration);
97619761
}
97629762

9763+
if (!node.name && !(node.flags & NodeFlags.Default)) {
9764+
grammarErrorOnFirstToken(node, Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name);
9765+
}
9766+
97639767
checkGrammarClassDeclarationHeritageClauses(node);
97649768
checkDecorators(node);
97659769
if (node.name) {

src/compiler/diagnosticInformationMap.generated.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ module ts {
168168
Cannot_compile_non_external_modules_when_the_separateCompilation_flag_is_provided: { code: 1208, category: DiagnosticCategory.Error, key: "Cannot compile non-external modules when the '--separateCompilation' flag is provided." },
169169
Ambient_const_enums_are_not_allowed_when_the_separateCompilation_flag_is_provided: { code: 1209, category: DiagnosticCategory.Error, key: "Ambient const enums are not allowed when the '--separateCompilation' flag is provided." },
170170
Invalid_use_of_0_because_class_definition_is_considered_a_strict_mode_code: { code: 1210, category: DiagnosticCategory.Error, key: "Invalid use of '{0}' because class definition is considered a strict mode code " },
171+
A_class_declaration_without_the_default_modifier_must_have_a_name: { code: 1211, category: DiagnosticCategory.Error, key: "A class declaration without the 'default' modifier must have a name" },
171172
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
172173
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." },
173174
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },
@@ -506,6 +507,22 @@ module ts {
506507
Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: { code: 7024, category: DiagnosticCategory.Error, key: "Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions." },
507508
You_cannot_rename_this_element: { code: 8000, category: DiagnosticCategory.Error, key: "You cannot rename this element." },
508509
You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library: { code: 8001, category: DiagnosticCategory.Error, key: "You cannot rename elements that are defined in the standard TypeScript library." },
510+
import_can_only_be_used_in_a_ts_file: { code: 8002, category: DiagnosticCategory.Error, key: "'import ... =' can only be used in a .ts file." },
511+
export_can_only_be_used_in_a_ts_file: { code: 8003, category: DiagnosticCategory.Error, key: "'export=' can only be used in a .ts file." },
512+
type_parameter_declarations_can_only_be_used_in_a_ts_file: { code: 8004, category: DiagnosticCategory.Error, key: "'type parameter declarations' can only be used in a .ts file." },
513+
implements_clauses_can_only_be_used_in_a_ts_file: { code: 8005, category: DiagnosticCategory.Error, key: "'implements clauses' can only be used in a .ts file." },
514+
interface_declarations_can_only_be_used_in_a_ts_file: { code: 8006, category: DiagnosticCategory.Error, key: "'interface declarations' can only be used in a .ts file." },
515+
module_declarations_can_only_be_used_in_a_ts_file: { code: 8007, category: DiagnosticCategory.Error, key: "'module declarations' can only be used in a .ts file." },
516+
type_aliases_can_only_be_used_in_a_ts_file: { code: 8008, category: DiagnosticCategory.Error, key: "'type aliases' can only be used in a .ts file." },
517+
_0_can_only_be_used_in_a_ts_file: { code: 8009, category: DiagnosticCategory.Error, key: "'{0}' can only be used in a .ts file." },
518+
types_can_only_be_used_in_a_ts_file: { code: 8010, category: DiagnosticCategory.Error, key: "'types' can only be used in a .ts file." },
519+
type_arguments_can_only_be_used_in_a_ts_file: { code: 8011, category: DiagnosticCategory.Error, key: "'type arguments' can only be used in a .ts file." },
520+
parameter_modifiers_can_only_be_used_in_a_ts_file: { code: 8012, category: DiagnosticCategory.Error, key: "'parameter modifiers' can only be used in a .ts file." },
521+
can_only_be_used_in_a_ts_file: { code: 8013, category: DiagnosticCategory.Error, key: "'?' can only be used in a .ts file." },
522+
property_declarations_can_only_be_used_in_a_ts_file: { code: 8014, category: DiagnosticCategory.Error, key: "'property declarations' can only be used in a .ts file." },
523+
enum_declarations_can_only_be_used_in_a_ts_file: { code: 8015, category: DiagnosticCategory.Error, key: "'enum declarations' can only be used in a .ts file." },
524+
type_assertion_expressions_can_only_be_used_in_a_ts_file: { code: 8016, category: DiagnosticCategory.Error, key: "'type assertion expressions' can only be used in a .ts file." },
525+
decorators_can_only_be_used_in_a_ts_file: { code: 8017, category: DiagnosticCategory.Error, key: "'decorators' can only be used in a .ts file." },
509526
yield_expressions_are_not_currently_supported: { code: 9000, category: DiagnosticCategory.Error, key: "'yield' expressions are not currently supported." },
510527
Generators_are_not_currently_supported: { code: 9001, category: DiagnosticCategory.Error, key: "Generators are not currently supported." },
511528
Only_identifiers_Slashqualified_names_with_optional_type_arguments_are_currently_supported_in_a_class_extends_clauses: { code: 9002, category: DiagnosticCategory.Error, key: "Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses." },

src/compiler/diagnosticMessages.json

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,10 @@
663663
"category": "Error",
664664
"code": 1210
665665
},
666+
"A class declaration without the 'default' modifier must have a name": {
667+
"category": "Error",
668+
"code": 1211
669+
},
666670
"Duplicate identifier '{0}'.": {
667671
"category": "Error",
668672
"code": 2300
@@ -2017,6 +2021,71 @@
20172021
"category": "Error",
20182022
"code": 8001
20192023
},
2024+
"'import ... =' can only be used in a .ts file.": {
2025+
"category": "Error",
2026+
"code": 8002
2027+
},
2028+
"'export=' can only be used in a .ts file.": {
2029+
"category": "Error",
2030+
"code": 8003
2031+
},
2032+
"'type parameter declarations' can only be used in a .ts file.": {
2033+
"category": "Error",
2034+
"code": 8004
2035+
},
2036+
"'implements clauses' can only be used in a .ts file.": {
2037+
"category": "Error",
2038+
"code": 8005
2039+
},
2040+
"'interface declarations' can only be used in a .ts file.": {
2041+
"category": "Error",
2042+
"code": 8006
2043+
},
2044+
"'module declarations' can only be used in a .ts file.": {
2045+
"category": "Error",
2046+
"code": 8007
2047+
},
2048+
"'type aliases' can only be used in a .ts file.": {
2049+
"category": "Error",
2050+
"code": 8008
2051+
},
2052+
"'{0}' can only be used in a .ts file.": {
2053+
"category": "Error",
2054+
"code": 8009
2055+
},
2056+
"'types' can only be used in a .ts file.": {
2057+
"category": "Error",
2058+
"code": 8010
2059+
},
2060+
"'type arguments' can only be used in a .ts file.": {
2061+
"category": "Error",
2062+
"code": 8011
2063+
},
2064+
"'parameter modifiers' can only be used in a .ts file.": {
2065+
"category": "Error",
2066+
"code": 8012
2067+
},
2068+
"'?' can only be used in a .ts file.": {
2069+
"category": "Error",
2070+
"code": 8013
2071+
},
2072+
"'property declarations' can only be used in a .ts file.": {
2073+
"category": "Error",
2074+
"code": 8014
2075+
},
2076+
"'enum declarations' can only be used in a .ts file.": {
2077+
"category": "Error",
2078+
"code": 8015
2079+
},
2080+
"'type assertion expressions' can only be used in a .ts file.": {
2081+
"category": "Error",
2082+
"code": 8016
2083+
},
2084+
"'decorators' can only be used in a .ts file.": {
2085+
"category": "Error",
2086+
"code": 8017
2087+
},
2088+
20202089
"'yield' expressions are not currently supported.": {
20212090
"category": "Error",
20222091
"code": 9000

src/compiler/emitter.ts

Lines changed: 94 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ module ts {
262262
switch (node.kind) {
263263
case SyntaxKind.FunctionDeclaration:
264264
case SyntaxKind.ClassDeclaration:
265+
case SyntaxKind.ClassExpression:
265266
generateNameForFunctionOrClassDeclaration(<Declaration>node);
266267
break;
267268
case SyntaxKind.ModuleDeclaration:
@@ -3198,28 +3199,49 @@ module ts {
31983199
}
31993200
}
32003201

3201-
function emitMemberAssignments(node: ClassLikeDeclaration, staticFlag: NodeFlags) {
3202-
forEach(node.members, member => {
3203-
if (member.kind === SyntaxKind.PropertyDeclaration && (member.flags & NodeFlags.Static) === staticFlag && (<PropertyDeclaration>member).initializer) {
3204-
writeLine();
3205-
emitLeadingComments(member);
3206-
emitStart(member);
3207-
emitStart((<PropertyDeclaration>member).name);
3208-
if (staticFlag) {
3209-
emitDeclarationName(node);
3210-
}
3211-
else {
3212-
write("this");
3213-
}
3214-
emitMemberAccessForPropertyName((<PropertyDeclaration>member).name);
3215-
emitEnd((<PropertyDeclaration>member).name);
3216-
write(" = ");
3217-
emit((<PropertyDeclaration>member).initializer);
3218-
write(";");
3219-
emitEnd(member);
3220-
emitTrailingComments(member);
3202+
function getInitializedProperties(node: ClassLikeDeclaration, static: boolean) {
3203+
let properties: PropertyDeclaration[] = [];
3204+
for (let member of node.members) {
3205+
if (member.kind === SyntaxKind.PropertyDeclaration && static === ((member.flags & NodeFlags.Static) !== 0) && (<PropertyDeclaration>member).initializer) {
3206+
properties.push(<PropertyDeclaration>member);
32213207
}
3222-
});
3208+
}
3209+
3210+
return properties;
3211+
}
3212+
3213+
function emitPropertyDeclarations(node: ClassLikeDeclaration, properties: PropertyDeclaration[]) {
3214+
for (let property of properties) {
3215+
emitPropertyDeclaration(node, property);
3216+
}
3217+
}
3218+
3219+
function emitPropertyDeclaration(node: ClassLikeDeclaration, property: PropertyDeclaration, receiver?: Identifier, isExpression?: boolean) {
3220+
writeLine();
3221+
emitLeadingComments(property);
3222+
emitStart(property);
3223+
emitStart(property.name);
3224+
if (receiver) {
3225+
emit(receiver);
3226+
}
3227+
else {
3228+
if (property.flags & NodeFlags.Static) {
3229+
emitDeclarationName(node);
3230+
}
3231+
else {
3232+
write("this");
3233+
}
3234+
}
3235+
emitMemberAccessForPropertyName(property.name);
3236+
emitEnd(property.name);
3237+
write(" = ");
3238+
emit(property.initializer);
3239+
if (!isExpression) {
3240+
write(";");
3241+
}
3242+
3243+
emitEnd(property);
3244+
emitTrailingComments(property);
32233245
}
32243246

32253247
function emitMemberFunctionsForES5AndLower(node: ClassLikeDeclaration) {
@@ -3337,6 +3359,14 @@ module ts {
33373359
tempVariables = undefined;
33383360
tempParameters = undefined;
33393361

3362+
emitConstructorWorker(node, baseTypeElement);
3363+
3364+
tempFlags = saveTempFlags;
3365+
tempVariables = saveTempVariables;
3366+
tempParameters = saveTempParameters;
3367+
}
3368+
3369+
function emitConstructorWorker(node: ClassLikeDeclaration, baseTypeElement: HeritageClauseElement) {
33403370
// Check if we have property assignment inside class declaration.
33413371
// If there is property assignment, we need to emit constructor whether users define it or not
33423372
// If there is no property assignment, we can omit constructor if users do not define it
@@ -3424,7 +3454,7 @@ module ts {
34243454
emitEnd(baseTypeElement);
34253455
}
34263456
}
3427-
emitMemberAssignments(node, /*staticFlag*/0);
3457+
emitPropertyDeclarations(node, getInitializedProperties(node, /*static:*/ false));
34283458
if (ctor) {
34293459
var statements: Node[] = (<Block>ctor.body).statements;
34303460
if (superCall) {
@@ -3444,10 +3474,6 @@ module ts {
34443474
if (ctor) {
34453475
emitTrailingComments(ctor);
34463476
}
3447-
3448-
tempFlags = saveTempFlags;
3449-
tempVariables = saveTempVariables;
3450-
tempParameters = saveTempParameters;
34513477
}
34523478

34533479
function emitClassExpression(node: ClassExpression) {
@@ -3539,6 +3565,29 @@ module ts {
35393565
}
35403566
}
35413567

3568+
// If the class has static properties, and it's a class expression, then we'll need
3569+
// to specialize the emit a bit. for a class expression of the form:
3570+
//
3571+
// class C { static a = 1; static b = 2; ... }
3572+
//
3573+
// We'll emit:
3574+
//
3575+
// (_temp = class C { ... }, _temp.a = 1, _temp.b = 2, _temp)
3576+
//
3577+
// This keeps the expression as an expression, while ensuring that the static parts
3578+
// of it have been initialized by the time it is used.
3579+
let staticProperties = getInitializedProperties(node, /*static:*/ true);
3580+
let isClassExpressionWithStaticProperties = staticProperties.length > 0 && node.kind === SyntaxKind.ClassExpression;
3581+
let tempVariable: Identifier;
3582+
3583+
if (isClassExpressionWithStaticProperties) {
3584+
tempVariable = createAndRecordTempVariable(TempFlags.Auto);
3585+
write("(");
3586+
increaseIndent();
3587+
emit(tempVariable);
3588+
write(" = ")
3589+
}
3590+
35423591
write("class");
35433592

35443593
// check if this is an "export default class" as it may not have a name. Do not emit the name if the class is decorated.
@@ -3589,9 +3638,24 @@ module ts {
35893638
// From ES6 specification:
35903639
// HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using
35913640
// a lexical declaration such as a LexicalDeclaration or a ClassDeclaration.
3592-
writeLine();
3593-
emitMemberAssignments(node, NodeFlags.Static);
3594-
emitDecoratorsOfClass(node);
3641+
3642+
if (isClassExpressionWithStaticProperties) {
3643+
for (var property of staticProperties) {
3644+
write(",");
3645+
writeLine();
3646+
emitPropertyDeclaration(node, property, /*receiver:*/ tempVariable, /*isExpression:*/ true);
3647+
}
3648+
write(",");
3649+
writeLine();
3650+
emit(tempVariable);
3651+
decreaseIndent();
3652+
write(")");
3653+
}
3654+
else {
3655+
writeLine();
3656+
emitPropertyDeclarations(node, staticProperties);
3657+
emitDecoratorsOfClass(node);
3658+
}
35953659

35963660
// If this is an exported class, but not on the top level (i.e. on an internal
35973661
// module), export it
@@ -3647,7 +3711,7 @@ module ts {
36473711
writeLine();
36483712
emitConstructor(node, baseTypeNode);
36493713
emitMemberFunctionsForES5AndLower(node);
3650-
emitMemberAssignments(node, NodeFlags.Static);
3714+
emitPropertyDeclarations(node, getInitializedProperties(node, /*static:*/ true));
36513715
writeLine();
36523716
emitDecoratorsOfClass(node);
36533717
writeLine();

0 commit comments

Comments
 (0)