Skip to content

Commit f4158ee

Browse files
Merge pull request microsoft#2162 from Microsoft/declarations
Simplify some places in the compiler where we have esoteric declarations.
2 parents 7b22880 + 7b7f497 commit f4158ee

29 files changed

+225
-150
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: 32 additions & 29 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;
@@ -10190,7 +10190,7 @@ module ts {
1019010190
}
1019110191

1019210192
function getSymbolOfEntityNameOrPropertyAccessExpression(entityName: EntityName | PropertyAccessExpression): Symbol {
10193-
if (isDeclarationOrFunctionExpressionOrCatchVariableName(entityName)) {
10193+
if (isDeclarationName(entityName)) {
1019410194
return getSymbolOfNode(entityName.parent);
1019510195
}
1019610196

@@ -10255,7 +10255,7 @@ module ts {
1025510255
return undefined;
1025610256
}
1025710257

10258-
if (isDeclarationOrFunctionExpressionOrCatchVariableName(node)) {
10258+
if (isDeclarationName(node)) {
1025910259
// This is a declaration, call getSymbolOfNode
1026010260
return getSymbolOfNode(node.parent);
1026110261
}
@@ -10351,7 +10351,7 @@ module ts {
1035110351
return getTypeOfSymbol(symbol);
1035210352
}
1035310353

10354-
if (isDeclarationOrFunctionExpressionOrCatchVariableName(node)) {
10354+
if (isDeclarationName(node)) {
1035510355
var symbol = getSymbolInfo(node);
1035610356
return symbol && getTypeOfSymbol(symbol);
1035710357
}
@@ -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: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2465,8 +2465,6 @@ module ts {
24652465
return false;
24662466
case SyntaxKind.LabeledStatement:
24672467
return (<LabeledStatement>node.parent).label === node;
2468-
case SyntaxKind.CatchClause:
2469-
return (<CatchClause>node.parent).name === node;
24702468
}
24712469
}
24722470

@@ -3443,8 +3441,8 @@ module ts {
34433441
var endPos = emitToken(SyntaxKind.CatchKeyword, node.pos);
34443442
write(" ");
34453443
emitToken(SyntaxKind.OpenParenToken, endPos);
3446-
emit(node.name);
3447-
emitToken(SyntaxKind.CloseParenToken, node.name.end);
3444+
emit(node.variableDeclaration);
3445+
emitToken(SyntaxKind.CloseParenToken, node.variableDeclaration ? node.variableDeclaration.end : endPos);
34483446
write(" ");
34493447
emitBlock(node.block);
34503448
}

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
@@ -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.
@@ -681,31 +693,33 @@ module ts {
681693

682694
export function isDeclaration(node: Node): boolean {
683695
switch (node.kind) {
684-
case SyntaxKind.TypeParameter:
685-
case SyntaxKind.Parameter:
686-
case SyntaxKind.VariableDeclaration:
696+
case SyntaxKind.ArrowFunction:
687697
case SyntaxKind.BindingElement:
688-
case SyntaxKind.PropertyDeclaration:
689-
case SyntaxKind.PropertySignature:
690-
case SyntaxKind.PropertyAssignment:
691-
case SyntaxKind.ShorthandPropertyAssignment:
698+
case SyntaxKind.ClassDeclaration:
699+
case SyntaxKind.Constructor:
700+
case SyntaxKind.EnumDeclaration:
692701
case SyntaxKind.EnumMember:
693-
case SyntaxKind.MethodDeclaration:
694-
case SyntaxKind.MethodSignature:
702+
case SyntaxKind.ExportSpecifier:
695703
case SyntaxKind.FunctionDeclaration:
704+
case SyntaxKind.FunctionExpression:
696705
case SyntaxKind.GetAccessor:
697-
case SyntaxKind.SetAccessor:
698-
case SyntaxKind.Constructor:
699-
case SyntaxKind.ClassDeclaration:
700-
case SyntaxKind.InterfaceDeclaration:
701-
case SyntaxKind.TypeAliasDeclaration:
702-
case SyntaxKind.EnumDeclaration:
703-
case SyntaxKind.ModuleDeclaration:
704-
case SyntaxKind.ImportEqualsDeclaration:
705706
case SyntaxKind.ImportClause:
707+
case SyntaxKind.ImportEqualsDeclaration:
706708
case SyntaxKind.ImportSpecifier:
709+
case SyntaxKind.InterfaceDeclaration:
710+
case SyntaxKind.MethodDeclaration:
711+
case SyntaxKind.MethodSignature:
712+
case SyntaxKind.ModuleDeclaration:
707713
case SyntaxKind.NamespaceImport:
708-
case SyntaxKind.ExportSpecifier:
714+
case SyntaxKind.Parameter:
715+
case SyntaxKind.PropertyAssignment:
716+
case SyntaxKind.PropertyDeclaration:
717+
case SyntaxKind.PropertySignature:
718+
case SyntaxKind.SetAccessor:
719+
case SyntaxKind.ShorthandPropertyAssignment:
720+
case SyntaxKind.TypeAliasDeclaration:
721+
case SyntaxKind.TypeParameter:
722+
case SyntaxKind.VariableDeclaration:
709723
return true;
710724
}
711725
return false;
@@ -739,7 +753,7 @@ module ts {
739753
}
740754

741755
// True if the given identifier, string literal, or number literal is the name of a declaration node
742-
export function isDeclarationOrFunctionExpressionOrCatchVariableName(name: Node): boolean {
756+
export function isDeclarationName(name: Node): boolean {
743757
if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) {
744758
return false;
745759
}
@@ -751,14 +765,10 @@ module ts {
751765
}
752766
}
753767

754-
if (isDeclaration(parent) || parent.kind === SyntaxKind.FunctionExpression) {
768+
if (isDeclaration(parent)) {
755769
return (<Declaration>parent).name === name;
756770
}
757771

758-
if (parent.kind === SyntaxKind.CatchClause) {
759-
return (<CatchClause>parent).name === name;
760-
}
761-
762772
return false;
763773
}
764774

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)