Skip to content

Commit 11772e7

Browse files
Simplify how catch clauses are represented in our AST.
1 parent 7d6c0f0 commit 11772e7

22 files changed

+153
-124
lines changed

src/compiler/binder.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -342,14 +342,7 @@ module ts {
342342
}
343343

344344
function bindCatchVariableDeclaration(node: CatchClause) {
345-
var symbol = createSymbol(SymbolFlags.FunctionScopedVariable, node.name.text || "__missing");
346-
addDeclarationToSymbol(symbol, node, SymbolFlags.FunctionScopedVariable);
347-
var saveParent = parent;
348-
var savedBlockScopeContainer = blockScopeContainer;
349-
parent = blockScopeContainer = node;
350-
forEachChild(node, bind);
351-
parent = saveParent;
352-
blockScopeContainer = savedBlockScopeContainer;
345+
bindChildren(node, /*symbolKind:*/ 0, /*isBlockScopeContainer:*/ true);
353346
}
354347

355348
function bindBlockScopedVariableDeclaration(node: Declaration) {
@@ -390,7 +383,7 @@ module ts {
390383
if (isBindingPattern((<Declaration>node).name)) {
391384
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
392385
}
393-
else if (getCombinedNodeFlags(node) & NodeFlags.BlockScoped) {
386+
else if (isBlockOrCatchScoped(<Declaration>node)) {
394387
bindBlockScopedVariableDeclaration(<Declaration>node);
395388
}
396389
else {

src/compiler/checker.ts

Lines changed: 29 additions & 26 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
@@ -8926,18 +8920,29 @@ module ts {
89268920
var catchClause = node.catchClause;
89278921
if (catchClause) {
89288922
// Grammar checking
8929-
if (catchClause.type) {
8930-
var sourceFile = getSourceFileOfNode(node);
8931-
var colonStart = skipTrivia(sourceFile.text, catchClause.name.end);
8932-
grammarErrorAtPos(sourceFile, colonStart, ":".length, Diagnostics.Catch_clause_parameter_cannot_have_a_type_annotation);
8923+
if (catchClause.variableDeclaration) {
8924+
if (catchClause.variableDeclaration.name.kind !== SyntaxKind.Identifier) {
8925+
grammarErrorOnFirstToken(catchClause.variableDeclaration.name, Diagnostics.Catch_clause_variable_name_must_be_an_identifier);
8926+
}
8927+
else if (catchClause.variableDeclaration.type) {
8928+
grammarErrorOnFirstToken(catchClause.variableDeclaration.type, Diagnostics.Catch_clause_variable_cannot_have_a_type_annotation);
8929+
}
8930+
else if (catchClause.variableDeclaration.initializer) {
8931+
grammarErrorOnFirstToken(catchClause.variableDeclaration.initializer, Diagnostics.Catch_clause_variable_cannot_have_an_initializer);
8932+
}
8933+
else {
8934+
// It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the
8935+
// Catch production is eval or arguments
8936+
checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>catchClause.variableDeclaration.name);
8937+
}
89338938
}
8934-
// It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the
8935-
// Catch production is eval or arguments
8936-
checkGrammarEvalOrArgumentsInStrictMode(node, catchClause.name);
89378939

89388940
checkBlock(catchClause.block);
89398941
}
8940-
if (node.finallyBlock) checkBlock(node.finallyBlock);
8942+
8943+
if (node.finallyBlock) {
8944+
checkBlock(node.finallyBlock);
8945+
}
89418946
}
89428947

89438948
function checkIndexConstraints(type: Type) {
@@ -10049,11 +10054,6 @@ module ts {
1004910054
copySymbol(location.symbol, meaning);
1005010055
}
1005110056
break;
10052-
case SyntaxKind.CatchClause:
10053-
if ((<CatchClause>location).name.text) {
10054-
copySymbol(location.symbol, meaning);
10055-
}
10056-
break;
1005710057
}
1005810058
memberFlags = location.flags;
1005910059
location = location.parent;
@@ -11616,10 +11616,13 @@ module ts {
1161611616
}
1161711617
}
1161811618

11619-
function checkGrammarEvalOrArgumentsInStrictMode(contextNode: Node, identifier: Identifier): boolean {
11620-
if (contextNode && (contextNode.parserContextFlags & ParserContextFlags.StrictMode) && isEvalOrArgumentsIdentifier(identifier)) {
11621-
var name = declarationNameToString(identifier);
11622-
return grammarErrorOnNode(identifier, Diagnostics.Invalid_use_of_0_in_strict_mode, name);
11619+
function checkGrammarEvalOrArgumentsInStrictMode(contextNode: Node, name: Node): boolean {
11620+
if (name && name.kind === SyntaxKind.Identifier) {
11621+
var identifier = <Identifier>name;
11622+
if (contextNode && (contextNode.parserContextFlags & ParserContextFlags.StrictMode) && isEvalOrArgumentsIdentifier(identifier)) {
11623+
var nameText = declarationNameToString(identifier);
11624+
return grammarErrorOnNode(identifier, Diagnostics.Invalid_use_of_0_in_strict_mode, nameText);
11625+
}
1162311626
}
1162411627
}
1162511628

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: 13 additions & 5 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",
@@ -1572,7 +1580,7 @@
15721580
"Exported type alias '{0}' has or is using private name '{1}'.": {
15731581
"category": "Error",
15741582
"code": 4081
1575-
},
1583+
},
15761584
"The current host does not support the '{0}' option.": {
15771585
"category": "Error",
15781586
"code": 5001

src/compiler/emitter.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2461,8 +2461,8 @@ module ts {
24612461
return false;
24622462
case SyntaxKind.LabeledStatement:
24632463
return (<LabeledStatement>node.parent).label === node;
2464-
case SyntaxKind.CatchClause:
2465-
return (<CatchClause>node.parent).name === node;
2464+
//case SyntaxKind.CatchClause:
2465+
// return (<CatchClause>node.parent).name === node;
24662466
}
24672467
}
24682468

@@ -3428,8 +3428,8 @@ module ts {
34283428
var endPos = emitToken(SyntaxKind.CatchKeyword, node.pos);
34293429
write(" ");
34303430
emitToken(SyntaxKind.OpenParenToken, endPos);
3431-
emit(node.name);
3432-
emitToken(SyntaxKind.CloseParenToken, node.name.end);
3431+
emit(node.variableDeclaration);
3432+
emitToken(SyntaxKind.CloseParenToken, node.variableDeclaration ? node.variableDeclaration.end : endPos);
34333433
write(" ");
34343434
emitBlock(node.block);
34353435
}

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: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,18 @@ module ts {
192192
return getBaseFileName(moduleName).replace(/\W/g, "_");
193193
}
194194

195+
export function isBlockOrCatchScoped(declaration: Declaration) {
196+
return (getCombinedNodeFlags(declaration) & NodeFlags.BlockScoped) !== 0 ||
197+
isCatchClauseVariableDeclaration(declaration);
198+
}
199+
200+
export function isCatchClauseVariableDeclaration(declaration: Declaration) {
201+
return declaration &&
202+
declaration.kind === SyntaxKind.VariableDeclaration &&
203+
declaration.parent &&
204+
declaration.parent.kind === SyntaxKind.CatchClause;
205+
}
206+
195207
// Return display name of an identifier
196208
// Computed property names will just be emitted as "[<expr>]", where <expr> is the source
197209
// text of the expression in the computed property.
@@ -757,9 +769,9 @@ module ts {
757769
return (<Declaration>parent).name === name;
758770
}
759771

760-
if (parent.kind === SyntaxKind.CatchClause) {
761-
return (<CatchClause>parent).name === name;
762-
}
772+
//if (parent.kind === SyntaxKind.CatchClause) {
773+
// return (<CatchClause>parent).name === name;
774+
//}
763775

764776
return false;
765777
}

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 {

tests/baselines/reference/APISample_compile.types

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2030,17 +2030,13 @@ declare module "typescript" {
20302030
>finallyBlock : Block
20312031
>Block : Block
20322032
}
2033-
interface CatchClause extends Declaration {
2033+
interface CatchClause extends Node {
20342034
>CatchClause : CatchClause
2035-
>Declaration : Declaration
2036-
2037-
name: Identifier;
2038-
>name : Identifier
2039-
>Identifier : Identifier
2035+
>Node : Node
20402036

2041-
type?: TypeNode;
2042-
>type : TypeNode
2043-
>TypeNode : TypeNode
2037+
variableDeclaration: VariableDeclaration;
2038+
>variableDeclaration : VariableDeclaration
2039+
>VariableDeclaration : VariableDeclaration
20442040

20452041
block: Block;
20462042
>block : Block

0 commit comments

Comments
 (0)