Move declaration list checking to the grammar checks.

This commit is contained in:
Cyrus Najmabadi 2014-11-19 02:11:17 -08:00
parent 7222fd34ec
commit 9170962998
13 changed files with 118 additions and 83 deletions

View File

@ -7531,10 +7531,13 @@ module ts {
// for (var VarDecl in Expr) Statement
// VarDecl must be a variable declaration without a type annotation that declares a variable of type Any,
// and Expr must be an expression of type Any, an object type, or a type parameter type.
if (node.declaration) {
checkVariableDeclaration(node.declaration);
if (node.declaration.type) {
error(node.declaration, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation);
if (node.declarations) {
if (node.declarations.length >= 1) {
var decl = node.declarations[0];
checkVariableDeclaration(decl);
if (decl.type) {
error(decl, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation);
}
}
}

View File

@ -1336,15 +1336,18 @@ module ts {
var endPos = emitToken(SyntaxKind.ForKeyword, node.pos);
write(" ");
endPos = emitToken(SyntaxKind.OpenParenToken, endPos);
if (node.declaration) {
if (node.declaration.flags & NodeFlags.Let) {
emitToken(SyntaxKind.LetKeyword, endPos);
if (node.declarations) {
if (node.declarations.length >= 1) {
var decl = node.declarations[0];
if (decl.flags & NodeFlags.Let) {
emitToken(SyntaxKind.LetKeyword, endPos);
}
else {
emitToken(SyntaxKind.VarKeyword, endPos);
}
write(" ");
emit(decl);
}
else {
emitToken(SyntaxKind.VarKeyword, endPos);
}
write(" ");
emit(node.declaration);
}
else {
emit(node.variable);

View File

@ -303,7 +303,7 @@ module ts {
child((<ForStatement>node).iterator) ||
child((<ForStatement>node).statement);
case SyntaxKind.ForInStatement:
return child((<ForInStatement>node).declaration) ||
return children((<ForInStatement>node).declarations) ||
child((<ForInStatement>node).variable) ||
child((<ForInStatement>node).expression) ||
child((<ForInStatement>node).statement);
@ -2750,27 +2750,12 @@ module ts {
if (token !== SyntaxKind.SemicolonToken) {
if (parseOptional(SyntaxKind.VarKeyword)) {
var declarations = parseVariableDeclarationList(0, /*noIn*/ true);
if (!declarations.length) {
error(Diagnostics.Variable_declaration_list_cannot_be_empty);
}
}
else if (parseOptional(SyntaxKind.LetKeyword)) {
var declarations = parseVariableDeclarationList(NodeFlags.Let, /*noIn*/ true);
if (!declarations.length) {
error(Diagnostics.Variable_declaration_list_cannot_be_empty);
}
if (languageVersion < ScriptTarget.ES6) {
grammarErrorAtPos(declarations.pos, declarations.end - declarations.pos, Diagnostics.let_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher);
}
}
else if (parseOptional(SyntaxKind.ConstKeyword)) {
var declarations = parseVariableDeclarationList(NodeFlags.Const, /*noIn*/ true);
if (!declarations.length) {
error(Diagnostics.Variable_declaration_list_cannot_be_empty);
}
if (languageVersion < ScriptTarget.ES6) {
grammarErrorAtPos(declarations.pos, declarations.end - declarations.pos, Diagnostics.const_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher);
}
}
else {
var varOrInit = parseExpression(true);
@ -2780,10 +2765,7 @@ module ts {
if (parseOptional(SyntaxKind.InKeyword)) {
var forInStatement = <ForInStatement>createNode(SyntaxKind.ForInStatement, pos);
if (declarations) {
if (declarations.length > 1) {
error(Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement);
}
forInStatement.declaration = declarations[0];
forInStatement.declarations = declarations;
}
else {
forInStatement.variable = varOrInit;
@ -4047,6 +4029,8 @@ module ts {
case SyntaxKind.ConstructorType: return visitConstructorType(<SignatureDeclaration>node);
case SyntaxKind.ConstructSignature: return visitConstructSignature(<SignatureDeclaration>node);
case SyntaxKind.EnumDeclaration: return visitEnumDeclaration(<EnumDeclaration>node);
case SyntaxKind.ForInStatement: return visitForInStatement(<ForInStatement>node);
case SyntaxKind.ForStatement: return visitForStatement(<ForStatement>node);
case SyntaxKind.FunctionDeclaration: return visitFunctionDeclaration(<FunctionLikeDeclaration>node);
case SyntaxKind.FunctionExpression: return visitFunctionExpression(<FunctionExpression>node);
case SyntaxKind.FunctionType: return visitFunctionType(<SignatureDeclaration>node);
@ -4215,6 +4199,21 @@ module ts {
return false;
}
function visitForInStatement(node: ForInStatement) {
checkVariableDeclarations(node.declarations) ||
checkForMoreThanOneDeclaration(node.declarations);
}
function visitForStatement(node: ForStatement) {
checkVariableDeclarations(node.declarations);
}
function checkForMoreThanOneDeclaration(declarations: NodeArray<VariableDeclaration>) {
if (declarations && declarations.length > 1) {
return grammarErrorOnNode(declarations[1], Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement);
}
}
function visitFunctionDeclaration(node: FunctionLikeDeclaration) {
checkTypeParameterList(node.typeParameters) ||
checkParameterList(node.parameters) ||
@ -4536,28 +4535,40 @@ module ts {
}
}
function visitVariableStatement(node: VariableStatement) {
if (checkForTrailingComma(node.declarations)) {
return;
}
function checkVariableDeclarations(declarations: NodeArray<VariableDeclaration>): boolean {
if (declarations) {
if (checkForTrailingComma(declarations)) {
return true;
}
if (!node.declarations.length) {
grammarErrorOnNode(node, Diagnostics.Variable_declaration_list_cannot_be_empty);
}
if (languageVersion < ScriptTarget.ES6) {
if (node.flags & NodeFlags.Let) {
grammarErrorOnNode(node, Diagnostics.let_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher);
if (!declarations.length) {
return grammarErrorAtPos(declarations.pos, declarations.end - declarations.pos, Diagnostics.Variable_declaration_list_cannot_be_empty);
}
else if (node.flags & NodeFlags.Const) {
grammarErrorOnNode(node, Diagnostics.const_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher);
var decl = declarations[0];
if (languageVersion < ScriptTarget.ES6) {
if (decl.flags & NodeFlags.Let) {
return grammarErrorOnNode(decl, Diagnostics.let_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher);
}
else if (decl.flags & NodeFlags.Const) {
return grammarErrorOnNode(decl, Diagnostics.const_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher);
}
}
}
else if (!allowLetAndConstDeclarations(node.parent)) {
}
function visitVariableStatement(node: VariableStatement) {
checkVariableDeclarations(node.declarations) ||
checkForDisallowedLetOrConstStatement(node);
}
function checkForDisallowedLetOrConstStatement(node: VariableStatement) {
if (!allowLetAndConstDeclarations(node.parent)) {
if (node.flags & NodeFlags.Let) {
grammarErrorOnNode(node, Diagnostics.let_declarations_can_only_be_declared_inside_a_block);
return grammarErrorOnNode(node, Diagnostics.let_declarations_can_only_be_declared_inside_a_block);
}
else if (node.flags & NodeFlags.Const) {
grammarErrorOnNode(node, Diagnostics.const_declarations_can_only_be_declared_inside_a_block);
return grammarErrorOnNode(node, Diagnostics.const_declarations_can_only_be_declared_inside_a_block);
}
}
}

View File

@ -539,7 +539,7 @@ module ts {
}
export interface ForInStatement extends IterationStatement {
declaration?: VariableDeclaration;
declarations?: NodeArray<VariableDeclaration>;
variable?: Expression;
expression: Expression;
}

View File

@ -1,17 +1,17 @@
tests/cases/compiler/constDeclarations-es5.ts(2,1): error TS1154: 'const' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/constDeclarations-es5.ts(3,1): error TS1154: 'const' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/constDeclarations-es5.ts(4,1): error TS1154: 'const' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/constDeclarations-es5.ts(2,7): error TS1154: 'const' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/constDeclarations-es5.ts(3,7): error TS1154: 'const' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/constDeclarations-es5.ts(4,7): error TS1154: 'const' declarations are only available when targeting ECMAScript 6 and higher.
==== tests/cases/compiler/constDeclarations-es5.ts (3 errors) ====
const z7 = false;
~~~~~~~~~~~~~~~~~
~~
!!! error TS1154: 'const' declarations are only available when targeting ECMAScript 6 and higher.
const z8: number = 23;
~~~~~~~~~~~~~~~~~~~~~~
~~
!!! error TS1154: 'const' declarations are only available when targeting ECMAScript 6 and higher.
const z9 = 0, z10 :string = "", z11 = null;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~
!!! error TS1154: 'const' declarations are only available when targeting ECMAScript 6 and higher.

View File

@ -1,27 +1,27 @@
tests/cases/compiler/letDeclarations-es5-1.ts(1,5): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5-1.ts(2,5): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5-1.ts(3,5): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5-1.ts(4,5): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5-1.ts(5,5): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5-1.ts(6,5): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5-1.ts(1,9): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5-1.ts(2,9): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5-1.ts(3,9): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5-1.ts(4,9): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5-1.ts(5,9): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5-1.ts(6,9): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
==== tests/cases/compiler/letDeclarations-es5-1.ts (6 errors) ====
let l1;
~~~~~~~
~~
!!! error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
let l2: number;
~~~~~~~~~~~~~~~
~~
!!! error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
let l3, l4, l5 :string, l6;
~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~
!!! error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
let l7 = false;
~~~~~~~~~~~~~~~
~~
!!! error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
let l8: number = 23;
~~~~~~~~~~~~~~~~~~~~
~~
!!! error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
let l9 = 0, l10 :string = "", l11 = null;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~
!!! error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.

View File

@ -1,22 +1,40 @@
tests/cases/compiler/letDeclarations-es5.ts(10,8): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5.ts(12,8): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5.ts(2,5): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5.ts(3,5): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5.ts(4,5): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5.ts(6,5): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5.ts(7,5): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5.ts(8,5): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5.ts(10,9): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/letDeclarations-es5.ts(12,9): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
==== tests/cases/compiler/letDeclarations-es5.ts (2 errors) ====
==== tests/cases/compiler/letDeclarations-es5.ts (8 errors) ====
let l1;
~~
!!! error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
let l2: number;
~~
!!! error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
let l3, l4, l5 :string, l6;
~~
!!! error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
let l7 = false;
~~
!!! error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
let l8: number = 23;
~~
!!! error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
let l9 = 0, l10 :string = "", l11 = null;
~~
!!! error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
for(let l11 in {}) { }
~~~~
~~~
!!! error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
for(let l12 = 0; l12 < 9; l12++) { }
~~~~~~~~
~~~
!!! error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.

View File

@ -1,10 +1,10 @@
tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement2.ts(1,10): error TS1123: Variable declaration list cannot be empty.
tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement2.ts(1,9): error TS1123: Variable declaration list cannot be empty.
tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement2.ts(1,13): error TS2304: Cannot find name 'X'.
==== tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement2.ts (2 errors) ====
for (var in X) {
~~
!!! error TS1123: Variable declaration list cannot be empty.
~
!!! error TS2304: Cannot find name 'X'.

View File

@ -1,10 +1,10 @@
tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement3.ts(1,18): error TS1091: Only a single variable declaration is allowed in a 'for...in' statement.
tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement3.ts(1,13): error TS1091: Only a single variable declaration is allowed in a 'for...in' statement.
tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement3.ts(1,18): error TS2304: Cannot find name 'X'.
==== tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement3.ts (2 errors) ====
for (var a, b in X) {
~
~
!!! error TS1091: Only a single variable declaration is allowed in a 'for...in' statement.
~
!!! error TS2304: Cannot find name 'X'.

View File

@ -1,10 +1,10 @@
tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement6.ts(1,26): error TS1091: Only a single variable declaration is allowed in a 'for...in' statement.
tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement6.ts(1,17): error TS1091: Only a single variable declaration is allowed in a 'for...in' statement.
tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement6.ts(1,26): error TS2304: Cannot find name 'X'.
==== tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement6.ts (2 errors) ====
for (var a = 1, b = 2 in X) {
~
~
!!! error TS1091: Only a single variable declaration is allowed in a 'for...in' statement.
~
!!! error TS2304: Cannot find name 'X'.

View File

@ -1,11 +1,11 @@
tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement7.ts(1,43): error TS1091: Only a single variable declaration is allowed in a 'for...in' statement.
tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement7.ts(1,25): error TS1091: Only a single variable declaration is allowed in a 'for...in' statement.
tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement7.ts(1,10): error TS2404: The left-hand side of a 'for...in' statement cannot use a type annotation.
tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement7.ts(1,43): error TS2304: Cannot find name 'X'.
==== tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement7.ts (3 errors) ====
for (var a: number = 1, b: string = "" in X) {
~
~
!!! error TS1091: Only a single variable declaration is allowed in a 'for...in' statement.
~
!!! error TS2404: The left-hand side of a 'for...in' statement cannot use a type annotation.

View File

@ -1,7 +1,7 @@
tests/cases/conformance/parser/ecmascript5/VariableDeclarations/parserVariableDeclaration6.ts(1,1): error TS1123: Variable declaration list cannot be empty.
tests/cases/conformance/parser/ecmascript5/VariableDeclarations/parserVariableDeclaration6.ts(1,4): error TS1123: Variable declaration list cannot be empty.
==== tests/cases/conformance/parser/ecmascript5/VariableDeclarations/parserVariableDeclaration6.ts (1 errors) ====
var
~~~
!!! error TS1123: Variable declaration list cannot be empty.

View File

@ -1,7 +1,7 @@
tests/cases/conformance/parser/ecmascript5/VariableDeclarations/parserVariableDeclaration8.ts(1,1): error TS1123: Variable declaration list cannot be empty.
tests/cases/conformance/parser/ecmascript5/VariableDeclarations/parserVariableDeclaration8.ts(1,4): error TS1123: Variable declaration list cannot be empty.
==== tests/cases/conformance/parser/ecmascript5/VariableDeclarations/parserVariableDeclaration8.ts (1 errors) ====
var ;
~~~~~
!!! error TS1123: Variable declaration list cannot be empty.