From 81b658805916e091de27676d46a86634c1dccf01 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 26 Feb 2015 16:11:27 -0800 Subject: [PATCH 1/7] Make isDeclaration return 'true' on FunctionExpressions. --- src/compiler/checker.ts | 6 +++--- src/compiler/utilities.ts | 5 +++-- src/services/services.ts | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d666da91fe0..19a2dae2424 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10190,7 +10190,7 @@ module ts { } function getSymbolOfEntityNameOrPropertyAccessExpression(entityName: EntityName | PropertyAccessExpression): Symbol { - if (isDeclarationOrFunctionExpressionOrCatchVariableName(entityName)) { + if (isDeclarationOrCatchVariableName(entityName)) { return getSymbolOfNode(entityName.parent); } @@ -10255,7 +10255,7 @@ module ts { return undefined; } - if (isDeclarationOrFunctionExpressionOrCatchVariableName(node)) { + if (isDeclarationOrCatchVariableName(node)) { // This is a declaration, call getSymbolOfNode return getSymbolOfNode(node.parent); } @@ -10351,7 +10351,7 @@ module ts { return getTypeOfSymbol(symbol); } - if (isDeclarationOrFunctionExpressionOrCatchVariableName(node)) { + if (isDeclarationOrCatchVariableName(node)) { var symbol = getSymbolInfo(node); return symbol && getTypeOfSymbol(symbol); } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index b53c0007248..489e985fb42 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -706,6 +706,7 @@ module ts { case SyntaxKind.ImportSpecifier: case SyntaxKind.NamespaceImport: case SyntaxKind.ExportSpecifier: + case SyntaxKind.FunctionExpression: return true; } return false; @@ -739,7 +740,7 @@ module ts { } // True if the given identifier, string literal, or number literal is the name of a declaration node - export function isDeclarationOrFunctionExpressionOrCatchVariableName(name: Node): boolean { + export function isDeclarationOrCatchVariableName(name: Node): boolean { if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) { return false; } @@ -751,7 +752,7 @@ module ts { } } - if (isDeclaration(parent) || parent.kind === SyntaxKind.FunctionExpression) { + if (isDeclaration(parent)) { return (parent).name === name; } diff --git a/src/services/services.ts b/src/services/services.ts index 58c1d08110a..5ee623fd3fa 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4756,7 +4756,7 @@ module ts { /** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */ function isWriteAccess(node: Node): boolean { - if (node.kind === SyntaxKind.Identifier && isDeclarationOrFunctionExpressionOrCatchVariableName(node)) { + if (node.kind === SyntaxKind.Identifier && isDeclarationOrCatchVariableName(node)) { return true; } @@ -4918,7 +4918,7 @@ module ts { else if (isInRightSideOfImport(node)) { return getMeaningFromRightHandSideOfImportEquals(node); } - else if (isDeclarationOrFunctionExpressionOrCatchVariableName(node)) { + else if (isDeclarationOrCatchVariableName(node)) { return getMeaningFromDeclaration(node.parent); } else if (isTypeReference(node)) { From 7d6c0f0893d76f11c6d68bd92f500355eaf89f83 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 26 Feb 2015 16:16:20 -0800 Subject: [PATCH 2/7] Add ArrowFunction and sort cases. --- src/compiler/utilities.ts | 41 ++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 489e985fb42..a6923e1eb94 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -681,32 +681,33 @@ module ts { export function isDeclaration(node: Node): boolean { switch (node.kind) { - case SyntaxKind.TypeParameter: - case SyntaxKind.Parameter: - case SyntaxKind.VariableDeclaration: + case SyntaxKind.ArrowFunction: case SyntaxKind.BindingElement: - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.PropertySignature: - case SyntaxKind.PropertyAssignment: - case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.EnumDeclaration: case SyntaxKind.EnumMember: + case SyntaxKind.ExportSpecifier: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.GetAccessor: + case SyntaxKind.ImportClause: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.InterfaceDeclaration: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - case SyntaxKind.Constructor: - case SyntaxKind.ClassDeclaration: - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.TypeAliasDeclaration: - case SyntaxKind.EnumDeclaration: case SyntaxKind.ModuleDeclaration: - case SyntaxKind.ImportEqualsDeclaration: - case SyntaxKind.ImportClause: - case SyntaxKind.ImportSpecifier: case SyntaxKind.NamespaceImport: - case SyntaxKind.ExportSpecifier: - case SyntaxKind.FunctionExpression: + case SyntaxKind.Parameter: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.SetAccessor: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.TypeParameter: + case SyntaxKind.VariableDeclaration: return true; } return false; From 11772e75a7bc3c091ad97fd752ee56053deba58e Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 26 Feb 2015 17:19:19 -0800 Subject: [PATCH 3/7] Simplify how catch clauses are represented in our AST. --- src/compiler/binder.ts | 11 +--- src/compiler/checker.ts | 55 ++++++++++--------- .../diagnosticInformationMap.generated.ts | 4 +- src/compiler/diagnosticMessages.json | 18 ++++-- src/compiler/emitter.ts | 8 +-- src/compiler/parser.ts | 10 ++-- src/compiler/types.ts | 5 +- src/compiler/utilities.ts | 18 +++++- .../baselines/reference/APISample_compile.js | 5 +- .../reference/APISample_compile.types | 14 ++--- tests/baselines/reference/APISample_linter.js | 5 +- .../reference/APISample_linter.types | 14 ++--- .../reference/APISample_transform.js | 5 +- .../reference/APISample_transform.types | 14 ++--- .../baselines/reference/APISample_watcher.js | 5 +- .../reference/APISample_watcher.types | 14 ++--- .../baselines/reference/bpSpan_stmts.baseline | 20 ++++++- .../reference/bpSpan_tryCatchFinally.baseline | 20 ++++++- .../catchClauseWithTypeAnnotation.errors.txt | 6 +- .../reference/invalidTryStatements.errors.txt | 18 +++--- ...rCatchClauseWithTypeAnnotation1.errors.txt | 6 +- .../fourslash/quickInfoOnCatchVariable.ts | 2 +- 22 files changed, 153 insertions(+), 124 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index a9d8b5f895a..9e36fc3e662 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -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((node).name)) { bindChildren(node, 0, /*isBlockScopeContainer*/ false); } - else if (getCombinedNodeFlags(node) & NodeFlags.BlockScoped) { + else if (isBlockOrCatchScoped(node)) { bindBlockScopedVariableDeclaration(node); } else { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 19a2dae2424..196871786e5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -416,13 +416,6 @@ module ts { break loop; } break; - case SyntaxKind.CatchClause: - var id = (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, 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 ((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 = 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); + } } } diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 7c53d70f591..88ae6eda361 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -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." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 7a7efe4e43c..e78ae2dad27 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -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 diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index e57255a776b..444b1dd508f 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2461,8 +2461,8 @@ module ts { return false; case SyntaxKind.LabeledStatement: return (node.parent).label === node; - case SyntaxKind.CatchClause: - return (node.parent).name === node; + //case SyntaxKind.CatchClause: + // return (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); } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 9dc8a475527..ff22f857cad 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -222,8 +222,7 @@ module ts { visitNode(cbNode, (node).catchClause) || visitNode(cbNode, (node).finallyBlock); case SyntaxKind.CatchClause: - return visitNode(cbNode, (node).name) || - visitNode(cbNode, (node).type) || + return visitNode(cbNode, (node).variableDeclaration) || visitNode(cbNode, (node).block); case SyntaxKind.ClassDeclaration: return visitNodes(cbNodes, node.modifiers) || @@ -3973,9 +3972,10 @@ module ts { function parseCatchClause(): CatchClause { var result = 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); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d1730ce1f1b..da8e1bdbe40 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -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; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index a6923e1eb94..dde0cece723 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -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 "[]", where is the source // text of the expression in the computed property. @@ -757,9 +769,9 @@ module ts { return (parent).name === name; } - if (parent.kind === SyntaxKind.CatchClause) { - return (parent).name === name; - } + //if (parent.kind === SyntaxKind.CatchClause) { + // return (parent).name === name; + //} return false; } diff --git a/tests/baselines/reference/APISample_compile.js b/tests/baselines/reference/APISample_compile.js index 5381b327504..7f5bc29906a 100644 --- a/tests/baselines/reference/APISample_compile.js +++ b/tests/baselines/reference/APISample_compile.js @@ -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 { diff --git a/tests/baselines/reference/APISample_compile.types b/tests/baselines/reference/APISample_compile.types index 106fa45e424..d93a48b7852 100644 --- a/tests/baselines/reference/APISample_compile.types +++ b/tests/baselines/reference/APISample_compile.types @@ -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 diff --git a/tests/baselines/reference/APISample_linter.js b/tests/baselines/reference/APISample_linter.js index 47183c920b4..36dd2421add 100644 --- a/tests/baselines/reference/APISample_linter.js +++ b/tests/baselines/reference/APISample_linter.js @@ -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 { diff --git a/tests/baselines/reference/APISample_linter.types b/tests/baselines/reference/APISample_linter.types index 776e7c0bbc1..7a282b61f42 100644 --- a/tests/baselines/reference/APISample_linter.types +++ b/tests/baselines/reference/APISample_linter.types @@ -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 diff --git a/tests/baselines/reference/APISample_transform.js b/tests/baselines/reference/APISample_transform.js index ea323ba927f..2ead5140261 100644 --- a/tests/baselines/reference/APISample_transform.js +++ b/tests/baselines/reference/APISample_transform.js @@ -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 { diff --git a/tests/baselines/reference/APISample_transform.types b/tests/baselines/reference/APISample_transform.types index 9abc0385d07..7a9d0523653 100644 --- a/tests/baselines/reference/APISample_transform.types +++ b/tests/baselines/reference/APISample_transform.types @@ -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 diff --git a/tests/baselines/reference/APISample_watcher.js b/tests/baselines/reference/APISample_watcher.js index 3e80b34ba0e..1d1f9f03d68 100644 --- a/tests/baselines/reference/APISample_watcher.js +++ b/tests/baselines/reference/APISample_watcher.js @@ -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 { diff --git a/tests/baselines/reference/APISample_watcher.types b/tests/baselines/reference/APISample_watcher.types index 79c2177ce79..55c48d1354b 100644 --- a/tests/baselines/reference/APISample_watcher.types +++ b/tests/baselines/reference/APISample_watcher.types @@ -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 diff --git a/tests/baselines/reference/bpSpan_stmts.baseline b/tests/baselines/reference/bpSpan_stmts.baseline index a81559ee9a5..7f6bf21b40b 100644 --- a/tests/baselines/reference/bpSpan_stmts.baseline +++ b/tests/baselines/reference/bpSpan_stmts.baseline @@ -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) -------------------------------- diff --git a/tests/baselines/reference/bpSpan_tryCatchFinally.baseline b/tests/baselines/reference/bpSpan_tryCatchFinally.baseline index 5a9e569f403..e5465b8812c 100644 --- a/tests/baselines/reference/bpSpan_tryCatchFinally.baseline +++ b/tests/baselines/reference/bpSpan_tryCatchFinally.baseline @@ -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) -------------------------------- diff --git a/tests/baselines/reference/catchClauseWithTypeAnnotation.errors.txt b/tests/baselines/reference/catchClauseWithTypeAnnotation.errors.txt index d3eea6619b6..5bc7339d2fc 100644 --- a/tests/baselines/reference/catchClauseWithTypeAnnotation.errors.txt +++ b/tests/baselines/reference/catchClauseWithTypeAnnotation.errors.txt @@ -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. } \ No newline at end of file diff --git a/tests/baselines/reference/invalidTryStatements.errors.txt b/tests/baselines/reference/invalidTryStatements.errors.txt index 4dacdb8f4b6..a2f8a7bac0c 100644 --- a/tests/baselines/reference/invalidTryStatements.errors.txt +++ b/tests/baselines/reference/invalidTryStatements.errors.txt @@ -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. } \ No newline at end of file diff --git a/tests/baselines/reference/parserCatchClauseWithTypeAnnotation1.errors.txt b/tests/baselines/reference/parserCatchClauseWithTypeAnnotation1.errors.txt index 73b97ac5573..a1f1d1fd6c7 100644 --- a/tests/baselines/reference/parserCatchClauseWithTypeAnnotation1.errors.txt +++ b/tests/baselines/reference/parserCatchClauseWithTypeAnnotation1.errors.txt @@ -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. } \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoOnCatchVariable.ts b/tests/cases/fourslash/quickInfoOnCatchVariable.ts index d03b5d7b8b6..5d0af595e91 100644 --- a/tests/cases/fourslash/quickInfoOnCatchVariable.ts +++ b/tests/cases/fourslash/quickInfoOnCatchVariable.ts @@ -6,4 +6,4 @@ goTo.marker(); verify.quickInfoExists(); -verify.quickInfoIs("(var) e: any"); +verify.quickInfoIs("(local var) e: any"); From 9125aa5192071774172c89d29a647dd97e46eeea Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 26 Feb 2015 17:26:33 -0800 Subject: [PATCH 4/7] Rename method. --- src/compiler/checker.ts | 6 +++--- src/compiler/utilities.ts | 6 +----- src/services/services.ts | 4 ++-- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 196871786e5..918090b3a94 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10190,7 +10190,7 @@ module ts { } function getSymbolOfEntityNameOrPropertyAccessExpression(entityName: EntityName | PropertyAccessExpression): Symbol { - if (isDeclarationOrCatchVariableName(entityName)) { + if (isDeclarationName(entityName)) { return getSymbolOfNode(entityName.parent); } @@ -10255,7 +10255,7 @@ module ts { return undefined; } - if (isDeclarationOrCatchVariableName(node)) { + if (isDeclarationName(node)) { // This is a declaration, call getSymbolOfNode return getSymbolOfNode(node.parent); } @@ -10351,7 +10351,7 @@ module ts { return getTypeOfSymbol(symbol); } - if (isDeclarationOrCatchVariableName(node)) { + if (isDeclarationName(node)) { var symbol = getSymbolInfo(node); return symbol && getTypeOfSymbol(symbol); } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index dde0cece723..01def791c02 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -753,7 +753,7 @@ module ts { } // True if the given identifier, string literal, or number literal is the name of a declaration node - export function isDeclarationOrCatchVariableName(name: Node): boolean { + export function isDeclarationName(name: Node): boolean { if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) { return false; } @@ -769,10 +769,6 @@ module ts { return (parent).name === name; } - //if (parent.kind === SyntaxKind.CatchClause) { - // return (parent).name === name; - //} - return false; } diff --git a/src/services/services.ts b/src/services/services.ts index 5ee623fd3fa..c13ae22718b 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4756,7 +4756,7 @@ module ts { /** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */ function isWriteAccess(node: Node): boolean { - if (node.kind === SyntaxKind.Identifier && isDeclarationOrCatchVariableName(node)) { + if (node.kind === SyntaxKind.Identifier && isDeclarationName(node)) { return true; } @@ -4918,7 +4918,7 @@ module ts { else if (isInRightSideOfImport(node)) { return getMeaningFromRightHandSideOfImportEquals(node); } - else if (isDeclarationOrCatchVariableName(node)) { + else if (isDeclarationName(node)) { return getMeaningFromDeclaration(node.parent); } else if (isTypeReference(node)) { From e2d9ea51eb615023dcaa18f5ca250f63cf8cf737 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 26 Feb 2015 17:27:18 -0800 Subject: [PATCH 5/7] Add test for catch variables with initializers. --- .../reference/catchClauseWithInitializer1.errors.txt | 10 ++++++++++ .../reference/catchClauseWithInitializer1.js | 11 +++++++++++ tests/cases/compiler/catchClauseWithInitializer1.ts | 4 ++++ 3 files changed, 25 insertions(+) create mode 100644 tests/baselines/reference/catchClauseWithInitializer1.errors.txt create mode 100644 tests/baselines/reference/catchClauseWithInitializer1.js create mode 100644 tests/cases/compiler/catchClauseWithInitializer1.ts diff --git a/tests/baselines/reference/catchClauseWithInitializer1.errors.txt b/tests/baselines/reference/catchClauseWithInitializer1.errors.txt new file mode 100644 index 00000000000..b13644f4d83 --- /dev/null +++ b/tests/baselines/reference/catchClauseWithInitializer1.errors.txt @@ -0,0 +1,10 @@ +tests/cases/compiler/catchClauseWithInitializer1.ts(3,12): error TS1197: Catch clause variable cannot have an initializer. + + +==== tests/cases/compiler/catchClauseWithInitializer1.ts (1 errors) ==== + try { + } + catch (e = 1) { + ~ +!!! error TS1197: Catch clause variable cannot have an initializer. + } \ No newline at end of file diff --git a/tests/baselines/reference/catchClauseWithInitializer1.js b/tests/baselines/reference/catchClauseWithInitializer1.js new file mode 100644 index 00000000000..5cb89a567f1 --- /dev/null +++ b/tests/baselines/reference/catchClauseWithInitializer1.js @@ -0,0 +1,11 @@ +//// [catchClauseWithInitializer1.ts] +try { +} +catch (e = 1) { +} + +//// [catchClauseWithInitializer1.js] +try { +} +catch (e = 1) { +} diff --git a/tests/cases/compiler/catchClauseWithInitializer1.ts b/tests/cases/compiler/catchClauseWithInitializer1.ts new file mode 100644 index 00000000000..320a2813170 --- /dev/null +++ b/tests/cases/compiler/catchClauseWithInitializer1.ts @@ -0,0 +1,4 @@ +try { +} +catch (e = 1) { +} \ No newline at end of file From 27e888284dd925a09be3a3f7c1b88b11d9bc6b8a Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 26 Feb 2015 17:37:01 -0800 Subject: [PATCH 6/7] CR feedback. --- src/compiler/emitter.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 444b1dd508f..e922803c0d4 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2461,8 +2461,6 @@ module ts { return false; case SyntaxKind.LabeledStatement: return (node.parent).label === node; - //case SyntaxKind.CatchClause: - // return (node.parent).name === node; } } From 7b7f49725d7b51bebdbb5acccc3caefc3fc7ce9d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 26 Feb 2015 17:42:46 -0800 Subject: [PATCH 7/7] Adding test. --- .../catchClauseWithBindingPattern1.errors.txt | 10 ++++++++++ .../reference/catchClauseWithBindingPattern1.js | 11 +++++++++++ .../cases/compiler/catchClauseWithBindingPattern1.ts | 4 ++++ 3 files changed, 25 insertions(+) create mode 100644 tests/baselines/reference/catchClauseWithBindingPattern1.errors.txt create mode 100644 tests/baselines/reference/catchClauseWithBindingPattern1.js create mode 100644 tests/cases/compiler/catchClauseWithBindingPattern1.ts diff --git a/tests/baselines/reference/catchClauseWithBindingPattern1.errors.txt b/tests/baselines/reference/catchClauseWithBindingPattern1.errors.txt new file mode 100644 index 00000000000..0b7482850e5 --- /dev/null +++ b/tests/baselines/reference/catchClauseWithBindingPattern1.errors.txt @@ -0,0 +1,10 @@ +tests/cases/compiler/catchClauseWithBindingPattern1.ts(3,8): error TS1195: Catch clause variable name must be an identifier. + + +==== tests/cases/compiler/catchClauseWithBindingPattern1.ts (1 errors) ==== + try { + } + catch ({a}) { + ~ +!!! error TS1195: Catch clause variable name must be an identifier. + } \ No newline at end of file diff --git a/tests/baselines/reference/catchClauseWithBindingPattern1.js b/tests/baselines/reference/catchClauseWithBindingPattern1.js new file mode 100644 index 00000000000..bbdc259946c --- /dev/null +++ b/tests/baselines/reference/catchClauseWithBindingPattern1.js @@ -0,0 +1,11 @@ +//// [catchClauseWithBindingPattern1.ts] +try { +} +catch ({a}) { +} + +//// [catchClauseWithBindingPattern1.js] +try { +} +catch (a = (void 0).a) { +} diff --git a/tests/cases/compiler/catchClauseWithBindingPattern1.ts b/tests/cases/compiler/catchClauseWithBindingPattern1.ts new file mode 100644 index 00000000000..dbd0f81c576 --- /dev/null +++ b/tests/cases/compiler/catchClauseWithBindingPattern1.ts @@ -0,0 +1,4 @@ +try { +} +catch ({a}) { +} \ No newline at end of file