Simplify how catch clauses are represented in our AST.

This commit is contained in:
Cyrus Najmabadi
2015-02-26 17:19:19 -08:00
parent 7d6c0f0893
commit 11772e75a7
22 changed files with 153 additions and 124 deletions
+2 -9
View File
@@ -342,14 +342,7 @@ module ts {
}
function bindCatchVariableDeclaration(node: CatchClause) {
var symbol = createSymbol(SymbolFlags.FunctionScopedVariable, node.name.text || "__missing");
addDeclarationToSymbol(symbol, node, SymbolFlags.FunctionScopedVariable);
var saveParent = parent;
var savedBlockScopeContainer = blockScopeContainer;
parent = blockScopeContainer = node;
forEachChild(node, bind);
parent = saveParent;
blockScopeContainer = savedBlockScopeContainer;
bindChildren(node, /*symbolKind:*/ 0, /*isBlockScopeContainer:*/ true);
}
function bindBlockScopedVariableDeclaration(node: Declaration) {
@@ -390,7 +383,7 @@ module ts {
if (isBindingPattern((<Declaration>node).name)) {
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
}
else if (getCombinedNodeFlags(node) & NodeFlags.BlockScoped) {
else if (isBlockOrCatchScoped(<Declaration>node)) {
bindBlockScopedVariableDeclaration(<Declaration>node);
}
else {
+29 -26
View File
@@ -416,13 +416,6 @@ module ts {
break loop;
}
break;
case SyntaxKind.CatchClause:
var id = (<CatchClause>location).name;
if (name === id.text) {
result = location.symbol;
break loop;
}
break;
}
lastLocation = location;
location = location.parent;
@@ -451,7 +444,8 @@ module ts {
}
if (result.flags & SymbolFlags.BlockScopedVariable) {
// Block-scoped variables cannot be used before their definition
var declaration = forEach(result.declarations, d => getCombinedNodeFlags(d) & NodeFlags.BlockScoped ? d : undefined);
var declaration = forEach(result.declarations, d => isBlockOrCatchScoped(d) ? d : undefined);
Debug.assert(declaration !== undefined, "Block-scoped variable declaration is undefined");
if (!isDefinedBefore(declaration, errorLocation)) {
error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationNameToString(declaration.name));
@@ -1994,7 +1988,7 @@ module ts {
}
// Handle catch clause variables
var declaration = symbol.valueDeclaration;
if (declaration.kind === SyntaxKind.CatchClause) {
if (declaration.parent.kind === SyntaxKind.CatchClause) {
return links.type = anyType;
}
// Handle variable, parameter or property
@@ -8926,18 +8920,29 @@ module ts {
var catchClause = node.catchClause;
if (catchClause) {
// Grammar checking
if (catchClause.type) {
var sourceFile = getSourceFileOfNode(node);
var colonStart = skipTrivia(sourceFile.text, catchClause.name.end);
grammarErrorAtPos(sourceFile, colonStart, ":".length, Diagnostics.Catch_clause_parameter_cannot_have_a_type_annotation);
if (catchClause.variableDeclaration) {
if (catchClause.variableDeclaration.name.kind !== SyntaxKind.Identifier) {
grammarErrorOnFirstToken(catchClause.variableDeclaration.name, Diagnostics.Catch_clause_variable_name_must_be_an_identifier);
}
else if (catchClause.variableDeclaration.type) {
grammarErrorOnFirstToken(catchClause.variableDeclaration.type, Diagnostics.Catch_clause_variable_cannot_have_a_type_annotation);
}
else if (catchClause.variableDeclaration.initializer) {
grammarErrorOnFirstToken(catchClause.variableDeclaration.initializer, Diagnostics.Catch_clause_variable_cannot_have_an_initializer);
}
else {
// It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the
// Catch production is eval or arguments
checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>catchClause.variableDeclaration.name);
}
}
// It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the
// Catch production is eval or arguments
checkGrammarEvalOrArgumentsInStrictMode(node, catchClause.name);
checkBlock(catchClause.block);
}
if (node.finallyBlock) checkBlock(node.finallyBlock);
if (node.finallyBlock) {
checkBlock(node.finallyBlock);
}
}
function checkIndexConstraints(type: Type) {
@@ -10049,11 +10054,6 @@ module ts {
copySymbol(location.symbol, meaning);
}
break;
case SyntaxKind.CatchClause:
if ((<CatchClause>location).name.text) {
copySymbol(location.symbol, meaning);
}
break;
}
memberFlags = location.flags;
location = location.parent;
@@ -11616,10 +11616,13 @@ module ts {
}
}
function checkGrammarEvalOrArgumentsInStrictMode(contextNode: Node, identifier: Identifier): boolean {
if (contextNode && (contextNode.parserContextFlags & ParserContextFlags.StrictMode) && isEvalOrArgumentsIdentifier(identifier)) {
var name = declarationNameToString(identifier);
return grammarErrorOnNode(identifier, Diagnostics.Invalid_use_of_0_in_strict_mode, name);
function checkGrammarEvalOrArgumentsInStrictMode(contextNode: Node, name: Node): boolean {
if (name && name.kind === SyntaxKind.Identifier) {
var identifier = <Identifier>name;
if (contextNode && (contextNode.parserContextFlags & ParserContextFlags.StrictMode) && isEvalOrArgumentsIdentifier(identifier)) {
var nameText = declarationNameToString(identifier);
return grammarErrorOnNode(identifier, Diagnostics.Invalid_use_of_0_in_strict_mode, nameText);
}
}
}
@@ -9,7 +9,6 @@ module ts {
Trailing_comma_not_allowed: { code: 1009, category: DiagnosticCategory.Error, key: "Trailing comma not allowed." },
Asterisk_Slash_expected: { code: 1010, category: DiagnosticCategory.Error, key: "'*/' expected." },
Unexpected_token: { code: 1012, category: DiagnosticCategory.Error, key: "Unexpected token." },
Catch_clause_parameter_cannot_have_a_type_annotation: { code: 1013, category: DiagnosticCategory.Error, key: "Catch clause parameter cannot have a type annotation." },
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." },
Parameter_cannot_have_question_mark_and_initializer: { code: 1015, category: DiagnosticCategory.Error, key: "Parameter cannot have question mark and initializer." },
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 {
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." },
An_export_declaration_cannot_have_modifiers: { code: 1193, category: DiagnosticCategory.Error, key: "An export declaration cannot have modifiers." },
Export_declarations_are_not_permitted_in_an_internal_module: { code: 1194, category: DiagnosticCategory.Error, key: "Export declarations are not permitted in an internal module." },
Catch_clause_variable_name_must_be_an_identifier: { code: 1195, category: DiagnosticCategory.Error, key: "Catch clause variable name must be an identifier." },
Catch_clause_variable_cannot_have_a_type_annotation: { code: 1196, category: DiagnosticCategory.Error, key: "Catch clause variable cannot have a type annotation." },
Catch_clause_variable_cannot_have_an_initializer: { code: 1197, category: DiagnosticCategory.Error, key: "Catch clause variable cannot have an initializer." },
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." },
+13 -5
View File
@@ -27,10 +27,6 @@
"category": "Error",
"code": 1012
},
"Catch clause parameter cannot have a type annotation.": {
"category": "Error",
"code": 1013
},
"A rest parameter must be last in a parameter list.": {
"category": "Error",
"code": 1014
@@ -603,6 +599,18 @@
"category": "Error",
"code": 1194
},
"Catch clause variable name must be an identifier.": {
"category": "Error",
"code": 1195
},
"Catch clause variable cannot have a type annotation.": {
"category": "Error",
"code": 1196
},
"Catch clause variable cannot have an initializer.": {
"category": "Error",
"code": 1197
},
"Duplicate identifier '{0}'.": {
"category": "Error",
@@ -1572,7 +1580,7 @@
"Exported type alias '{0}' has or is using private name '{1}'.": {
"category": "Error",
"code": 4081
},
},
"The current host does not support the '{0}' option.": {
"category": "Error",
"code": 5001
+4 -4
View File
@@ -2461,8 +2461,8 @@ module ts {
return false;
case SyntaxKind.LabeledStatement:
return (<LabeledStatement>node.parent).label === node;
case SyntaxKind.CatchClause:
return (<CatchClause>node.parent).name === node;
//case SyntaxKind.CatchClause:
// return (<CatchClause>node.parent).name === node;
}
}
@@ -3428,8 +3428,8 @@ module ts {
var endPos = emitToken(SyntaxKind.CatchKeyword, node.pos);
write(" ");
emitToken(SyntaxKind.OpenParenToken, endPos);
emit(node.name);
emitToken(SyntaxKind.CloseParenToken, node.name.end);
emit(node.variableDeclaration);
emitToken(SyntaxKind.CloseParenToken, node.variableDeclaration ? node.variableDeclaration.end : endPos);
write(" ");
emitBlock(node.block);
}
+5 -5
View File
@@ -222,8 +222,7 @@ module ts {
visitNode(cbNode, (<TryStatement>node).catchClause) ||
visitNode(cbNode, (<TryStatement>node).finallyBlock);
case SyntaxKind.CatchClause:
return visitNode(cbNode, (<CatchClause>node).name) ||
visitNode(cbNode, (<CatchClause>node).type) ||
return visitNode(cbNode, (<CatchClause>node).variableDeclaration) ||
visitNode(cbNode, (<CatchClause>node).block);
case SyntaxKind.ClassDeclaration:
return visitNodes(cbNodes, node.modifiers) ||
@@ -3973,9 +3972,10 @@ module ts {
function parseCatchClause(): CatchClause {
var result = <CatchClause>createNode(SyntaxKind.CatchClause);
parseExpected(SyntaxKind.CatchKeyword);
parseExpected(SyntaxKind.OpenParenToken);
result.name = parseIdentifier();
result.type = parseTypeAnnotation();
if (parseExpected(SyntaxKind.OpenParenToken)) {
result.variableDeclaration = parseVariableDeclaration();
}
parseExpected(SyntaxKind.CloseParenToken);
result.block = parseBlock(/*ignoreMissingOpenBrace:*/ false, /*checkForStrictMode:*/ false);
return finishNode(result);
+2 -3
View File
@@ -814,9 +814,8 @@ module ts {
finallyBlock?: Block;
}
export interface CatchClause extends Declaration {
name: Identifier;
type?: TypeNode;
export interface CatchClause extends Node {
variableDeclaration: VariableDeclaration;
block: Block;
}
+15 -3
View File
@@ -192,6 +192,18 @@ module ts {
return getBaseFileName(moduleName).replace(/\W/g, "_");
}
export function isBlockOrCatchScoped(declaration: Declaration) {
return (getCombinedNodeFlags(declaration) & NodeFlags.BlockScoped) !== 0 ||
isCatchClauseVariableDeclaration(declaration);
}
export function isCatchClauseVariableDeclaration(declaration: Declaration) {
return declaration &&
declaration.kind === SyntaxKind.VariableDeclaration &&
declaration.parent &&
declaration.parent.kind === SyntaxKind.CatchClause;
}
// Return display name of an identifier
// Computed property names will just be emitted as "[<expr>]", where <expr> is the source
// text of the expression in the computed property.
@@ -757,9 +769,9 @@ module ts {
return (<Declaration>parent).name === name;
}
if (parent.kind === SyntaxKind.CatchClause) {
return (<CatchClause>parent).name === name;
}
//if (parent.kind === SyntaxKind.CatchClause) {
// return (<CatchClause>parent).name === name;
//}
return false;
}
@@ -673,9 +673,8 @@ declare module "typescript" {
catchClause?: CatchClause;
finallyBlock?: Block;
}
interface CatchClause extends Declaration {
name: Identifier;
type?: TypeNode;
interface CatchClause extends Node {
variableDeclaration: VariableDeclaration;
block: Block;
}
interface ModuleElement extends Node {
@@ -2030,17 +2030,13 @@ declare module "typescript" {
>finallyBlock : Block
>Block : Block
}
interface CatchClause extends Declaration {
interface CatchClause extends Node {
>CatchClause : CatchClause
>Declaration : Declaration
>Node : Node
name: Identifier;
>name : Identifier
>Identifier : Identifier
type?: TypeNode;
>type : TypeNode
>TypeNode : TypeNode
variableDeclaration: VariableDeclaration;
>variableDeclaration : VariableDeclaration
>VariableDeclaration : VariableDeclaration
block: Block;
>block : Block
@@ -704,9 +704,8 @@ declare module "typescript" {
catchClause?: CatchClause;
finallyBlock?: Block;
}
interface CatchClause extends Declaration {
name: Identifier;
type?: TypeNode;
interface CatchClause extends Node {
variableDeclaration: VariableDeclaration;
block: Block;
}
interface ModuleElement extends Node {
@@ -2176,17 +2176,13 @@ declare module "typescript" {
>finallyBlock : Block
>Block : Block
}
interface CatchClause extends Declaration {
interface CatchClause extends Node {
>CatchClause : CatchClause
>Declaration : Declaration
>Node : Node
name: Identifier;
>name : Identifier
>Identifier : Identifier
type?: TypeNode;
>type : TypeNode
>TypeNode : TypeNode
variableDeclaration: VariableDeclaration;
>variableDeclaration : VariableDeclaration
>VariableDeclaration : VariableDeclaration
block: Block;
>block : Block
@@ -705,9 +705,8 @@ declare module "typescript" {
catchClause?: CatchClause;
finallyBlock?: Block;
}
interface CatchClause extends Declaration {
name: Identifier;
type?: TypeNode;
interface CatchClause extends Node {
variableDeclaration: VariableDeclaration;
block: Block;
}
interface ModuleElement extends Node {
@@ -2126,17 +2126,13 @@ declare module "typescript" {
>finallyBlock : Block
>Block : Block
}
interface CatchClause extends Declaration {
interface CatchClause extends Node {
>CatchClause : CatchClause
>Declaration : Declaration
>Node : Node
name: Identifier;
>name : Identifier
>Identifier : Identifier
type?: TypeNode;
>type : TypeNode
>TypeNode : TypeNode
variableDeclaration: VariableDeclaration;
>variableDeclaration : VariableDeclaration
>VariableDeclaration : VariableDeclaration
block: Block;
>block : Block
@@ -742,9 +742,8 @@ declare module "typescript" {
catchClause?: CatchClause;
finallyBlock?: Block;
}
interface CatchClause extends Declaration {
name: Identifier;
type?: TypeNode;
interface CatchClause extends Node {
variableDeclaration: VariableDeclaration;
block: Block;
}
interface ModuleElement extends Node {
@@ -2299,17 +2299,13 @@ declare module "typescript" {
>finallyBlock : Block
>Block : Block
}
interface CatchClause extends Declaration {
interface CatchClause extends Node {
>CatchClause : CatchClause
>Declaration : Declaration
>Node : Node
name: Identifier;
>name : Identifier
>Identifier : Identifier
type?: TypeNode;
>type : TypeNode
>TypeNode : TypeNode
variableDeclaration: VariableDeclaration;
>variableDeclaration : VariableDeclaration
>VariableDeclaration : VariableDeclaration
block: Block;
>block : Block
@@ -217,7 +217,15 @@
>:=> (line 28, col 8) to (line 28, col 22)
29 > } catch (e) {
~~~~~~~~~~~~~ => Pos: (416 to 428) SpanInfo: {"start":437,"length":15}
~~~~~~~~ => Pos: (416 to 423) SpanInfo: {"start":437,"length":15}
>if (obj.z < 10)
>:=> (line 30, col 8) to (line 30, col 23)
29 > } catch (e) {
~ => Pos: (424 to 424) SpanInfo: undefined
29 > } catch (e) {
~~~~ => Pos: (425 to 428) SpanInfo: {"start":437,"length":15}
>if (obj.z < 10)
>:=> (line 30, col 8) to (line 30, col 23)
--------------------------------
@@ -286,7 +294,15 @@
>:=> (line 37, col 8) to (line 37, col 25)
38 > } catch (e1) {
~~~~~~~~~~~~~~ => Pos: (581 to 594) SpanInfo: {"start":603,"length":10}
~~~~~~~~ => Pos: (581 to 588) SpanInfo: {"start":603,"length":10}
>var b = e1
>:=> (line 39, col 8) to (line 39, col 18)
38 > } catch (e1) {
~~ => Pos: (589 to 590) SpanInfo: undefined
38 > } catch (e1) {
~~~~ => Pos: (591 to 594) SpanInfo: {"start":603,"length":10}
>var b = e1
>:=> (line 39, col 8) to (line 39, col 18)
--------------------------------
@@ -24,7 +24,15 @@
>:=> (line 3, col 4) to (line 3, col 13)
4 >} catch (e) {
~~~~~~~~~~~~~ => Pos: (34 to 46) SpanInfo: {"start":51,"length":9}
~~~~~~~~ => Pos: (34 to 41) SpanInfo: {"start":51,"length":9}
>x = x - 1
>:=> (line 5, col 4) to (line 5, col 13)
4 >} catch (e) {
~ => Pos: (42 to 42) SpanInfo: undefined
4 >} catch (e) {
~~~~ => Pos: (43 to 46) SpanInfo: {"start":51,"length":9}
>x = x - 1
>:=> (line 5, col 4) to (line 5, col 13)
--------------------------------
@@ -94,7 +102,15 @@
--------------------------------
14 >catch (e)
~~~~~~~~~~ => Pos: (138 to 147) SpanInfo: {"start":154,"length":9}
~~~~~~~ => Pos: (138 to 144) SpanInfo: {"start":154,"length":9}
>x = x - 1
>:=> (line 16, col 4) to (line 16, col 13)
14 >catch (e)
~ => Pos: (145 to 145) SpanInfo: undefined
14 >catch (e)
~~ => Pos: (146 to 147) SpanInfo: {"start":154,"length":9}
>x = x - 1
>:=> (line 16, col 4) to (line 16, col 13)
--------------------------------
@@ -1,9 +1,9 @@
tests/cases/compiler/catchClauseWithTypeAnnotation.ts(2,11): error TS1013: Catch clause parameter cannot have a type annotation.
tests/cases/compiler/catchClauseWithTypeAnnotation.ts(2,13): error TS1196: Catch clause variable cannot have a type annotation.
==== tests/cases/compiler/catchClauseWithTypeAnnotation.ts (1 errors) ====
try {
} catch (e: any) {
~
!!! error TS1013: Catch clause parameter cannot have a type annotation.
~~~
!!! error TS1196: Catch clause variable cannot have a type annotation.
}
@@ -1,6 +1,6 @@
tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(8,21): error TS1013: Catch clause parameter cannot have a type annotation.
tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(9,21): error TS1013: Catch clause parameter cannot have a type annotation.
tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(10,21): error TS1013: Catch clause parameter cannot have a type annotation.
tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(8,23): error TS1196: Catch clause variable cannot have a type annotation.
tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(9,23): error TS1196: Catch clause variable cannot have a type annotation.
tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(10,23): error TS1196: Catch clause variable cannot have a type annotation.
==== tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts (3 errors) ====
@@ -12,14 +12,14 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(10,21):
// no type annotation allowed
try { } catch (z: any) { }
~
!!! error TS1013: Catch clause parameter cannot have a type annotation.
~~~
!!! error TS1196: Catch clause variable cannot have a type annotation.
try { } catch (a: number) { }
~
!!! error TS1013: Catch clause parameter cannot have a type annotation.
~~~~~~
!!! error TS1196: Catch clause variable cannot have a type annotation.
try { } catch (y: string) { }
~
!!! error TS1013: Catch clause parameter cannot have a type annotation.
~~~~~~
!!! error TS1196: Catch clause variable cannot have a type annotation.
}
@@ -1,10 +1,10 @@
tests/cases/conformance/parser/ecmascript5/CatchClauses/parserCatchClauseWithTypeAnnotation1.ts(2,11): error TS1013: Catch clause parameter cannot have a type annotation.
tests/cases/conformance/parser/ecmascript5/CatchClauses/parserCatchClauseWithTypeAnnotation1.ts(2,13): error TS1196: Catch clause variable cannot have a type annotation.
==== tests/cases/conformance/parser/ecmascript5/CatchClauses/parserCatchClauseWithTypeAnnotation1.ts (1 errors) ====
try {
} catch (e: Error) {
~
!!! error TS1013: Catch clause parameter cannot have a type annotation.
~~~~~
!!! error TS1196: Catch clause variable cannot have a type annotation.
}
@@ -6,4 +6,4 @@
goTo.marker();
verify.quickInfoExists();
verify.quickInfoIs("(var) e: any");
verify.quickInfoIs("(local var) e: any");