Update AstBuilder to generate new for statement structure
... if control flow or spread collection entries are enabled. Change-Id: I8718c1f7a649b7a2a7c9e376a6bf67c1df0542cf Reviewed-on: https://dart-review.googlesource.com/c/91320 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
@@ -596,7 +596,8 @@ abstract class AstFactory {
|
||||
* Returns a newly created for statement.
|
||||
*/
|
||||
ForStatement2 forStatement2(
|
||||
{Token forKeyword,
|
||||
{Token awaitKeyword,
|
||||
Token forKeyword,
|
||||
Token leftParenthesis,
|
||||
ForLoopParts forLoopParts,
|
||||
Token rightParenthesis,
|
||||
|
||||
@@ -872,22 +872,6 @@ class AstBuilder extends StackListener {
|
||||
assert(optional(';', leftSeparator));
|
||||
assert(updateExpressionCount >= 0);
|
||||
|
||||
push(forKeyword);
|
||||
push(leftParen);
|
||||
push(leftSeparator);
|
||||
push(updateExpressionCount);
|
||||
}
|
||||
|
||||
@override
|
||||
void endForControlFlow(Token rightParenthesis) {
|
||||
debugEvent("endForControlFlow");
|
||||
var entry = pop();
|
||||
|
||||
int updateExpressionCount = pop();
|
||||
Token leftSeparator = pop();
|
||||
Token leftParenthesis = pop();
|
||||
Token forToken = pop();
|
||||
|
||||
List<Expression> updates = popTypedList(updateExpressionCount);
|
||||
Statement conditionStatement = pop();
|
||||
Object initializerPart = pop();
|
||||
@@ -901,8 +885,7 @@ class AstBuilder extends StackListener {
|
||||
rightSeparator = (conditionStatement as EmptyStatement).semicolon;
|
||||
}
|
||||
|
||||
ForLoopParts forLoopParts;
|
||||
Expression initializer;
|
||||
ForParts forLoopParts;
|
||||
if (initializerPart is VariableDeclarationStatement) {
|
||||
forLoopParts = ast.forPartsWithDeclarations(
|
||||
variables: initializerPart.variables,
|
||||
@@ -912,9 +895,8 @@ class AstBuilder extends StackListener {
|
||||
updaters: updates,
|
||||
);
|
||||
} else {
|
||||
initializer = initializerPart as Expression;
|
||||
forLoopParts = ast.forPartsWithExpression(
|
||||
initialization: initializer,
|
||||
initialization: initializerPart as Expression,
|
||||
leftSeparator: leftSeparator,
|
||||
condition: condition,
|
||||
rightSeparator: rightSeparator,
|
||||
@@ -922,8 +904,20 @@ class AstBuilder extends StackListener {
|
||||
);
|
||||
}
|
||||
|
||||
pushForControlFlowInfo(
|
||||
null, forToken, leftParenthesis, forLoopParts, entry);
|
||||
push(forKeyword);
|
||||
push(leftParen);
|
||||
push(forLoopParts);
|
||||
}
|
||||
|
||||
@override
|
||||
void endForControlFlow(Token token) {
|
||||
debugEvent("endForControlFlow");
|
||||
var entry = pop();
|
||||
ForParts forLoopParts = pop();
|
||||
Token leftParen = pop();
|
||||
Token forToken = pop();
|
||||
|
||||
pushForControlFlowInfo(null, forToken, leftParen, forLoopParts, entry);
|
||||
}
|
||||
|
||||
void pushForControlFlowInfo(Token awaitToken, Token forToken,
|
||||
@@ -942,44 +936,38 @@ class AstBuilder extends StackListener {
|
||||
void endForStatement(Token endToken) {
|
||||
debugEvent("ForStatement");
|
||||
Statement body = pop();
|
||||
|
||||
int updateExpressionCount = pop();
|
||||
Token leftSeparator = pop();
|
||||
ForParts forLoopParts = pop();
|
||||
Token leftParen = pop();
|
||||
Token forKeyword = pop();
|
||||
Token forToken = pop();
|
||||
|
||||
List<Expression> updates = popTypedList(updateExpressionCount);
|
||||
Statement conditionStatement = pop();
|
||||
Object initializerPart = pop();
|
||||
|
||||
VariableDeclarationList variableList;
|
||||
Expression initializer;
|
||||
if (initializerPart is VariableDeclarationStatement) {
|
||||
variableList = initializerPart.variables;
|
||||
if (enableControlFlowCollections || enableSpreadCollections) {
|
||||
push(ast.forStatement2(
|
||||
forKeyword: forToken,
|
||||
leftParenthesis: leftParen,
|
||||
forLoopParts: forLoopParts,
|
||||
rightParenthesis: leftParen.endGroup,
|
||||
body: body,
|
||||
));
|
||||
} else {
|
||||
initializer = initializerPart as Expression;
|
||||
VariableDeclarationList variableList;
|
||||
Expression initializer;
|
||||
if (forLoopParts is ForPartsWithDeclarations) {
|
||||
variableList = forLoopParts.variables;
|
||||
} else {
|
||||
initializer = (forLoopParts as ForPartsWithExpression).initialization;
|
||||
}
|
||||
push(ast.forStatement(
|
||||
forToken,
|
||||
leftParen,
|
||||
variableList,
|
||||
initializer,
|
||||
forLoopParts.leftSeparator,
|
||||
forLoopParts.condition,
|
||||
forLoopParts.rightSeparator,
|
||||
forLoopParts.updaters,
|
||||
leftParen?.endGroup,
|
||||
body));
|
||||
}
|
||||
|
||||
Expression condition;
|
||||
Token rightSeparator;
|
||||
if (conditionStatement is ExpressionStatement) {
|
||||
condition = conditionStatement.expression;
|
||||
rightSeparator = conditionStatement.semicolon;
|
||||
} else {
|
||||
rightSeparator = (conditionStatement as EmptyStatement).semicolon;
|
||||
}
|
||||
|
||||
push(ast.forStatement(
|
||||
forKeyword,
|
||||
leftParen,
|
||||
variableList,
|
||||
initializer,
|
||||
leftSeparator,
|
||||
condition,
|
||||
rightSeparator,
|
||||
updates,
|
||||
leftParen?.endGroup,
|
||||
body));
|
||||
}
|
||||
|
||||
void handleLiteralList(
|
||||
@@ -1358,26 +1346,10 @@ class AstBuilder extends StackListener {
|
||||
assert(optional('(', leftParenthesis));
|
||||
assert(optional('in', inKeyword) || optional(':', inKeyword));
|
||||
|
||||
push(awaitToken ?? NullValue.AwaitToken);
|
||||
push(forToken);
|
||||
push(leftParenthesis);
|
||||
push(inKeyword);
|
||||
}
|
||||
|
||||
@override
|
||||
void endForInControlFlow(Token rightParenthesis) {
|
||||
debugEvent("endForInControlFlow");
|
||||
var entry = pop();
|
||||
|
||||
Token inKeyword = pop();
|
||||
Token leftParenthesis = pop();
|
||||
Token forToken = pop();
|
||||
Token awaitToken = pop(NullValue.AwaitToken);
|
||||
|
||||
Expression iterator = pop();
|
||||
Object variableOrDeclaration = pop();
|
||||
|
||||
ForLoopParts forLoopParts;
|
||||
ForEachParts forLoopParts;
|
||||
if (variableOrDeclaration is VariableDeclarationStatement) {
|
||||
VariableDeclarationList variableList = variableOrDeclaration.variables;
|
||||
forLoopParts = ast.forEachPartsWithDeclaration(
|
||||
@@ -1408,6 +1380,22 @@ class AstBuilder extends StackListener {
|
||||
);
|
||||
}
|
||||
|
||||
push(awaitToken ?? NullValue.AwaitToken);
|
||||
push(forToken);
|
||||
push(leftParenthesis);
|
||||
push(forLoopParts);
|
||||
}
|
||||
|
||||
@override
|
||||
void endForInControlFlow(Token token) {
|
||||
debugEvent("endForInControlFlow");
|
||||
|
||||
var entry = pop();
|
||||
ForEachParts forLoopParts = pop();
|
||||
Token leftParenthesis = pop();
|
||||
Token forToken = pop();
|
||||
Token awaitToken = pop(NullValue.AwaitToken);
|
||||
|
||||
pushForControlFlowInfo(
|
||||
awaitToken, forToken, leftParenthesis, forLoopParts, entry);
|
||||
}
|
||||
@@ -1417,48 +1405,38 @@ class AstBuilder extends StackListener {
|
||||
debugEvent("ForInExpression");
|
||||
|
||||
Statement body = pop();
|
||||
|
||||
Token inKeyword = pop();
|
||||
ForEachParts forLoopParts = pop();
|
||||
Token leftParenthesis = pop();
|
||||
Token forToken = pop();
|
||||
Token awaitToken = pop(NullValue.AwaitToken);
|
||||
|
||||
Expression iterator = pop();
|
||||
Object variableOrDeclaration = pop();
|
||||
if (variableOrDeclaration is VariableDeclarationStatement) {
|
||||
VariableDeclarationList variableList = variableOrDeclaration.variables;
|
||||
if (enableControlFlowCollections || enableSpreadCollections) {
|
||||
push(ast.forStatement2(
|
||||
awaitKeyword: awaitToken,
|
||||
forKeyword: forToken,
|
||||
leftParenthesis: leftParenthesis,
|
||||
forLoopParts: forLoopParts,
|
||||
rightParenthesis: leftParenthesis.endGroup,
|
||||
body: body,
|
||||
));
|
||||
} else if (forLoopParts is ForEachPartsWithDeclaration) {
|
||||
push(ast.forEachStatementWithDeclaration(
|
||||
awaitToken,
|
||||
forToken,
|
||||
leftParenthesis,
|
||||
ast.declaredIdentifier(
|
||||
variableList.documentationComment,
|
||||
variableList.metadata,
|
||||
variableList.keyword,
|
||||
variableList.type,
|
||||
variableList.variables.first.name),
|
||||
inKeyword,
|
||||
iterator,
|
||||
forLoopParts.loopVariable,
|
||||
forLoopParts.inKeyword,
|
||||
forLoopParts.iterable,
|
||||
leftParenthesis?.endGroup,
|
||||
body));
|
||||
} else {
|
||||
if (variableOrDeclaration is! SimpleIdentifier) {
|
||||
// Parser has already reported the error.
|
||||
if (!leftParenthesis.next.isIdentifier) {
|
||||
parser.rewriter.insertToken(
|
||||
leftParenthesis,
|
||||
new SyntheticStringToken(
|
||||
TokenType.IDENTIFIER, '', leftParenthesis.next.charOffset));
|
||||
}
|
||||
variableOrDeclaration = ast.simpleIdentifier(leftParenthesis.next);
|
||||
}
|
||||
push(ast.forEachStatementWithReference(
|
||||
awaitToken,
|
||||
forToken,
|
||||
leftParenthesis,
|
||||
variableOrDeclaration,
|
||||
inKeyword,
|
||||
iterator,
|
||||
(forLoopParts as ForEachPartsWithIdentifier).identifier,
|
||||
forLoopParts.inKeyword,
|
||||
forLoopParts.iterable,
|
||||
leftParenthesis?.endGroup,
|
||||
body));
|
||||
}
|
||||
|
||||
@@ -710,15 +710,15 @@ class ForwardingTestListener extends ForwardingListener {
|
||||
}
|
||||
|
||||
@override
|
||||
void endForControlFlow(Token rightParenthesis) {
|
||||
void endForControlFlow(Token token) {
|
||||
end('ForControlFlow');
|
||||
super.endForControlFlow(rightParenthesis);
|
||||
super.endForControlFlow(token);
|
||||
}
|
||||
|
||||
@override
|
||||
void endForInControlFlow(Token rightParenthesis) {
|
||||
void endForInControlFlow(Token token) {
|
||||
end('ForControlFlow');
|
||||
super.endForInControlFlow(rightParenthesis);
|
||||
super.endForInControlFlow(token);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1477,8 +1477,20 @@ class FastaParserTestCase
|
||||
|
||||
@override
|
||||
Statement parseStatement(String source,
|
||||
{bool enableLazyAssignmentOperators, int expectedEndOffset}) {
|
||||
{bool enableLazyAssignmentOperators,
|
||||
int expectedEndOffset,
|
||||
bool parseSetLiterals = false,
|
||||
bool parseSpreadCollections = false,
|
||||
bool parseControlFlowCollections = false,
|
||||
bool inAsync = false}) {
|
||||
createParser(source, expectedEndOffset: expectedEndOffset);
|
||||
_parserProxy.fastaParser.enableSetLiterals = parseSetLiterals;
|
||||
_parserProxy.astBuilder.enableSpreadCollections = parseSpreadCollections;
|
||||
_parserProxy.astBuilder.enableControlFlowCollections =
|
||||
parseControlFlowCollections;
|
||||
if (inAsync) {
|
||||
_parserProxy.fastaParser.asyncState = AsyncModifier.Async;
|
||||
}
|
||||
Statement statement = _parserProxy.parseStatement2();
|
||||
assertErrors(codes: NO_ERROR_COMPARISON);
|
||||
return statement;
|
||||
@@ -1762,6 +1774,21 @@ class RecoveryParserTest_Fasta extends FastaParserTestCase
|
||||
]);
|
||||
}
|
||||
|
||||
void test_incompleteForEach2() {
|
||||
ForStatement2 statement = parseStatement('for (String item i) {}',
|
||||
parseControlFlowCollections: true);
|
||||
listener.assertErrors([
|
||||
expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 4),
|
||||
expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 1)
|
||||
]);
|
||||
expect(statement.toSource(), 'for (String item; i;) {}');
|
||||
ForPartsWithDeclarations forLoopParts = statement.forLoopParts;
|
||||
expect(forLoopParts.leftSeparator, isNotNull);
|
||||
expect(forLoopParts.leftSeparator.type, TokenType.SEMICOLON);
|
||||
expect(forLoopParts.rightSeparator, isNotNull);
|
||||
expect(forLoopParts.rightSeparator.type, TokenType.SEMICOLON);
|
||||
}
|
||||
|
||||
void test_invalidTypeParameters_super() {
|
||||
parseCompilationUnit('class C<X super Y> {}', errors: [
|
||||
// TODO(danrubel): Improve recovery.
|
||||
@@ -1865,6 +1892,304 @@ class StatementParserTest_Fasta extends FastaParserTestCase
|
||||
}
|
||||
}
|
||||
|
||||
void test_parseForStatement_each_await2() {
|
||||
ForStatement2 forStatement = parseStatement(
|
||||
'await for (element in list) {}',
|
||||
inAsync: true,
|
||||
parseControlFlowCollections: true,
|
||||
);
|
||||
assertNoErrors();
|
||||
expect(forStatement.awaitKeyword, isNotNull);
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
expect(forStatement.leftParenthesis, isNotNull);
|
||||
ForEachPartsWithIdentifier forLoopParts = forStatement.forLoopParts;
|
||||
expect(forLoopParts.identifier, isNotNull);
|
||||
expect(forLoopParts.inKeyword, isNotNull);
|
||||
expect(forLoopParts.iterable, isNotNull);
|
||||
expect(forStatement.rightParenthesis, isNotNull);
|
||||
expect(forStatement.body, isNotNull);
|
||||
}
|
||||
|
||||
void test_parseForStatement_each_genericFunctionType2() {
|
||||
ForStatement2 forStatement = parseStatement(
|
||||
'for (void Function<T>(T) element in list) {}',
|
||||
parseControlFlowCollections: true,
|
||||
);
|
||||
assertNoErrors();
|
||||
expect(forStatement.awaitKeyword, isNull);
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
expect(forStatement.leftParenthesis, isNotNull);
|
||||
ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
|
||||
expect(forLoopParts.loopVariable, isNotNull);
|
||||
expect(forLoopParts.inKeyword, isNotNull);
|
||||
expect(forLoopParts.iterable, isNotNull);
|
||||
expect(forStatement.rightParenthesis, isNotNull);
|
||||
expect(forStatement.body, isNotNull);
|
||||
}
|
||||
|
||||
void test_parseForStatement_each_identifier2() {
|
||||
ForStatement2 forStatement = parseStatement(
|
||||
'for (element in list) {}',
|
||||
parseControlFlowCollections: true,
|
||||
);
|
||||
assertNoErrors();
|
||||
expect(forStatement.awaitKeyword, isNull);
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
expect(forStatement.leftParenthesis, isNotNull);
|
||||
ForEachPartsWithIdentifier forLoopParts = forStatement.forLoopParts;
|
||||
expect(forLoopParts.identifier, isNotNull);
|
||||
expect(forLoopParts.inKeyword, isNotNull);
|
||||
expect(forLoopParts.iterable, isNotNull);
|
||||
expect(forStatement.rightParenthesis, isNotNull);
|
||||
expect(forStatement.body, isNotNull);
|
||||
}
|
||||
|
||||
void test_parseForStatement_each_noType_metadata2() {
|
||||
ForStatement2 forStatement = parseStatement(
|
||||
'for (@A var element in list) {}',
|
||||
parseControlFlowCollections: true,
|
||||
);
|
||||
assertNoErrors();
|
||||
expect(forStatement.awaitKeyword, isNull);
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
expect(forStatement.leftParenthesis, isNotNull);
|
||||
ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
|
||||
expect(forLoopParts.loopVariable, isNotNull);
|
||||
expect(forLoopParts.loopVariable.metadata, hasLength(1));
|
||||
expect(forLoopParts.inKeyword, isNotNull);
|
||||
expect(forLoopParts.iterable, isNotNull);
|
||||
expect(forStatement.rightParenthesis, isNotNull);
|
||||
expect(forStatement.body, isNotNull);
|
||||
}
|
||||
|
||||
void test_parseForStatement_each_type2() {
|
||||
ForStatement2 forStatement = parseStatement(
|
||||
'for (A element in list) {}',
|
||||
parseControlFlowCollections: true,
|
||||
);
|
||||
assertNoErrors();
|
||||
expect(forStatement.awaitKeyword, isNull);
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
expect(forStatement.leftParenthesis, isNotNull);
|
||||
ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
|
||||
expect(forLoopParts.loopVariable, isNotNull);
|
||||
expect(forLoopParts.inKeyword, isNotNull);
|
||||
expect(forLoopParts.iterable, isNotNull);
|
||||
expect(forStatement.rightParenthesis, isNotNull);
|
||||
expect(forStatement.body, isNotNull);
|
||||
}
|
||||
|
||||
void test_parseForStatement_each_var2() {
|
||||
ForStatement2 forStatement = parseStatement(
|
||||
'for (var element in list) {}',
|
||||
parseControlFlowCollections: true,
|
||||
);
|
||||
assertNoErrors();
|
||||
expect(forStatement.awaitKeyword, isNull);
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
expect(forStatement.leftParenthesis, isNotNull);
|
||||
ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
|
||||
expect(forLoopParts.loopVariable, isNotNull);
|
||||
expect(forLoopParts.inKeyword, isNotNull);
|
||||
expect(forLoopParts.iterable, isNotNull);
|
||||
expect(forStatement.rightParenthesis, isNotNull);
|
||||
expect(forStatement.body, isNotNull);
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_c2() {
|
||||
ForStatement2 forStatement = parseStatement(
|
||||
'for (; i < count;) {}',
|
||||
parseControlFlowCollections: true,
|
||||
);
|
||||
assertNoErrors();
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
expect(forStatement.leftParenthesis, isNotNull);
|
||||
ForPartsWithExpression forLoopParts = forStatement.forLoopParts;
|
||||
expect(forLoopParts.initialization, isNull);
|
||||
expect(forLoopParts.leftSeparator, isNotNull);
|
||||
expect(forLoopParts.condition, isNotNull);
|
||||
expect(forLoopParts.rightSeparator, isNotNull);
|
||||
expect(forLoopParts.updaters, hasLength(0));
|
||||
expect(forStatement.rightParenthesis, isNotNull);
|
||||
expect(forStatement.body, isNotNull);
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_cu2() {
|
||||
ForStatement2 forStatement = parseStatement(
|
||||
'for (; i < count; i++) {}',
|
||||
parseControlFlowCollections: true,
|
||||
);
|
||||
assertNoErrors();
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
expect(forStatement.leftParenthesis, isNotNull);
|
||||
ForPartsWithExpression forLoopParts = forStatement.forLoopParts;
|
||||
expect(forLoopParts.initialization, isNull);
|
||||
expect(forLoopParts.leftSeparator, isNotNull);
|
||||
expect(forLoopParts.condition, isNotNull);
|
||||
expect(forLoopParts.rightSeparator, isNotNull);
|
||||
expect(forLoopParts.updaters, hasLength(1));
|
||||
expect(forStatement.rightParenthesis, isNotNull);
|
||||
expect(forStatement.body, isNotNull);
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_ecu2() {
|
||||
ForStatement2 forStatement = parseStatement(
|
||||
'for (i--; i < count; i++) {}',
|
||||
parseSpreadCollections: true,
|
||||
);
|
||||
assertNoErrors();
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
expect(forStatement.leftParenthesis, isNotNull);
|
||||
ForPartsWithExpression forLoopParts = forStatement.forLoopParts;
|
||||
expect(forLoopParts.initialization, isNotNull);
|
||||
expect(forLoopParts.leftSeparator, isNotNull);
|
||||
expect(forLoopParts.condition, isNotNull);
|
||||
expect(forLoopParts.rightSeparator, isNotNull);
|
||||
expect(forLoopParts.updaters, hasLength(1));
|
||||
expect(forStatement.rightParenthesis, isNotNull);
|
||||
expect(forStatement.body, isNotNull);
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_i2() {
|
||||
ForStatement2 forStatement = parseStatement(
|
||||
'for (var i = 0;;) {}',
|
||||
parseSpreadCollections: true,
|
||||
);
|
||||
assertNoErrors();
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
expect(forStatement.leftParenthesis, isNotNull);
|
||||
ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
|
||||
VariableDeclarationList variables = forLoopParts.variables;
|
||||
expect(variables, isNotNull);
|
||||
expect(variables.metadata, hasLength(0));
|
||||
expect(variables.variables, hasLength(1));
|
||||
expect(forLoopParts.leftSeparator, isNotNull);
|
||||
expect(forLoopParts.condition, isNull);
|
||||
expect(forLoopParts.rightSeparator, isNotNull);
|
||||
expect(forLoopParts.updaters, hasLength(0));
|
||||
expect(forStatement.rightParenthesis, isNotNull);
|
||||
expect(forStatement.body, isNotNull);
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_i_withMetadata2() {
|
||||
ForStatement2 forStatement = parseStatement(
|
||||
'for (@A var i = 0;;) {}',
|
||||
parseSpreadCollections: true,
|
||||
);
|
||||
assertNoErrors();
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
expect(forStatement.leftParenthesis, isNotNull);
|
||||
ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
|
||||
VariableDeclarationList variables = forLoopParts.variables;
|
||||
expect(variables, isNotNull);
|
||||
expect(variables.metadata, hasLength(1));
|
||||
expect(variables.variables, hasLength(1));
|
||||
expect(forLoopParts.leftSeparator, isNotNull);
|
||||
expect(forLoopParts.condition, isNull);
|
||||
expect(forLoopParts.rightSeparator, isNotNull);
|
||||
expect(forLoopParts.updaters, hasLength(0));
|
||||
expect(forStatement.rightParenthesis, isNotNull);
|
||||
expect(forStatement.body, isNotNull);
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_ic2() {
|
||||
ForStatement2 forStatement = parseStatement(
|
||||
'for (var i = 0; i < count;) {}',
|
||||
parseSpreadCollections: true,
|
||||
);
|
||||
assertNoErrors();
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
expect(forStatement.leftParenthesis, isNotNull);
|
||||
ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
|
||||
VariableDeclarationList variables = forLoopParts.variables;
|
||||
expect(variables, isNotNull);
|
||||
expect(variables.variables, hasLength(1));
|
||||
expect(forLoopParts.leftSeparator, isNotNull);
|
||||
expect(forLoopParts.condition, isNotNull);
|
||||
expect(forLoopParts.rightSeparator, isNotNull);
|
||||
expect(forLoopParts.updaters, hasLength(0));
|
||||
expect(forStatement.rightParenthesis, isNotNull);
|
||||
expect(forStatement.body, isNotNull);
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_icu2() {
|
||||
ForStatement2 forStatement = parseStatement(
|
||||
'for (var i = 0; i < count; i++) {}',
|
||||
parseSpreadCollections: true,
|
||||
);
|
||||
assertNoErrors();
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
expect(forStatement.leftParenthesis, isNotNull);
|
||||
ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
|
||||
VariableDeclarationList variables = forLoopParts.variables;
|
||||
expect(variables, isNotNull);
|
||||
expect(variables.variables, hasLength(1));
|
||||
expect(forLoopParts.leftSeparator, isNotNull);
|
||||
expect(forLoopParts.condition, isNotNull);
|
||||
expect(forLoopParts.rightSeparator, isNotNull);
|
||||
expect(forLoopParts.updaters, hasLength(1));
|
||||
expect(forStatement.rightParenthesis, isNotNull);
|
||||
expect(forStatement.body, isNotNull);
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_iicuu2() {
|
||||
ForStatement2 forStatement = parseStatement(
|
||||
'for (int i = 0, j = count; i < j; i++, j--) {}',
|
||||
parseSpreadCollections: true,
|
||||
);
|
||||
assertNoErrors();
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
expect(forStatement.leftParenthesis, isNotNull);
|
||||
ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
|
||||
VariableDeclarationList variables = forLoopParts.variables;
|
||||
expect(variables, isNotNull);
|
||||
expect(variables.variables, hasLength(2));
|
||||
expect(forLoopParts.leftSeparator, isNotNull);
|
||||
expect(forLoopParts.condition, isNotNull);
|
||||
expect(forLoopParts.rightSeparator, isNotNull);
|
||||
expect(forLoopParts.updaters, hasLength(2));
|
||||
expect(forStatement.rightParenthesis, isNotNull);
|
||||
expect(forStatement.body, isNotNull);
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_iu2() {
|
||||
ForStatement2 forStatement = parseStatement(
|
||||
'for (var i = 0;; i++) {}',
|
||||
parseSpreadCollections: true,
|
||||
);
|
||||
assertNoErrors();
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
expect(forStatement.leftParenthesis, isNotNull);
|
||||
ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
|
||||
VariableDeclarationList variables = forLoopParts.variables;
|
||||
expect(variables, isNotNull);
|
||||
expect(variables.variables, hasLength(1));
|
||||
expect(forLoopParts.leftSeparator, isNotNull);
|
||||
expect(forLoopParts.condition, isNull);
|
||||
expect(forLoopParts.rightSeparator, isNotNull);
|
||||
expect(forLoopParts.updaters, hasLength(1));
|
||||
expect(forStatement.rightParenthesis, isNotNull);
|
||||
expect(forStatement.body, isNotNull);
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_u2() {
|
||||
ForStatement2 forStatement = parseStatement(
|
||||
'for (;; i++) {}',
|
||||
parseSpreadCollections: true,
|
||||
);
|
||||
assertNoErrors();
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
expect(forStatement.leftParenthesis, isNotNull);
|
||||
ForPartsWithExpression forLoopParts = forStatement.forLoopParts;
|
||||
expect(forLoopParts.initialization, isNull);
|
||||
expect(forLoopParts.leftSeparator, isNotNull);
|
||||
expect(forLoopParts.condition, isNull);
|
||||
expect(forLoopParts.rightSeparator, isNotNull);
|
||||
expect(forLoopParts.updaters, hasLength(1));
|
||||
expect(forStatement.rightParenthesis, isNotNull);
|
||||
expect(forStatement.body, isNotNull);
|
||||
}
|
||||
|
||||
void test_partial_typeArg1_34850() {
|
||||
var unit = parseCompilationUnit('<bar<', errors: [
|
||||
expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
|
||||
|
||||
@@ -10860,6 +10860,8 @@ class C {
|
||||
}
|
||||
|
||||
void test_incompleteForEach() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
ForStatement statement = parseStatement('for (String item i) {}');
|
||||
listener.assertErrors([
|
||||
expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 4),
|
||||
@@ -14571,6 +14573,8 @@ main() {
|
||||
}
|
||||
|
||||
void test_parseForStatement_each_await() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
String code = 'await for (element in list) {}';
|
||||
var forStatement = _parseAsyncStatement(code) as ForEachStatement;
|
||||
assertNoErrors();
|
||||
@@ -14586,6 +14590,8 @@ main() {
|
||||
}
|
||||
|
||||
void test_parseForStatement_each_genericFunctionType() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
var forStatement =
|
||||
parseStatement('for (void Function<T>(T) element in list) {}')
|
||||
as ForEachStatement;
|
||||
@@ -14602,6 +14608,8 @@ main() {
|
||||
}
|
||||
|
||||
void test_parseForStatement_each_identifier() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
var forStatement =
|
||||
parseStatement('for (element in list) {}') as ForEachStatement;
|
||||
assertNoErrors();
|
||||
@@ -14617,6 +14625,8 @@ main() {
|
||||
}
|
||||
|
||||
void test_parseForStatement_each_noType_metadata() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
var forStatement =
|
||||
parseStatement('for (@A var element in list) {}') as ForEachStatement;
|
||||
assertNoErrors();
|
||||
@@ -14633,6 +14643,8 @@ main() {
|
||||
}
|
||||
|
||||
void test_parseForStatement_each_type() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
var forStatement =
|
||||
parseStatement('for (A element in list) {}') as ForEachStatement;
|
||||
assertNoErrors();
|
||||
@@ -14648,6 +14660,8 @@ main() {
|
||||
}
|
||||
|
||||
void test_parseForStatement_each_var() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
var forStatement =
|
||||
parseStatement('for (var element in list) {}') as ForEachStatement;
|
||||
assertNoErrors();
|
||||
@@ -14663,6 +14677,8 @@ main() {
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_c() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
var forStatement = parseStatement('for (; i < count;) {}') as ForStatement;
|
||||
assertNoErrors();
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
@@ -14678,6 +14694,8 @@ main() {
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_cu() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
var forStatement =
|
||||
parseStatement('for (; i < count; i++) {}') as ForStatement;
|
||||
assertNoErrors();
|
||||
@@ -14694,6 +14712,8 @@ main() {
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_ecu() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
var forStatement =
|
||||
parseStatement('for (i--; i < count; i++) {}') as ForStatement;
|
||||
assertNoErrors();
|
||||
@@ -14710,6 +14730,8 @@ main() {
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_i() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
var forStatement = parseStatement('for (var i = 0;;) {}') as ForStatement;
|
||||
assertNoErrors();
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
@@ -14728,6 +14750,8 @@ main() {
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_i_withMetadata() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
var forStatement =
|
||||
parseStatement('for (@A var i = 0;;) {}') as ForStatement;
|
||||
assertNoErrors();
|
||||
@@ -14747,6 +14771,8 @@ main() {
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_ic() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
var forStatement =
|
||||
parseStatement('for (var i = 0; i < count;) {}') as ForStatement;
|
||||
assertNoErrors();
|
||||
@@ -14765,6 +14791,8 @@ main() {
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_icu() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
var forStatement =
|
||||
parseStatement('for (var i = 0; i < count; i++) {}') as ForStatement;
|
||||
assertNoErrors();
|
||||
@@ -14783,6 +14811,8 @@ main() {
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_iicuu() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
var forStatement =
|
||||
parseStatement('for (int i = 0, j = count; i < j; i++, j--) {}')
|
||||
as ForStatement;
|
||||
@@ -14802,6 +14832,8 @@ main() {
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_iu() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
var forStatement =
|
||||
parseStatement('for (var i = 0;; i++) {}') as ForStatement;
|
||||
assertNoErrors();
|
||||
@@ -14820,6 +14852,8 @@ main() {
|
||||
}
|
||||
|
||||
void test_parseForStatement_loop_u() {
|
||||
// TODO(danrubel): remove this once control flow and spread collection
|
||||
// entry parsing is enabled by default
|
||||
var forStatement = parseStatement('for (;; i++) {}') as ForStatement;
|
||||
assertNoErrors();
|
||||
expect(forStatement.forKeyword, isNotNull);
|
||||
|
||||
@@ -2250,7 +2250,7 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
|
||||
}
|
||||
|
||||
@override
|
||||
void endForControlFlow(Token rightParenthesis) {
|
||||
void endForControlFlow(Token token) {
|
||||
debugEvent("endForControlFlow");
|
||||
// TODO(danrubel) implement control flow support
|
||||
var entry = pop();
|
||||
@@ -3874,7 +3874,7 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
|
||||
}
|
||||
|
||||
@override
|
||||
void endForInControlFlow(Token rightParenthesis) {
|
||||
void endForInControlFlow(Token token) {
|
||||
debugEvent("endForInControlFlow");
|
||||
// TODO(danrubel) implement control flow support
|
||||
var entry = pop();
|
||||
|
||||
@@ -569,13 +569,13 @@ class ForwardingListener implements Listener {
|
||||
}
|
||||
|
||||
@override
|
||||
void endForControlFlow(Token rightParenthesis) {
|
||||
listener?.endForControlFlow(rightParenthesis);
|
||||
void endForControlFlow(Token token) {
|
||||
listener?.endForControlFlow(token);
|
||||
}
|
||||
|
||||
@override
|
||||
void endForInControlFlow(Token rightParenthesis) {
|
||||
listener?.endForInControlFlow(rightParenthesis);
|
||||
void endForInControlFlow(Token token) {
|
||||
listener?.endForInControlFlow(token);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1088,12 +1088,12 @@ class Listener implements UnescapeErrorListener {
|
||||
void beginForControlFlow(Token awaitToken, Token forToken) {}
|
||||
|
||||
/// Called after parsing a "for" control flow list, set, or map entry.
|
||||
void endForControlFlow(Token rightParenthesis) {
|
||||
void endForControlFlow(Token token) {
|
||||
logEvent('endForControlFlow');
|
||||
}
|
||||
|
||||
/// Called after parsing a "for-in" control flow list, set, or map entry.
|
||||
void endForInControlFlow(Token rightParenthesis) {
|
||||
void endForInControlFlow(Token token) {
|
||||
logEvent('endForInControlFlow');
|
||||
}
|
||||
|
||||
|
||||
@@ -377,13 +377,13 @@ class TypePromotionLookAheadListener extends Listener {
|
||||
}
|
||||
|
||||
@override
|
||||
void endForControlFlow(Token rightParenthesis) {
|
||||
void endForControlFlow(Token token) {
|
||||
// TODO(danrubel) add support for for control flow collection entries
|
||||
// but for now this is ignored and an error reported in the body builder.
|
||||
}
|
||||
|
||||
@override
|
||||
void endForInControlFlow(Token rightParenthesis) {
|
||||
void endForInControlFlow(Token token) {
|
||||
// TODO(danrubel) add support for for control flow collection entries
|
||||
// but for now this is ignored and an error reported in the body builder.
|
||||
}
|
||||
|
||||
@@ -660,13 +660,13 @@ class TestInfoListener implements Listener {
|
||||
}
|
||||
|
||||
@override
|
||||
void endForControlFlow(Token rightParenthesis) {
|
||||
calls.add('endForControlFlow $rightParenthesis');
|
||||
void endForControlFlow(Token token) {
|
||||
calls.add('endForControlFlow $token');
|
||||
}
|
||||
|
||||
@override
|
||||
void endForInControlFlow(Token rightParenthesis) {
|
||||
calls.add('endForInControlFlow $rightParenthesis');
|
||||
void endForInControlFlow(Token token) {
|
||||
calls.add('endForInControlFlow $token');
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
Reference in New Issue
Block a user