Skip to content

Commit 09d5582

Browse files
committed
merge with master
2 parents 626b6d4 + f4158ee commit 09d5582

29 files changed

+228
-151
lines changed

src/compiler/binder.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -353,15 +353,8 @@ module ts {
353353
}
354354

355355
function bindCatchVariableDeclaration(node: CatchClause) {
356-
var symbol = createSymbol(SymbolFlags.FunctionScopedVariable, node.name.text || "__missing");
357-
addDeclarationToSymbol(symbol, node, SymbolFlags.FunctionScopedVariable);
358-
var saveParent = parent;
359-
var savedBlockScopeContainer = blockScopeContainer;
360-
parent = node;
361-
setBlockScopeContainer(node, /*cleanLocals*/ true);
362-
forEachChild(node, bind);
363-
parent = saveParent;
364-
blockScopeContainer = savedBlockScopeContainer;
356+
bindChildren(node, /*symbolKind:*/ 0, /*isBlockScopeContainer:*/ true);
357+
365358
}
366359

367360
function bindBlockScopedVariableDeclaration(node: Declaration) {
@@ -402,7 +395,7 @@ module ts {
402395
if (isBindingPattern((<Declaration>node).name)) {
403396
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
404397
}
405-
else if (getCombinedNodeFlags(node) & NodeFlags.BlockScoped) {
398+
else if (isBlockOrCatchScoped(<Declaration>node)) {
406399
bindBlockScopedVariableDeclaration(<Declaration>node);
407400
}
408401
else {

src/compiler/checker.ts

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -416,13 +416,6 @@ module ts {
416416
break loop;
417417
}
418418
break;
419-
case SyntaxKind.CatchClause:
420-
var id = (<CatchClause>location).name;
421-
if (name === id.text) {
422-
result = location.symbol;
423-
break loop;
424-
}
425-
break;
426419
}
427420
lastLocation = location;
428421
location = location.parent;
@@ -451,7 +444,8 @@ module ts {
451444
}
452445
if (result.flags & SymbolFlags.BlockScopedVariable) {
453446
// Block-scoped variables cannot be used before their definition
454-
var declaration = forEach(result.declarations, d => getCombinedNodeFlags(d) & NodeFlags.BlockScoped ? d : undefined);
447+
var declaration = forEach(result.declarations, d => isBlockOrCatchScoped(d) ? d : undefined);
448+
455449
Debug.assert(declaration !== undefined, "Block-scoped variable declaration is undefined");
456450
if (!isDefinedBefore(declaration, errorLocation)) {
457451
error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationNameToString(declaration.name));
@@ -1994,7 +1988,7 @@ module ts {
19941988
}
19951989
// Handle catch clause variables
19961990
var declaration = symbol.valueDeclaration;
1997-
if (declaration.kind === SyntaxKind.CatchClause) {
1991+
if (declaration.parent.kind === SyntaxKind.CatchClause) {
19981992
return links.type = anyType;
19991993
}
20001994
// Handle variable, parameter or property
@@ -5087,7 +5081,9 @@ module ts {
50875081
}
50885082

50895083
function checkBlockScopedBindingCapturedInLoop(node: Identifier, symbol: Symbol): void {
5090-
if (languageVersion >= ScriptTarget.ES6 || (symbol.flags & SymbolFlags.BlockScopedVariable) === 0) {
5084+
if (languageVersion >= ScriptTarget.ES6 ||
5085+
(symbol.flags & SymbolFlags.BlockScopedVariable) === 0 ||
5086+
symbol.valueDeclaration.parent.kind === SyntaxKind.CatchClause) {
50915087
return;
50925088
}
50935089

@@ -8973,18 +8969,29 @@ module ts {
89738969
var catchClause = node.catchClause;
89748970
if (catchClause) {
89758971
// Grammar checking
8976-
if (catchClause.type) {
8977-
var sourceFile = getSourceFileOfNode(node);
8978-
var colonStart = skipTrivia(sourceFile.text, catchClause.name.end);
8979-
grammarErrorAtPos(sourceFile, colonStart, ":".length, Diagnostics.Catch_clause_parameter_cannot_have_a_type_annotation);
8972+
if (catchClause.variableDeclaration) {
8973+
if (catchClause.variableDeclaration.name.kind !== SyntaxKind.Identifier) {
8974+
grammarErrorOnFirstToken(catchClause.variableDeclaration.name, Diagnostics.Catch_clause_variable_name_must_be_an_identifier);
8975+
}
8976+
else if (catchClause.variableDeclaration.type) {
8977+
grammarErrorOnFirstToken(catchClause.variableDeclaration.type, Diagnostics.Catch_clause_variable_cannot_have_a_type_annotation);
8978+
}
8979+
else if (catchClause.variableDeclaration.initializer) {
8980+
grammarErrorOnFirstToken(catchClause.variableDeclaration.initializer, Diagnostics.Catch_clause_variable_cannot_have_an_initializer);
8981+
}
8982+
else {
8983+
// It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the
8984+
// Catch production is eval or arguments
8985+
checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>catchClause.variableDeclaration.name);
8986+
}
89808987
}
8981-
// It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the
8982-
// Catch production is eval or arguments
8983-
checkGrammarEvalOrArgumentsInStrictMode(node, catchClause.name);
89848988

89858989
checkBlock(catchClause.block);
89868990
}
8987-
if (node.finallyBlock) checkBlock(node.finallyBlock);
8991+
8992+
if (node.finallyBlock) {
8993+
checkBlock(node.finallyBlock);
8994+
}
89888995
}
89898996

89908997
function checkIndexConstraints(type: Type) {
@@ -10096,11 +10103,6 @@ module ts {
1009610103
copySymbol(location.symbol, meaning);
1009710104
}
1009810105
break;
10099-
case SyntaxKind.CatchClause:
10100-
if ((<CatchClause>location).name.text) {
10101-
copySymbol(location.symbol, meaning);
10102-
}
10103-
break;
1010410106
}
1010510107
memberFlags = location.flags;
1010610108
location = location.parent;
@@ -10237,7 +10239,7 @@ module ts {
1023710239
}
1023810240

1023910241
function getSymbolOfEntityNameOrPropertyAccessExpression(entityName: EntityName | PropertyAccessExpression): Symbol {
10240-
if (isDeclarationOrFunctionExpressionOrCatchVariableName(entityName)) {
10242+
if (isDeclarationName(entityName)) {
1024110243
return getSymbolOfNode(entityName.parent);
1024210244
}
1024310245

@@ -10302,7 +10304,7 @@ module ts {
1030210304
return undefined;
1030310305
}
1030410306

10305-
if (isDeclarationOrFunctionExpressionOrCatchVariableName(node)) {
10307+
if (isDeclarationName(node)) {
1030610308
// This is a declaration, call getSymbolOfNode
1030710309
return getSymbolOfNode(node.parent);
1030810310
}
@@ -10398,7 +10400,7 @@ module ts {
1039810400
return getTypeOfSymbol(symbol);
1039910401
}
1040010402

10401-
if (isDeclarationOrFunctionExpressionOrCatchVariableName(node)) {
10403+
if (isDeclarationName(node)) {
1040210404
var symbol = getSymbolInfo(node);
1040310405
return symbol && getTypeOfSymbol(symbol);
1040410406
}
@@ -11674,10 +11676,13 @@ module ts {
1167411676
}
1167511677
}
1167611678

11677-
function checkGrammarEvalOrArgumentsInStrictMode(contextNode: Node, identifier: Identifier): boolean {
11678-
if (contextNode && (contextNode.parserContextFlags & ParserContextFlags.StrictMode) && isEvalOrArgumentsIdentifier(identifier)) {
11679-
var name = declarationNameToString(identifier);
11680-
return grammarErrorOnNode(identifier, Diagnostics.Invalid_use_of_0_in_strict_mode, name);
11679+
function checkGrammarEvalOrArgumentsInStrictMode(contextNode: Node, name: Node): boolean {
11680+
if (name && name.kind === SyntaxKind.Identifier) {
11681+
var identifier = <Identifier>name;
11682+
if (contextNode && (contextNode.parserContextFlags & ParserContextFlags.StrictMode) && isEvalOrArgumentsIdentifier(identifier)) {
11683+
var nameText = declarationNameToString(identifier);
11684+
return grammarErrorOnNode(identifier, Diagnostics.Invalid_use_of_0_in_strict_mode, nameText);
11685+
}
1168111686
}
1168211687
}
1168311688

src/compiler/diagnosticInformationMap.generated.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ module ts {
99
Trailing_comma_not_allowed: { code: 1009, category: DiagnosticCategory.Error, key: "Trailing comma not allowed." },
1010
Asterisk_Slash_expected: { code: 1010, category: DiagnosticCategory.Error, key: "'*/' expected." },
1111
Unexpected_token: { code: 1012, category: DiagnosticCategory.Error, key: "Unexpected token." },
12-
Catch_clause_parameter_cannot_have_a_type_annotation: { code: 1013, category: DiagnosticCategory.Error, key: "Catch clause parameter cannot have a type annotation." },
1312
A_rest_parameter_must_be_last_in_a_parameter_list: { code: 1014, category: DiagnosticCategory.Error, key: "A rest parameter must be last in a parameter list." },
1413
Parameter_cannot_have_question_mark_and_initializer: { code: 1015, category: DiagnosticCategory.Error, key: "Parameter cannot have question mark and initializer." },
1514
A_required_parameter_cannot_follow_an_optional_parameter: { code: 1016, category: DiagnosticCategory.Error, key: "A required parameter cannot follow an optional parameter." },
@@ -153,6 +152,9 @@ module ts {
153152
External_module_0_has_no_default_export_or_export_assignment: { code: 1192, category: DiagnosticCategory.Error, key: "External module '{0}' has no default export or export assignment." },
154153
An_export_declaration_cannot_have_modifiers: { code: 1193, category: DiagnosticCategory.Error, key: "An export declaration cannot have modifiers." },
155154
Export_declarations_are_not_permitted_in_an_internal_module: { code: 1194, category: DiagnosticCategory.Error, key: "Export declarations are not permitted in an internal module." },
155+
Catch_clause_variable_name_must_be_an_identifier: { code: 1195, category: DiagnosticCategory.Error, key: "Catch clause variable name must be an identifier." },
156+
Catch_clause_variable_cannot_have_a_type_annotation: { code: 1196, category: DiagnosticCategory.Error, key: "Catch clause variable cannot have a type annotation." },
157+
Catch_clause_variable_cannot_have_an_initializer: { code: 1197, category: DiagnosticCategory.Error, key: "Catch clause variable cannot have an initializer." },
156158
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
157159
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." },
158160
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: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@
2727
"category": "Error",
2828
"code": 1012
2929
},
30-
"Catch clause parameter cannot have a type annotation.": {
31-
"category": "Error",
32-
"code": 1013
33-
},
3430
"A rest parameter must be last in a parameter list.": {
3531
"category": "Error",
3632
"code": 1014
@@ -603,6 +599,18 @@
603599
"category": "Error",
604600
"code": 1194
605601
},
602+
"Catch clause variable name must be an identifier.": {
603+
"category": "Error",
604+
"code": 1195
605+
},
606+
"Catch clause variable cannot have a type annotation.": {
607+
"category": "Error",
608+
"code": 1196
609+
},
610+
"Catch clause variable cannot have an initializer.": {
611+
"category": "Error",
612+
"code": 1197
613+
},
606614

607615
"Duplicate identifier '{0}'.": {
608616
"category": "Error",

src/compiler/emitter.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2545,8 +2545,6 @@ module ts {
25452545
return false;
25462546
case SyntaxKind.LabeledStatement:
25472547
return (<LabeledStatement>node.parent).label === node;
2548-
case SyntaxKind.CatchClause:
2549-
return (<CatchClause>node.parent).name === node;
25502548
}
25512549
}
25522550

@@ -3536,8 +3534,8 @@ module ts {
35363534
var endPos = emitToken(SyntaxKind.CatchKeyword, node.pos);
35373535
write(" ");
35383536
emitToken(SyntaxKind.OpenParenToken, endPos);
3539-
emit(node.name);
3540-
emitToken(SyntaxKind.CloseParenToken, node.name.end);
3537+
emit(node.variableDeclaration);
3538+
emitToken(SyntaxKind.CloseParenToken, node.variableDeclaration ? node.variableDeclaration.end : endPos);
35413539
write(" ");
35423540
emitBlock(node.block);
35433541
}

src/compiler/parser.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,7 @@ module ts {
222222
visitNode(cbNode, (<TryStatement>node).catchClause) ||
223223
visitNode(cbNode, (<TryStatement>node).finallyBlock);
224224
case SyntaxKind.CatchClause:
225-
return visitNode(cbNode, (<CatchClause>node).name) ||
226-
visitNode(cbNode, (<CatchClause>node).type) ||
225+
return visitNode(cbNode, (<CatchClause>node).variableDeclaration) ||
227226
visitNode(cbNode, (<CatchClause>node).block);
228227
case SyntaxKind.ClassDeclaration:
229228
return visitNodes(cbNodes, node.modifiers) ||
@@ -3973,9 +3972,10 @@ module ts {
39733972
function parseCatchClause(): CatchClause {
39743973
var result = <CatchClause>createNode(SyntaxKind.CatchClause);
39753974
parseExpected(SyntaxKind.CatchKeyword);
3976-
parseExpected(SyntaxKind.OpenParenToken);
3977-
result.name = parseIdentifier();
3978-
result.type = parseTypeAnnotation();
3975+
if (parseExpected(SyntaxKind.OpenParenToken)) {
3976+
result.variableDeclaration = parseVariableDeclaration();
3977+
}
3978+
39793979
parseExpected(SyntaxKind.CloseParenToken);
39803980
result.block = parseBlock(/*ignoreMissingOpenBrace:*/ false, /*checkForStrictMode:*/ false);
39813981
return finishNode(result);

src/compiler/types.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -814,9 +814,8 @@ module ts {
814814
finallyBlock?: Block;
815815
}
816816

817-
export interface CatchClause extends Declaration {
818-
name: Identifier;
819-
type?: TypeNode;
817+
export interface CatchClause extends Node {
818+
variableDeclaration: VariableDeclaration;
820819
block: Block;
821820
}
822821

src/compiler/utilities.ts

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,18 @@ module ts {
198198
return getBaseFileName(moduleName).replace(/\W/g, "_");
199199
}
200200

201+
export function isBlockOrCatchScoped(declaration: Declaration) {
202+
return (getCombinedNodeFlags(declaration) & NodeFlags.BlockScoped) !== 0 ||
203+
isCatchClauseVariableDeclaration(declaration);
204+
}
205+
206+
export function isCatchClauseVariableDeclaration(declaration: Declaration) {
207+
return declaration &&
208+
declaration.kind === SyntaxKind.VariableDeclaration &&
209+
declaration.parent &&
210+
declaration.parent.kind === SyntaxKind.CatchClause;
211+
}
212+
201213
// Return display name of an identifier
202214
// Computed property names will just be emitted as "[<expr>]", where <expr> is the source
203215
// text of the expression in the computed property.
@@ -687,31 +699,33 @@ module ts {
687699

688700
export function isDeclaration(node: Node): boolean {
689701
switch (node.kind) {
690-
case SyntaxKind.TypeParameter:
691-
case SyntaxKind.Parameter:
692-
case SyntaxKind.VariableDeclaration:
702+
case SyntaxKind.ArrowFunction:
693703
case SyntaxKind.BindingElement:
694-
case SyntaxKind.PropertyDeclaration:
695-
case SyntaxKind.PropertySignature:
696-
case SyntaxKind.PropertyAssignment:
697-
case SyntaxKind.ShorthandPropertyAssignment:
704+
case SyntaxKind.ClassDeclaration:
705+
case SyntaxKind.Constructor:
706+
case SyntaxKind.EnumDeclaration:
698707
case SyntaxKind.EnumMember:
699-
case SyntaxKind.MethodDeclaration:
700-
case SyntaxKind.MethodSignature:
708+
case SyntaxKind.ExportSpecifier:
701709
case SyntaxKind.FunctionDeclaration:
710+
case SyntaxKind.FunctionExpression:
702711
case SyntaxKind.GetAccessor:
703-
case SyntaxKind.SetAccessor:
704-
case SyntaxKind.Constructor:
705-
case SyntaxKind.ClassDeclaration:
706-
case SyntaxKind.InterfaceDeclaration:
707-
case SyntaxKind.TypeAliasDeclaration:
708-
case SyntaxKind.EnumDeclaration:
709-
case SyntaxKind.ModuleDeclaration:
710-
case SyntaxKind.ImportEqualsDeclaration:
711712
case SyntaxKind.ImportClause:
713+
case SyntaxKind.ImportEqualsDeclaration:
712714
case SyntaxKind.ImportSpecifier:
715+
case SyntaxKind.InterfaceDeclaration:
716+
case SyntaxKind.MethodDeclaration:
717+
case SyntaxKind.MethodSignature:
718+
case SyntaxKind.ModuleDeclaration:
713719
case SyntaxKind.NamespaceImport:
714-
case SyntaxKind.ExportSpecifier:
720+
case SyntaxKind.Parameter:
721+
case SyntaxKind.PropertyAssignment:
722+
case SyntaxKind.PropertyDeclaration:
723+
case SyntaxKind.PropertySignature:
724+
case SyntaxKind.SetAccessor:
725+
case SyntaxKind.ShorthandPropertyAssignment:
726+
case SyntaxKind.TypeAliasDeclaration:
727+
case SyntaxKind.TypeParameter:
728+
case SyntaxKind.VariableDeclaration:
715729
return true;
716730
}
717731
return false;
@@ -745,7 +759,7 @@ module ts {
745759
}
746760

747761
// True if the given identifier, string literal, or number literal is the name of a declaration node
748-
export function isDeclarationOrFunctionExpressionOrCatchVariableName(name: Node): boolean {
762+
export function isDeclarationName(name: Node): boolean {
749763
if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) {
750764
return false;
751765
}
@@ -757,14 +771,10 @@ module ts {
757771
}
758772
}
759773

760-
if (isDeclaration(parent) || parent.kind === SyntaxKind.FunctionExpression) {
774+
if (isDeclaration(parent)) {
761775
return (<Declaration>parent).name === name;
762776
}
763777

764-
if (parent.kind === SyntaxKind.CatchClause) {
765-
return (<CatchClause>parent).name === name;
766-
}
767-
768778
return false;
769779
}
770780

src/services/services.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4756,7 +4756,7 @@ module ts {
47564756

47574757
/** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */
47584758
function isWriteAccess(node: Node): boolean {
4759-
if (node.kind === SyntaxKind.Identifier && isDeclarationOrFunctionExpressionOrCatchVariableName(node)) {
4759+
if (node.kind === SyntaxKind.Identifier && isDeclarationName(node)) {
47604760
return true;
47614761
}
47624762

@@ -4918,7 +4918,7 @@ module ts {
49184918
else if (isInRightSideOfImport(node)) {
49194919
return getMeaningFromRightHandSideOfImportEquals(node);
49204920
}
4921-
else if (isDeclarationOrFunctionExpressionOrCatchVariableName(node)) {
4921+
else if (isDeclarationName(node)) {
49224922
return getMeaningFromDeclaration(node.parent);
49234923
}
49244924
else if (isTypeReference(node)) {

tests/baselines/reference/APISample_compile.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -673,9 +673,8 @@ declare module "typescript" {
673673
catchClause?: CatchClause;
674674
finallyBlock?: Block;
675675
}
676-
interface CatchClause extends Declaration {
677-
name: Identifier;
678-
type?: TypeNode;
676+
interface CatchClause extends Node {
677+
variableDeclaration: VariableDeclaration;
679678
block: Block;
680679
}
681680
interface ModuleElement extends Node {

0 commit comments

Comments
 (0)