Parity sweep for for-in & for-of

This commit is contained in:
Jason Freeman 2015-02-17 12:37:14 -08:00
parent 2c4244d749
commit 1a3294a7d2
11 changed files with 51 additions and 20 deletions

View file

@ -495,6 +495,7 @@ module ts {
case SyntaxKind.CatchClause:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.SwitchStatement:
bindChildren(node, 0, /*isBlockScopeContainer*/ true);
break;

View file

@ -4612,6 +4612,7 @@ module ts {
case SyntaxKind.WhileStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.ReturnStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.SwitchStatement:
@ -8449,23 +8450,12 @@ module ts {
function checkForOfStatement(node: ForOfStatement) {
// TODO: not yet implemented
if (!checkGrammarForStatementInAmbientContext(node)) {
checkGrammarForOfStatement(node);
}
checkGrammarForOfStatement(node);
}
function checkForInStatement(node: ForInStatement) {
// Grammar checking
if (!checkGrammarForStatementInAmbientContext(node)) {
if (node.initializer.kind === SyntaxKind.VariableDeclarationList) {
var variableList = <VariableDeclarationList>node.initializer;
if (!checkGrammarVariableDeclarationList(variableList)) {
if (variableList.declarations.length > 1) {
grammarErrorOnFirstToken(variableList.declarations[1], Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement);
}
}
}
}
checkGrammarForInOrForOfStatement(node);
// TypeScript 1.0 spec (April 2014): 5.4
// In a 'for-in' statement of the form
@ -9568,6 +9558,7 @@ module ts {
case SyntaxKind.WhileStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.ContinueStatement:
case SyntaxKind.BreakStatement:
case SyntaxKind.ReturnStatement:
@ -10764,10 +10755,33 @@ module ts {
}
}
function checkGrammarForInOrForOfStatement(forInOrOfStatement: ForInStatement | ForOfStatement): boolean {
if (checkGrammarForStatementInAmbientContext(forInOrOfStatement)) {
return true;
}
if (forInOrOfStatement.initializer.kind === SyntaxKind.VariableDeclarationList) {
var variableList = <VariableDeclarationList>forInOrOfStatement.initializer;
if (!checkGrammarVariableDeclarationList(variableList)) {
if (variableList.declarations.length > 1) {
var keywordText = forInOrOfStatement.kind === SyntaxKind.ForInStatement ? "in" : "of";
return grammarErrorOnFirstToken(variableList.declarations[1], Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_0_statement, keywordText);
}
}
}
return false;
}
function checkGrammarForOfStatement(forOfStatement: ForOfStatement): boolean {
if (checkGrammarForInOrForOfStatement(forOfStatement)) {
return true;
}
if (languageVersion < ScriptTarget.ES6) {
return grammarErrorOnFirstToken(forOfStatement, Diagnostics.For_of_statements_are_only_available_when_targeting_ECMAScript_6_or_higher);
}
return false;
}
function checkGrammarAccessor(accessor: MethodDeclaration): boolean {
@ -10862,6 +10876,7 @@ module ts {
switch (node.kind) {
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
return true;
@ -11018,6 +11033,7 @@ module ts {
case SyntaxKind.WithStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
return false;
case SyntaxKind.LabeledStatement:
return allowLetAndConstDeclarations(parent.parent);

View file

@ -55,7 +55,7 @@ module ts {
An_accessor_cannot_be_declared_in_an_ambient_context: { code: 1086, category: DiagnosticCategory.Error, key: "An accessor cannot be declared in an ambient context." },
_0_modifier_cannot_appear_on_a_constructor_declaration: { code: 1089, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a constructor declaration." },
_0_modifier_cannot_appear_on_a_parameter: { code: 1090, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a parameter." },
Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement: { code: 1091, category: DiagnosticCategory.Error, key: "Only a single variable declaration is allowed in a 'for...in' statement." },
Only_a_single_variable_declaration_is_allowed_in_a_for_0_statement: { code: 1091, category: DiagnosticCategory.Error, key: "Only a single variable declaration is allowed in a 'for...{0}' statement." },
Type_parameters_cannot_appear_on_a_constructor_declaration: { code: 1092, category: DiagnosticCategory.Error, key: "Type parameters cannot appear on a constructor declaration." },
Type_annotation_cannot_appear_on_a_constructor_declaration: { code: 1093, category: DiagnosticCategory.Error, key: "Type annotation cannot appear on a constructor declaration." },
An_accessor_cannot_have_type_parameters: { code: 1094, category: DiagnosticCategory.Error, key: "An accessor cannot have type parameters." },

View file

@ -211,7 +211,7 @@
"category": "Error",
"code": 1090
},
"Only a single variable declaration is allowed in a 'for...in' statement.": {
"Only a single variable declaration is allowed in a 'for...{0}' statement.": {
"category": "Error",
"code": 1091
},

View file

@ -1602,7 +1602,7 @@ module ts {
}
// in the case where we're parsing the variable declarator of a 'for-in' statement, we
// are done if we see an 'in' keyword in front of us.
// are done if we see an 'in' keyword in front of us. Same with for-of
if (isInOrOfKeyword(token)) {
return true;
}
@ -1881,6 +1881,7 @@ module ts {
case SyntaxKind.BreakStatement:
case SyntaxKind.ContinueStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.WithStatement:

View file

@ -343,6 +343,7 @@ module ts {
case SyntaxKind.WhileStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseClause:
@ -560,7 +561,8 @@ module ts {
forStatement.condition === node ||
forStatement.iterator === node;
case SyntaxKind.ForInStatement:
var forInStatement = <ForInStatement>parent;
case SyntaxKind.ForOfStatement:
var forInStatement = <ForInStatement | ForOfStatement>parent;
return (forInStatement.initializer === node && forInStatement.initializer.kind !== SyntaxKind.VariableDeclarationList) ||
forInStatement.expression === node;
case SyntaxKind.TypeAssertionExpression:
@ -688,6 +690,7 @@ module ts {
case SyntaxKind.ExpressionStatement:
case SyntaxKind.EmptyStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.LabeledStatement:

View file

@ -151,8 +151,9 @@ module ts.BreakpointResolver {
return spanInForStatement(<ForStatement>node);
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
// span on for (a in ...)
return textSpan(node, findNextToken((<ForInStatement>node).expression, node));
return textSpan(node, findNextToken((<ForInStatement | ForOfStatement>node).expression, node));
case SyntaxKind.SwitchStatement:
// span on switch(...)
@ -261,7 +262,8 @@ module ts.BreakpointResolver {
function spanInVariableDeclaration(variableDeclaration: VariableDeclaration): TextSpan {
// If declaration of for in statement, just set the span in parent
if (variableDeclaration.parent.parent.kind === SyntaxKind.ForInStatement) {
if (variableDeclaration.parent.parent.kind === SyntaxKind.ForInStatement ||
variableDeclaration.parent.parent.kind === SyntaxKind.ForOfStatement) {
return spanInNode(variableDeclaration.parent.parent);
}
@ -362,6 +364,7 @@ module ts.BreakpointResolver {
case SyntaxKind.WhileStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
return spanInNodeIfStartsOnSameLine(block.parent, block.statements[0]);
// Set span on previous token if it starts on same line otherwise on the first statement of the block

View file

@ -592,6 +592,7 @@ module ts.formatting {
case SyntaxKind.SwitchStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.TryStatement:
case SyntaxKind.DoStatement:

View file

@ -359,6 +359,7 @@ module ts.formatting {
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.FunctionDeclaration:

View file

@ -61,6 +61,7 @@ module ts {
// to be the entire span of the parent.
if (parent.kind === SyntaxKind.DoStatement ||
parent.kind === SyntaxKind.ForInStatement ||
parent.kind === SyntaxKind.ForOfStatement ||
parent.kind === SyntaxKind.ForStatement ||
parent.kind === SyntaxKind.IfStatement ||
parent.kind === SyntaxKind.WhileStatement ||

View file

@ -3441,7 +3441,9 @@ module ts {
}
break;
case SyntaxKind.ForKeyword:
if (hasKind(node.parent, SyntaxKind.ForStatement) || hasKind(node.parent, SyntaxKind.ForInStatement)) {
if (hasKind(node.parent, SyntaxKind.ForStatement) ||
hasKind(node.parent, SyntaxKind.ForInStatement) ||
hasKind(node.parent, SyntaxKind.ForOfStatement)) {
return getLoopBreakContinueOccurrences(<IterationStatement>node.parent);
}
break;
@ -3718,6 +3720,7 @@ module ts {
switch (owner.kind) {
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
return getLoopBreakContinueOccurrences(<IterationStatement>owner)
@ -3762,6 +3765,7 @@ module ts {
// Fall through.
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.DoStatement:
if (!statement.label || isLabeledBy(node, statement.label.text)) {