Files
sdk/pkg/analyzer/test/generated/statement_parser_test.dart
T
FMorschel 240eda5647 [analyzer] Migrates to contexMessages from analyzer_testing package
This also includes some small refactorings for parameter names to start using the diagnostic wording instead of error. As well as a small change to `contextMessage` and related to use a list of `Pattern`s instead of a single `String` for better matching.

In future CLs, the TODOs added in this one will be addressed so we can fully migrate this. Added them because of the size of the CL.

Bug: https://github.com/dart-lang/sdk/issues/61557
Change-Id: I5557668a1baed98faff977255c9f22e0d9d96008
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/452180
Commit-Queue: Paul Berry <paulberry@google.com>
Auto-Submit: Felipe Morschel <git@fmorschel.dev>
Reviewed-by: Paul Berry <paulberry@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
2025-10-20 13:37:00 -07:00

1789 lines
70 KiB
Dart

// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart' as analyzer;
import 'package:analyzer/dart/ast/token.dart' show TokenType;
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../util/ast_type_matchers.dart';
import 'parser_test_base.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(StatementParserTest);
});
}
/// Tests of the fasta parser based on [FastaParserTestCase].
@reflectiveTest
class StatementParserTest extends FastaParserTestCase {
void test_35177() {
var statement = parseStatement('(f)()<int>();') as ExpressionStatement;
var funct1 = statement.expression as FunctionExpressionInvocation;
List<TypeAnnotation> typeArgs = funct1.typeArguments!.arguments;
expect(typeArgs, hasLength(1));
var typeName = typeArgs[0] as NamedType;
expect(typeName.name.lexeme, 'int');
expect(funct1.argumentList.arguments, hasLength(0));
var funct2 = funct1.function as FunctionExpressionInvocation;
expect(funct2.typeArguments, isNull);
expect(funct2.argumentList.arguments, hasLength(0));
var expression = funct2.function as ParenthesizedExpression;
var identifier = expression.expression as SimpleIdentifier;
expect(identifier.name, 'f');
}
void test_invalid_typeArg_34850() {
var unit = parseCompilationUnit(
'foo Future<List<int>> bar() {}',
diagnostics: [
expectedError(ParserErrorCode.expectedToken, 11, 4),
expectedError(ParserErrorCode.missingFunctionParameters, 4, 6),
expectedError(ParserErrorCode.missingFunctionBody, 22, 3),
],
);
// Validate that recovery has properly updated the token stream.
analyzer.Token token = unit.beginToken;
while (!token.isEof) {
expect(token.type, isNot(TokenType.GT_GT));
analyzer.Token next = token.next!;
expect(next.previous, token);
token = next;
}
}
void test_invalid_typeParamAnnotation() {
parseCompilationUnit(
'main() { C<@Foo T> v; }',
diagnostics: [
expectedError(ParserErrorCode.annotationOnTypeArgument, 11, 4),
],
);
}
void test_invalid_typeParamAnnotation2() {
parseCompilationUnit(
'main() { C<@Foo.bar(1) T> v; }',
diagnostics: [
expectedError(ParserErrorCode.annotationOnTypeArgument, 11, 11),
],
);
}
void test_invalid_typeParamAnnotation3() {
parseCompilationUnit(
'''
main() {
C<@Foo.bar(const [], const [1], const{"":r""}, 0xFF + 2, .3, 4.5) T,
F Function<G>(int, String, {Bar b}),
void Function<H>(int i, [String j, K]),
A<B<C>>,
W<X<Y<Z>>>
> v;
}''',
diagnostics: [
expectedError(ParserErrorCode.annotationOnTypeArgument, 13, 63),
],
);
}
void test_parseAssertStatement() {
var statement = parseStatement('assert (x);') as AssertStatement;
assertNoErrors();
expect(statement.assertKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.condition, isNotNull);
expect(statement.comma, isNull);
expect(statement.message, isNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.semicolon, isNotNull);
}
void test_parseAssertStatement_messageLowPrecedence() {
// Using a throw expression as an assert message would be silly in
// practice, but it's the lowest precedence expression type, so verifying
// that it works should give us high confidence that other expression types
// will work as well.
var statement =
parseStatement('assert (x, throw "foo");') as AssertStatement;
assertNoErrors();
expect(statement.assertKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.condition, isNotNull);
expect(statement.comma, isNotNull);
expect(statement.message, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.semicolon, isNotNull);
}
void test_parseAssertStatement_messageString() {
var statement = parseStatement('assert (x, "foo");') as AssertStatement;
assertNoErrors();
expect(statement.assertKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.condition, isNotNull);
expect(statement.comma, isNotNull);
expect(statement.message, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.semicolon, isNotNull);
}
void test_parseAssertStatement_trailingComma_message() {
var statement = parseStatement('assert (x, "m",);') as AssertStatement;
assertNoErrors();
expect(statement.assertKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.condition, isNotNull);
expect(statement.comma, isNotNull);
expect(statement.message, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.semicolon, isNotNull);
}
void test_parseAssertStatement_trailingComma_noMessage() {
var statement = parseStatement('assert (x,);') as AssertStatement;
assertNoErrors();
expect(statement.assertKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.condition, isNotNull);
expect(statement.comma, isNull);
expect(statement.message, isNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.semicolon, isNotNull);
}
void test_parseBlock_empty() {
var block = parseStatement('{}') as Block;
assertNoErrors();
expect(block.leftBracket, isNotNull);
expect(block.statements, hasLength(0));
expect(block.rightBracket, isNotNull);
}
void test_parseBlock_nonEmpty() {
var block = parseStatement('{;}') as Block;
assertNoErrors();
expect(block.leftBracket, isNotNull);
expect(block.statements, hasLength(1));
expect(block.rightBracket, isNotNull);
}
void test_parseBreakStatement_label() {
var labeledStatement =
parseStatement('foo: while (true) { break foo; }') as LabeledStatement;
var whileStatement = labeledStatement.statement as WhileStatement;
var statement =
(whileStatement.body as Block).statements[0] as BreakStatement;
assertNoErrors();
expect(statement.breakKeyword, isNotNull);
expect(statement.label, isNotNull);
expect(statement.semicolon, isNotNull);
}
void test_parseBreakStatement_noLabel() {
var whileStatement =
parseStatement('while (true) { break; }') as WhileStatement;
var statement =
(whileStatement.body as Block).statements[0] as BreakStatement;
assertNoErrors();
expect(statement.breakKeyword, isNotNull);
expect(statement.label, isNull);
expect(statement.semicolon, isNotNull);
}
void test_parseContinueStatement_label() {
var labeledStatement =
parseStatement('foo: while (true) { continue foo; }')
as LabeledStatement;
var whileStatement = labeledStatement.statement as WhileStatement;
var statement =
(whileStatement.body as Block).statements[0] as ContinueStatement;
assertNoErrors();
expect(statement.continueKeyword, isNotNull);
expect(statement.label, isNotNull);
expect(statement.semicolon, isNotNull);
}
void test_parseContinueStatement_noLabel() {
var whileStatement =
parseStatement('while (true) { continue; }') as WhileStatement;
var statement =
(whileStatement.body as Block).statements[0] as ContinueStatement;
assertNoErrors();
expect(statement.continueKeyword, isNotNull);
expect(statement.label, isNull);
expect(statement.semicolon, isNotNull);
}
void test_parseDoStatement() {
var statement = parseStatement('do {} while (x);') as DoStatement;
assertNoErrors();
expect(statement.doKeyword, isNotNull);
expect(statement.body, isNotNull);
expect(statement.whileKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.condition, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.semicolon, isNotNull);
}
void test_parseElseAlone() {
parseCompilationUnit(
'main() { else return 0; } ',
diagnostics: [
expectedError(ParserErrorCode.expectedToken, 7, 1),
expectedError(ParserErrorCode.missingIdentifier, 9, 4),
expectedError(ParserErrorCode.unexpectedToken, 9, 4),
],
);
}
void test_parseEmptyStatement() {
var statement = parseStatement(';') as EmptyStatement;
assertNoErrors();
expect(statement.semicolon, isNotNull);
}
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 ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNotNull);
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forEachParts = forStatement.forLoopParts as ForEachPartsWithIdentifier;
expect(forEachParts.identifier, isNotNull);
expect(forEachParts.inKeyword, isNotNull);
expect(forEachParts.iterable, isNotNull);
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_each_await2() {
var forStatement =
parseStatement('await for (element in list) {}', inAsync: true)
as ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNotNull);
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForEachPartsWithIdentifier;
expect(forLoopParts.identifier, isNotNull);
expect(forLoopParts.inKeyword, isNotNull);
expect(forLoopParts.iterable, isNotNull);
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_each_finalExternal() {
var forStatement =
parseStatement('for (final external in list) {}') as ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
expect(forLoopParts.loopVariable.name.lexeme, 'external');
expect(forLoopParts.inKeyword, isNotNull);
expect(forLoopParts.iterable, isNotNull);
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_each_finalRequired() {
var forStatement =
parseStatement('for (final required in list) {}') as ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
expect(forLoopParts.loopVariable.name.lexeme, 'required');
expect(forLoopParts.inKeyword, isNotNull);
expect(forLoopParts.iterable, isNotNull);
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
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 ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forEachParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
expect(forEachParts.loopVariable, isNotNull);
expect(forEachParts.inKeyword, isNotNull);
expect(forEachParts.iterable, isNotNull);
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_each_genericFunctionType2() {
var forStatement =
parseStatement('for (void Function<T>(T) element in list) {}')
as ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
expect(forLoopParts.loopVariable, isNotNull);
expect(forLoopParts.inKeyword, isNotNull);
expect(forLoopParts.iterable, isNotNull);
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
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 ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forEachParts = forStatement.forLoopParts as ForEachPartsWithIdentifier;
expect(forEachParts.identifier, isNotNull);
expect(forEachParts.inKeyword, isNotNull);
expect(forEachParts.iterable, isNotNull);
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_each_identifier2() {
var forStatement =
parseStatement('for (element in list) {}') as ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForEachPartsWithIdentifier;
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_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 ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forEachParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
expect(forEachParts.loopVariable, isNotNull);
expect(forEachParts.loopVariable.metadata, hasLength(1));
expect(forEachParts.inKeyword, isNotNull);
expect(forEachParts.iterable, isNotNull);
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_each_noType_metadata2() {
var forStatement =
parseStatement('for (@A var element in list) {}') as ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
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_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 ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forEachParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
expect(forEachParts.loopVariable, isNotNull);
expect(forEachParts.inKeyword, isNotNull);
expect(forEachParts.iterable, isNotNull);
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_each_type2() {
var forStatement =
parseStatement('for (A element in list) {}') as ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
expect(forLoopParts.loopVariable, isNotNull);
expect(forLoopParts.inKeyword, isNotNull);
expect(forLoopParts.iterable, isNotNull);
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
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 ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forEachParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
expect(forEachParts.loopVariable, isNotNull);
expect(forEachParts.inKeyword, isNotNull);
expect(forEachParts.iterable, isNotNull);
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_each_var2() {
var forStatement =
parseStatement('for (var element in list) {}') as ForStatement;
assertNoErrors();
expect(forStatement.awaitKeyword, isNull);
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
expect(forLoopParts.loopVariable, isNotNull);
expect(forLoopParts.inKeyword, isNotNull);
expect(forLoopParts.iterable, isNotNull);
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
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);
expect(forStatement.leftParenthesis, isNotNull);
var forParts = forStatement.forLoopParts as ForPartsWithExpression;
expect(forParts.initialization, isNull);
expect(forParts.leftSeparator, isNotNull);
expect(forParts.condition, isNotNull);
expect(forParts.rightSeparator, isNotNull);
expect(forParts.updaters, hasLength(0));
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_loop_c2() {
var forStatement = parseStatement('for (; i < count;) {}') as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForPartsWithExpression;
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_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();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forParts = forStatement.forLoopParts as ForPartsWithExpression;
expect(forParts.initialization, isNull);
expect(forParts.leftSeparator, isNotNull);
expect(forParts.condition, isNotNull);
expect(forParts.rightSeparator, isNotNull);
expect(forParts.updaters, hasLength(1));
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_loop_cu2() {
var forStatement =
parseStatement('for (; i < count; i++) {}') as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForPartsWithExpression;
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_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();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forParts = forStatement.forLoopParts as ForPartsWithExpression;
expect(forParts.initialization, isNotNull);
expect(forParts.leftSeparator, isNotNull);
expect(forParts.condition, isNotNull);
expect(forParts.rightSeparator, isNotNull);
expect(forParts.updaters, hasLength(1));
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_loop_ecu2() {
var forStatement =
parseStatement('for (i--; i < count; i++) {}') as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForPartsWithExpression;
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_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);
expect(forStatement.leftParenthesis, isNotNull);
var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
VariableDeclarationList variables = forParts.variables;
expect(variables, isNotNull);
expect(variables.metadata, hasLength(0));
expect(variables.variables, hasLength(1));
expect(forParts.leftSeparator, isNotNull);
expect(forParts.condition, isNull);
expect(forParts.rightSeparator, isNotNull);
expect(forParts.updaters, hasLength(0));
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_loop_i2() {
var forStatement = parseStatement('for (var i = 0;;) {}') as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForPartsWithDeclarations;
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_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();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
VariableDeclarationList variables = forParts.variables;
expect(variables, isNotNull);
expect(variables.metadata, hasLength(1));
expect(variables.variables, hasLength(1));
expect(forParts.leftSeparator, isNotNull);
expect(forParts.condition, isNull);
expect(forParts.rightSeparator, isNotNull);
expect(forParts.updaters, hasLength(0));
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_loop_i_withMetadata2() {
var forStatement =
parseStatement('for (@A var i = 0;;) {}') as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForPartsWithDeclarations;
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_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();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
VariableDeclarationList variables = forParts.variables;
expect(variables, isNotNull);
expect(variables.variables, hasLength(1));
expect(forParts.leftSeparator, isNotNull);
expect(forParts.condition, isNotNull);
expect(forParts.rightSeparator, isNotNull);
expect(forParts.updaters, hasLength(0));
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_loop_ic2() {
var forStatement =
parseStatement('for (var i = 0; i < count;) {}') as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForPartsWithDeclarations;
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_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();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
VariableDeclarationList variables = forParts.variables;
expect(variables, isNotNull);
expect(variables.variables, hasLength(1));
expect(forParts.leftSeparator, isNotNull);
expect(forParts.condition, isNotNull);
expect(forParts.rightSeparator, isNotNull);
expect(forParts.updaters, hasLength(1));
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_loop_icu2() {
var forStatement =
parseStatement('for (var i = 0; i < count; i++) {}') as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForPartsWithDeclarations;
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_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;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
VariableDeclarationList variables = forParts.variables;
expect(variables, isNotNull);
expect(variables.variables, hasLength(2));
expect(forParts.leftSeparator, isNotNull);
expect(forParts.condition, isNotNull);
expect(forParts.rightSeparator, isNotNull);
expect(forParts.updaters, hasLength(2));
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_loop_iicuu2() {
var forStatement =
parseStatement('for (int i = 0, j = count; i < j; i++, j--) {}')
as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForPartsWithDeclarations;
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_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();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
VariableDeclarationList variables = forParts.variables;
expect(variables, isNotNull);
expect(variables.variables, hasLength(1));
expect(forParts.leftSeparator, isNotNull);
expect(forParts.condition, isNull);
expect(forParts.rightSeparator, isNotNull);
expect(forParts.updaters, hasLength(1));
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_loop_iu2() {
var forStatement =
parseStatement('for (var i = 0;; i++) {}') as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForPartsWithDeclarations;
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_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);
expect(forStatement.leftParenthesis, isNotNull);
var forParts = forStatement.forLoopParts as ForPartsWithExpression;
expect(forParts.initialization, isNull);
expect(forParts.leftSeparator, isNotNull);
expect(forParts.condition, isNull);
expect(forParts.rightSeparator, isNotNull);
expect(forParts.updaters, hasLength(1));
expect(forStatement.rightParenthesis, isNotNull);
expect(forStatement.body, isNotNull);
}
void test_parseForStatement_loop_u2() {
var forStatement = parseStatement('for (;; i++) {}') as ForStatement;
assertNoErrors();
expect(forStatement.forKeyword, isNotNull);
expect(forStatement.leftParenthesis, isNotNull);
var forLoopParts = forStatement.forLoopParts as ForPartsWithExpression;
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_parseFunctionDeclarationStatement() {
var statement =
parseStatement('void f(int p) => p * 2;')
as FunctionDeclarationStatement;
assertNoErrors();
expect(statement.functionDeclaration, isNotNull);
}
void test_parseFunctionDeclarationStatement_typeParameters() {
var statement =
parseStatement('E f<E>(E p) => p * 2;') as FunctionDeclarationStatement;
assertNoErrors();
expect(statement.functionDeclaration, isNotNull);
expect(
statement.functionDeclaration.functionExpression.typeParameters,
isNotNull,
);
}
void test_parseFunctionDeclarationStatement_typeParameters_noReturnType() {
var statement =
parseStatement('f<E>(E p) => p * 2;') as FunctionDeclarationStatement;
assertNoErrors();
expect(statement.functionDeclaration, isNotNull);
expect(
statement.functionDeclaration.functionExpression.typeParameters,
isNotNull,
);
}
void test_parseIfStatement_else_block() {
var statement = parseStatement('if (x) {} else {}') as IfStatement;
assertNoErrors();
expect(statement.ifKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.expression, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.thenStatement, isNotNull);
expect(statement.elseKeyword, isNotNull);
expect(statement.elseStatement, isNotNull);
}
void test_parseIfStatement_else_emptyStatements() {
var statement = parseStatement('if (true) ; else ;') as IfStatement;
assertNoErrors();
expect(statement.ifKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.expression, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.thenStatement, isNotNull);
expect(statement.elseKeyword, isNotNull);
expect(statement.elseStatement, isNotNull);
}
void test_parseIfStatement_else_statement() {
var statement = parseStatement('if (x) f(x); else f(y);') as IfStatement;
assertNoErrors();
expect(statement.ifKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.expression, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.thenStatement, isNotNull);
expect(statement.elseKeyword, isNotNull);
expect(statement.elseStatement, isNotNull);
}
void test_parseIfStatement_noElse_block() {
var statement = parseStatement('if (x) {}') as IfStatement;
assertNoErrors();
expect(statement.ifKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.expression, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.thenStatement, isNotNull);
expect(statement.elseKeyword, isNull);
expect(statement.elseStatement, isNull);
}
void test_parseIfStatement_noElse_statement() {
var statement = parseStatement('if (x) f(x);') as IfStatement;
assertNoErrors();
expect(statement.ifKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.expression, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.thenStatement, isNotNull);
expect(statement.elseKeyword, isNull);
expect(statement.elseStatement, isNull);
}
void test_parseLocalVariable_external() {
parseStatement('external int i;');
assertErrors(
diagnostics: [expectedError(ParserErrorCode.extraneousModifier, 0, 8)],
);
}
void test_parseNonLabeledStatement_const_list_empty() {
var statement = parseStatement('const [];') as ExpressionStatement;
assertNoErrors();
expect(statement.expression, isNotNull);
}
void test_parseNonLabeledStatement_const_list_nonEmpty() {
var statement = parseStatement('const [1, 2];') as ExpressionStatement;
assertNoErrors();
expect(statement.expression, isNotNull);
}
void test_parseNonLabeledStatement_const_map_empty() {
var statement = parseStatement('const {};') as ExpressionStatement;
assertNoErrors();
expect(statement.expression, isNotNull);
}
void test_parseNonLabeledStatement_const_map_nonEmpty() {
// TODO(brianwilkerson): Implement more tests for this method.
var statement = parseStatement("const {'a' : 1};") as ExpressionStatement;
assertNoErrors();
expect(statement.expression, isNotNull);
}
void test_parseNonLabeledStatement_const_object() {
var statement = parseStatement('const A();') as ExpressionStatement;
assertNoErrors();
expect(statement.expression, isNotNull);
}
void test_parseNonLabeledStatement_const_object_named_typeParameters() {
var statement = parseStatement('const A<B>.c();') as ExpressionStatement;
assertNoErrors();
expect(statement.expression, isNotNull);
}
void test_parseNonLabeledStatement_const_object_named_typeParameters_34403() {
var statement = parseStatement('const A<B>.c<C>();') as ExpressionStatement;
assertErrorsWithCodes([ParserErrorCode.constructorWithTypeArguments]);
expect(statement.expression, isNotNull);
}
void test_parseNonLabeledStatement_constructorInvocation() {
var statement = parseStatement('new C().m();') as ExpressionStatement;
assertNoErrors();
expect(statement.expression, isNotNull);
}
void test_parseNonLabeledStatement_false() {
var statement = parseStatement('false;') as ExpressionStatement;
assertNoErrors();
expect(statement.expression, isNotNull);
}
void test_parseNonLabeledStatement_functionDeclaration() {
var statement = parseStatement('f() {}') as FunctionDeclarationStatement;
assertNoErrors();
var function = statement.functionDeclaration.functionExpression;
expect(function.parameters!.parameters, isEmpty);
expect(function.body, isNotNull);
}
void test_parseNonLabeledStatement_functionDeclaration_arguments() {
var statement =
parseStatement('f(void g()) {}') as FunctionDeclarationStatement;
assertNoErrors();
var function = statement.functionDeclaration.functionExpression;
expect(function.parameters!.parameters, hasLength(1));
expect(function.body, isNotNull);
}
void test_parseNonLabeledStatement_functionExpressionIndex() {
var statement = parseStatement('() {}[0] = null;') as ExpressionStatement;
assertNoErrors();
expect(statement, isNotNull);
}
void test_parseNonLabeledStatement_functionInvocation() {
var statement = parseStatement('f();') as ExpressionStatement;
assertNoErrors();
expect(statement.expression, isNotNull);
}
void test_parseNonLabeledStatement_invokeFunctionExpression() {
var statement =
parseStatement('(a) {return a + a;} (3);') as ExpressionStatement;
assertNoErrors();
var invocation = statement.expression as FunctionExpressionInvocation;
FunctionExpression expression = invocation.function as FunctionExpression;
expect(expression.parameters, isNotNull);
expect(expression.body, isNotNull);
expect(invocation.typeArguments, isNull);
expect(invocation.argumentList.arguments, hasLength(1));
}
void test_parseNonLabeledStatement_localFunction_gftReturnType() {
var statement =
parseStatement('int Function(int) f(String s) => null;')
as FunctionDeclarationStatement;
assertNoErrors();
FunctionDeclaration function = statement.functionDeclaration;
expect(function.returnType, isGenericFunctionType);
}
void test_parseNonLabeledStatement_null() {
var statement = parseStatement('null;') as ExpressionStatement;
assertNoErrors();
expect(statement.expression, isNotNull);
}
void test_parseNonLabeledStatement_startingWithBuiltInIdentifier() {
var statement = parseStatement('library.getName();') as ExpressionStatement;
assertNoErrors();
expect(statement.expression, isNotNull);
}
void test_parseNonLabeledStatement_true() {
var statement = parseStatement('true;') as ExpressionStatement;
assertNoErrors();
expect(statement.expression, isNotNull);
}
void test_parseNonLabeledStatement_typeCast() {
var statement = parseStatement('double.nan as num;') as ExpressionStatement;
assertNoErrors();
expect(statement.expression, isNotNull);
}
void test_parseNonLabeledStatement_variableDeclaration_final_namedFunction() {
var statement =
parseStatement('final int Function = 0;')
as VariableDeclarationStatement;
assertNoErrors();
List<VariableDeclaration> variables = statement.variables.variables;
expect(variables, hasLength(1));
expect(variables[0].name.lexeme, 'Function');
}
void test_parseNonLabeledStatement_variableDeclaration_gftType() {
var statement =
parseStatement('int Function(int) v;') as VariableDeclarationStatement;
assertNoErrors();
VariableDeclarationList variableList = statement.variables;
List<VariableDeclaration> variables = variableList.variables;
expect(variables, hasLength(1));
expect(variables[0].name.lexeme, 'v');
expect(variableList.type, isGenericFunctionType);
}
void
test_parseNonLabeledStatement_variableDeclaration_gftType_functionReturnType() {
var statement =
parseStatement(
'Function Function(int x1, {Function x}) Function<B extends core.int>(int x) v;',
)
as VariableDeclarationStatement;
assertNoErrors();
VariableDeclarationList variableList = statement.variables;
List<VariableDeclaration> variables = variableList.variables;
expect(variables, hasLength(1));
expect(variables[0].name.lexeme, 'v');
expect(variableList.type, isGenericFunctionType);
}
void
test_parseNonLabeledStatement_variableDeclaration_gftType_gftReturnType() {
var statement =
parseStatement('Function(int) Function(int) v;')
as VariableDeclarationStatement;
assertNoErrors();
VariableDeclarationList variableList = statement.variables;
List<VariableDeclaration> variables = variableList.variables;
expect(variables, hasLength(1));
expect(variables[0].name.lexeme, 'v');
expect(variableList.type, isGenericFunctionType);
}
void
test_parseNonLabeledStatement_variableDeclaration_gftType_gftReturnType2() {
var statement =
parseStatement('int Function(int) Function(int) v;')
as VariableDeclarationStatement;
assertNoErrors();
VariableDeclarationList variableList = statement.variables;
List<VariableDeclaration> variables = variableList.variables;
expect(variables, hasLength(1));
expect(variables[0].name.lexeme, 'v');
expect(variableList.type, isGenericFunctionType);
}
void
test_parseNonLabeledStatement_variableDeclaration_gftType_noReturnType() {
var statement =
parseStatement('Function(int) v;') as VariableDeclarationStatement;
assertNoErrors();
VariableDeclarationList variableList = statement.variables;
List<VariableDeclaration> variables = variableList.variables;
expect(variables, hasLength(1));
expect(variables[0].name.lexeme, 'v');
expect(variableList.type, isGenericFunctionType);
}
void test_parseNonLabeledStatement_variableDeclaration_gftType_returnType() {
var statement =
parseStatement('int Function<T>() v;') as VariableDeclarationStatement;
assertNoErrors();
VariableDeclarationList variableList = statement.variables;
List<VariableDeclaration> variables = variableList.variables;
expect(variables, hasLength(1));
expect(variables[0].name.lexeme, 'v');
expect(variableList.type, isGenericFunctionType);
}
void
test_parseNonLabeledStatement_variableDeclaration_gftType_voidReturnType() {
var statement =
parseStatement('void Function() v;') as VariableDeclarationStatement;
assertNoErrors();
VariableDeclarationList variableList = statement.variables;
List<VariableDeclaration> variables = variableList.variables;
expect(variables, hasLength(1));
expect(variables[0].name.lexeme, 'v');
expect(variableList.type, isGenericFunctionType);
}
void test_parseNonLabeledStatement_variableDeclaration_typeParam() {
var statement = parseStatement('C<T> v;') as VariableDeclarationStatement;
assertNoErrors();
VariableDeclarationList variableList = statement.variables;
List<VariableDeclaration> variables = variableList.variables;
expect(variables, hasLength(1));
expect(variables[0].name.lexeme, 'v');
var typeName = variableList.type as NamedType;
expect(typeName.name.lexeme, 'C');
expect(typeName.typeArguments!.arguments, hasLength(1));
var typeArgument = typeName.typeArguments!.arguments[0] as NamedType;
expect(typeArgument.name.lexeme, 'T');
}
void test_parseNonLabeledStatement_variableDeclaration_typeParam2() {
var statement =
parseStatement('C<T /* ignored comment */ > v;')
as VariableDeclarationStatement;
assertNoErrors();
VariableDeclarationList variableList = statement.variables;
List<VariableDeclaration> variables = variableList.variables;
expect(variables, hasLength(1));
expect(variables[0].name.lexeme, 'v');
var typeName = variableList.type as NamedType;
expect(typeName.name.lexeme, 'C');
expect(typeName.typeArguments!.arguments, hasLength(1));
var typeArgument = typeName.typeArguments!.arguments[0] as NamedType;
expect(typeArgument.name.lexeme, 'T');
}
void test_parseNonLabeledStatement_variableDeclaration_typeParam3() {
var statement =
parseStatement('C<T Function(String s)> v;')
as VariableDeclarationStatement;
assertNoErrors();
VariableDeclarationList variableList = statement.variables;
List<VariableDeclaration> variables = variableList.variables;
expect(variables, hasLength(1));
expect(variables[0].name.lexeme, 'v');
var typeName = variableList.type as NamedType;
expect(typeName.name.lexeme, 'C');
expect(typeName.typeArguments!.arguments, hasLength(1));
expect(typeName.typeArguments!.arguments[0], isGenericFunctionType);
}
void test_parseStatement_emptyTypeArgumentList() {
var declaration = parseStatement('C<> c;') as VariableDeclarationStatement;
assertErrorsWithCodes([ParserErrorCode.expectedTypeName]);
VariableDeclarationList variables = declaration.variables;
var type = variables.type as NamedType;
var argumentList = type.typeArguments!;
expect(argumentList.leftBracket, isNotNull);
expect(argumentList.arguments, hasLength(1));
expect(argumentList.arguments[0].isSynthetic, isTrue);
expect(argumentList.rightBracket, isNotNull);
}
void test_parseStatement_function_gftReturnType() {
var statement =
parseStatement('void Function<A>(core.List<core.int> x) m() => null;')
as FunctionDeclarationStatement;
expect(
statement.functionDeclaration.functionExpression.body,
isExpressionFunctionBody,
);
}
void test_parseStatement_functionDeclaration_noReturnType() {
var statement = parseStatement('true;') as ExpressionStatement;
assertNoErrors();
expect(statement.expression, isNotNull);
}
void test_parseStatement_functionDeclaration_noReturnType_typeParameters() {
var statement =
parseStatement('f<E>(a, b) {}') as FunctionDeclarationStatement;
assertNoErrors();
expect(statement.functionDeclaration, isNotNull);
}
void test_parseStatement_functionDeclaration_returnType() {
// TODO(brianwilkerson): Implement more tests for this method.
var statement =
parseStatement('int f(a, b) {}') as FunctionDeclarationStatement;
assertNoErrors();
expect(statement.functionDeclaration, isNotNull);
}
void test_parseStatement_functionDeclaration_returnType_typeParameters() {
var statement =
parseStatement('int f<E>(a, b) {}') as FunctionDeclarationStatement;
assertNoErrors();
expect(statement.functionDeclaration, isNotNull);
}
void test_parseStatement_multipleLabels() {
var statement = parseStatement('l: m: return x;') as LabeledStatement;
expect(statement.labels, hasLength(2));
expect(statement.statement, isNotNull);
}
void test_parseStatement_noLabels() {
var statement = parseStatement('return x;') as ReturnStatement;
assertNoErrors();
expect(statement, isNotNull);
}
void test_parseStatement_singleLabel() {
var statement = parseStatement('l: return x;') as LabeledStatement;
assertNoErrors();
expect(statement.labels, hasLength(1));
expect(statement.labels[0].label.inDeclarationContext(), isTrue);
expect(statement.statement, isNotNull);
}
void test_parseSwitchStatement_case() {
var statement =
parseStatement('switch (a) {case 1: return "I";}') as SwitchStatement;
assertNoErrors();
expect(statement.switchKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.expression, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.leftBracket, isNotNull);
expect(statement.members, hasLength(1));
expect(statement.rightBracket, isNotNull);
}
void test_parseSwitchStatement_empty() {
var statement = parseStatement('switch (a) {}') as SwitchStatement;
assertNoErrors();
expect(statement.switchKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.expression, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.leftBracket, isNotNull);
expect(statement.members, hasLength(0));
expect(statement.rightBracket, isNotNull);
}
void test_parseSwitchStatement_labeledCase() {
var statement =
parseStatement('switch (a) {l1: l2: l3: case(1):}') as SwitchStatement;
assertNoErrors();
expect(statement.switchKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.expression, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.leftBracket, isNotNull);
expect(statement.members, hasLength(1));
{
List<Label> labels = statement.members[0].labels;
expect(labels, hasLength(3));
expect(labels[0].label.inDeclarationContext(), isTrue);
expect(labels[1].label.inDeclarationContext(), isTrue);
expect(labels[2].label.inDeclarationContext(), isTrue);
}
expect(statement.rightBracket, isNotNull);
}
void test_parseSwitchStatement_labeledCase2() {
var statement =
parseStatement('switch (a) {l1: case 0: l2: case 1: return;}')
as SwitchStatement;
assertNoErrors();
expect(statement.switchKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.expression, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.leftBracket, isNotNull);
expect(statement.members, hasLength(2));
{
List<Label> labels = statement.members[0].labels;
expect(labels, hasLength(1));
expect(labels[0].label.inDeclarationContext(), isTrue);
}
{
List<Label> labels = statement.members[1].labels;
expect(labels, hasLength(1));
expect(labels[0].label.inDeclarationContext(), isTrue);
}
expect(statement.rightBracket, isNotNull);
}
void test_parseSwitchStatement_labeledDefault() {
var statement =
parseStatement('switch (a) {l1: l2: l3: default:}') as SwitchStatement;
assertNoErrors();
expect(statement.switchKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.expression, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.leftBracket, isNotNull);
expect(statement.members, hasLength(1));
{
List<Label> labels = statement.members[0].labels;
expect(labels, hasLength(3));
expect(labels[0].label.inDeclarationContext(), isTrue);
expect(labels[1].label.inDeclarationContext(), isTrue);
expect(labels[2].label.inDeclarationContext(), isTrue);
}
expect(statement.rightBracket, isNotNull);
}
void test_parseSwitchStatement_labeledDefault2() {
var statement =
parseStatement('switch (a) {l1: case 0: l2: default: return;}')
as SwitchStatement;
assertNoErrors();
expect(statement.switchKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.expression, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.leftBracket, isNotNull);
expect(statement.members, hasLength(2));
{
List<Label> labels = statement.members[0].labels;
expect(labels, hasLength(1));
expect(labels[0].label.inDeclarationContext(), isTrue);
}
{
List<Label> labels = statement.members[1].labels;
expect(labels, hasLength(1));
expect(labels[0].label.inDeclarationContext(), isTrue);
}
expect(statement.rightBracket, isNotNull);
}
void test_parseSwitchStatement_labeledStatementInCase() {
var statement =
parseStatement('switch (a) {case 0: f(); l1: g(); break;}')
as SwitchStatement;
assertNoErrors();
expect(statement.switchKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.expression, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.leftBracket, isNotNull);
expect(statement.members, hasLength(1));
expect(statement.members[0].statements, hasLength(3));
expect(statement.rightBracket, isNotNull);
}
void test_parseTryStatement_catch() {
var statement = parseStatement('try {} catch (e) {}') as TryStatement;
assertNoErrors();
expect(statement.tryKeyword, isNotNull);
expect(statement.body, isNotNull);
NodeList<CatchClause> catchClauses = statement.catchClauses;
expect(catchClauses, hasLength(1));
CatchClause clause = catchClauses[0];
expect(clause.onKeyword, isNull);
expect(clause.exceptionType, isNull);
expect(clause.catchKeyword, isNotNull);
expect(clause.exceptionParameter, isNotNull);
expect(clause.comma, isNull);
expect(clause.stackTraceParameter, isNull);
expect(clause.body, isNotNull);
expect(statement.finallyKeyword, isNull);
expect(statement.finallyBlock, isNull);
}
void test_parseTryStatement_catch_error_invalidCatchParam() {
CompilationUnit unit = parseCompilationUnit(
'main() { try {} catch (int e) { } }',
diagnostics: [expectedError(ParserErrorCode.catchSyntax, 27, 1)],
);
var method = unit.declarations[0] as FunctionDeclaration;
var body = method.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as TryStatement;
expect(statement.tryKeyword, isNotNull);
expect(statement.body, isNotNull);
NodeList<CatchClause> catchClauses = statement.catchClauses;
expect(catchClauses, hasLength(1));
CatchClause clause = catchClauses[0];
expect(clause.onKeyword, isNull);
expect(clause.exceptionType, isNull);
expect(clause.catchKeyword, isNotNull);
expect(clause.exceptionParameter!.name.lexeme, 'int');
expect(clause.comma, isNotNull);
expect(clause.stackTraceParameter!.name.lexeme, 'e');
expect(clause.body, isNotNull);
expect(statement.finallyKeyword, isNull);
expect(statement.finallyBlock, isNull);
}
void test_parseTryStatement_catch_error_missingCatchParam() {
var statement = parseStatement('try {} catch () {}') as TryStatement;
listener.assertErrors([expectedError(ParserErrorCode.catchSyntax, 14, 1)]);
expect(statement.tryKeyword, isNotNull);
expect(statement.body, isNotNull);
NodeList<CatchClause> catchClauses = statement.catchClauses;
expect(catchClauses, hasLength(1));
CatchClause clause = catchClauses[0];
expect(clause.onKeyword, isNull);
expect(clause.exceptionType, isNull);
expect(clause.catchKeyword, isNotNull);
expect(clause.exceptionParameter, isNotNull);
expect(clause.comma, isNull);
expect(clause.stackTraceParameter, isNull);
expect(clause.body, isNotNull);
expect(statement.finallyKeyword, isNull);
expect(statement.finallyBlock, isNull);
}
void test_parseTryStatement_catch_error_missingCatchParen() {
var statement = parseStatement('try {} catch {}') as TryStatement;
listener.assertErrors([expectedError(ParserErrorCode.catchSyntax, 13, 1)]);
expect(statement.tryKeyword, isNotNull);
expect(statement.body, isNotNull);
NodeList<CatchClause> catchClauses = statement.catchClauses;
expect(catchClauses, hasLength(1));
CatchClause clause = catchClauses[0];
expect(clause.onKeyword, isNull);
expect(clause.exceptionType, isNull);
expect(clause.catchKeyword, isNotNull);
expect(clause.exceptionParameter, isNotNull);
expect(clause.comma, isNull);
expect(clause.stackTraceParameter, isNull);
expect(clause.body, isNotNull);
expect(statement.finallyKeyword, isNull);
expect(statement.finallyBlock, isNull);
}
void test_parseTryStatement_catch_error_missingCatchTrace() {
var statement = parseStatement('try {} catch (e,) {}') as TryStatement;
listener.assertErrors([expectedError(ParserErrorCode.catchSyntax, 16, 1)]);
expect(statement.tryKeyword, isNotNull);
expect(statement.body, isNotNull);
NodeList<CatchClause> catchClauses = statement.catchClauses;
expect(catchClauses, hasLength(1));
CatchClause clause = catchClauses[0];
expect(clause.onKeyword, isNull);
expect(clause.exceptionType, isNull);
expect(clause.catchKeyword, isNotNull);
expect(clause.exceptionParameter, isNotNull);
expect(clause.comma, isNotNull);
expect(clause.stackTraceParameter, isNotNull);
expect(clause.body, isNotNull);
expect(statement.finallyKeyword, isNull);
expect(statement.finallyBlock, isNull);
}
void test_parseTryStatement_catch_finally() {
var statement =
parseStatement('try {} catch (e, s) {} finally {}') as TryStatement;
assertNoErrors();
expect(statement.tryKeyword, isNotNull);
expect(statement.body, isNotNull);
NodeList<CatchClause> catchClauses = statement.catchClauses;
expect(catchClauses, hasLength(1));
CatchClause clause = catchClauses[0];
expect(clause.onKeyword, isNull);
expect(clause.exceptionType, isNull);
expect(clause.catchKeyword, isNotNull);
expect(clause.exceptionParameter, isNotNull);
expect(clause.comma, isNotNull);
expect(clause.stackTraceParameter, isNotNull);
expect(clause.body, isNotNull);
expect(statement.finallyKeyword, isNotNull);
expect(statement.finallyBlock, isNotNull);
}
void test_parseTryStatement_finally() {
var statement = parseStatement('try {} finally {}') as TryStatement;
assertNoErrors();
expect(statement.tryKeyword, isNotNull);
expect(statement.body, isNotNull);
expect(statement.catchClauses, hasLength(0));
expect(statement.finallyKeyword, isNotNull);
expect(statement.finallyBlock, isNotNull);
}
void test_parseTryStatement_multiple() {
var statement =
parseStatement('try {} on NPE catch (e) {} on Error {} catch (e) {}')
as TryStatement;
assertNoErrors();
expect(statement.tryKeyword, isNotNull);
expect(statement.body, isNotNull);
expect(statement.catchClauses, hasLength(3));
expect(statement.finallyKeyword, isNull);
expect(statement.finallyBlock, isNull);
}
void test_parseTryStatement_on() {
var statement = parseStatement('try {} on Error {}') as TryStatement;
assertNoErrors();
expect(statement.tryKeyword, isNotNull);
expect(statement.body, isNotNull);
NodeList<CatchClause> catchClauses = statement.catchClauses;
expect(catchClauses, hasLength(1));
CatchClause clause = catchClauses[0];
expect(clause.onKeyword, isNotNull);
expect(clause.exceptionType, isNotNull);
expect(clause.catchKeyword, isNull);
expect(clause.exceptionParameter, isNull);
expect(clause.comma, isNull);
expect(clause.stackTraceParameter, isNull);
expect(clause.body, isNotNull);
expect(statement.finallyKeyword, isNull);
expect(statement.finallyBlock, isNull);
}
void test_parseTryStatement_on_catch() {
var statement =
parseStatement('try {} on Error catch (e, s) {}') as TryStatement;
assertNoErrors();
expect(statement.tryKeyword, isNotNull);
expect(statement.body, isNotNull);
NodeList<CatchClause> catchClauses = statement.catchClauses;
expect(catchClauses, hasLength(1));
CatchClause clause = catchClauses[0];
expect(clause.onKeyword, isNotNull);
expect(clause.exceptionType, isNotNull);
expect(clause.catchKeyword, isNotNull);
expect(clause.exceptionParameter, isNotNull);
expect(clause.comma, isNotNull);
expect(clause.stackTraceParameter, isNotNull);
expect(clause.body, isNotNull);
expect(statement.finallyKeyword, isNull);
expect(statement.finallyBlock, isNull);
}
void test_parseTryStatement_on_catch_finally() {
var statement =
parseStatement('try {} on Error catch (e, s) {} finally {}')
as TryStatement;
assertNoErrors();
expect(statement.tryKeyword, isNotNull);
expect(statement.body, isNotNull);
NodeList<CatchClause> catchClauses = statement.catchClauses;
expect(catchClauses, hasLength(1));
CatchClause clause = catchClauses[0];
expect(clause.onKeyword, isNotNull);
expect(clause.exceptionType, isNotNull);
expect(clause.catchKeyword, isNotNull);
expect(clause.exceptionParameter, isNotNull);
expect(clause.comma, isNotNull);
expect(clause.stackTraceParameter, isNotNull);
expect(clause.body, isNotNull);
expect(statement.finallyKeyword, isNotNull);
expect(statement.finallyBlock, isNotNull);
}
void test_parseVariableDeclaration_equals_builtIn() {
var statement =
parseStatement('int set = 0;') as VariableDeclarationStatement;
assertNoErrors();
expect(statement.semicolon, isNotNull);
VariableDeclarationList variableList = statement.variables;
expect(variableList, isNotNull);
expect(variableList.variables, hasLength(1));
}
void test_parseVariableDeclarationListAfterMetadata_const_noType() {
var declarationList = parseVariableDeclarationList('const a = 0');
assertNoErrors();
expect(declarationList.keyword!.lexeme, 'const');
expect(declarationList.type, isNull);
expect(declarationList.variables, hasLength(1));
}
void test_parseVariableDeclarationListAfterMetadata_const_type() {
var declarationList = parseVariableDeclarationList('const A a');
assertNoErrors();
expect(declarationList.keyword!.lexeme, 'const');
expect(declarationList.type, isNotNull);
expect(declarationList.variables, hasLength(1));
}
void test_parseVariableDeclarationListAfterMetadata_final_noType() {
var declarationList = parseVariableDeclarationList('final a');
assertNoErrors();
expect(declarationList.keyword, isNotNull);
expect(declarationList.type, isNull);
expect(declarationList.variables, hasLength(1));
}
void test_parseVariableDeclarationListAfterMetadata_final_type() {
var declarationList = parseVariableDeclarationList('final A a');
assertNoErrors();
expect(declarationList.keyword!.lexeme, 'final');
expect(declarationList.type, isNotNull);
expect(declarationList.variables, hasLength(1));
}
void test_parseVariableDeclarationListAfterMetadata_type_multiple() {
var declarationList = parseVariableDeclarationList('A a, b, c');
assertNoErrors();
expect(declarationList.keyword, isNull);
expect(declarationList.type, isNotNull);
expect(declarationList.variables, hasLength(3));
}
void test_parseVariableDeclarationListAfterMetadata_type_single() {
var declarationList = parseVariableDeclarationList('A a');
assertNoErrors();
expect(declarationList.keyword, isNull);
expect(declarationList.type, isNotNull);
expect(declarationList.variables, hasLength(1));
}
void test_parseVariableDeclarationListAfterMetadata_var_multiple() {
var declarationList = parseVariableDeclarationList('var a, b, c');
assertNoErrors();
expect(declarationList.keyword!.lexeme, 'var');
expect(declarationList.type, isNull);
expect(declarationList.variables, hasLength(3));
}
void test_parseVariableDeclarationListAfterMetadata_var_single() {
var declarationList = parseVariableDeclarationList('var a');
assertNoErrors();
expect(declarationList.keyword!.lexeme, 'var');
expect(declarationList.type, isNull);
expect(declarationList.variables, hasLength(1));
}
void test_parseVariableDeclarationStatementAfterMetadata_multiple() {
var statement =
parseStatement('var x, y, z;') as VariableDeclarationStatement;
assertNoErrors();
expect(statement.semicolon, isNotNull);
VariableDeclarationList variableList = statement.variables;
expect(variableList, isNotNull);
expect(variableList.variables, hasLength(3));
}
void test_parseVariableDeclarationStatementAfterMetadata_single() {
var statement = parseStatement('var x;') as VariableDeclarationStatement;
assertNoErrors();
expect(statement.semicolon, isNotNull);
VariableDeclarationList variableList = statement.variables;
expect(variableList, isNotNull);
expect(variableList.variables, hasLength(1));
}
void test_parseWhileStatement() {
var statement = parseStatement('while (x) {}') as WhileStatement;
assertNoErrors();
expect(statement.whileKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.condition, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.body, isNotNull);
}
void test_parseYieldStatement_each() {
var statement =
_parseAsyncStatement('yield* x;', isGenerator: true) as YieldStatement;
assertNoErrors();
expect(statement.yieldKeyword, isNotNull);
expect(statement.star, isNotNull);
expect(statement.expression, isNotNull);
expect(statement.semicolon, isNotNull);
}
void test_parseYieldStatement_normal() {
var statement =
_parseAsyncStatement('yield x;', isGenerator: true) as YieldStatement;
assertNoErrors();
expect(statement.yieldKeyword, isNotNull);
expect(statement.star, isNull);
expect(statement.expression, isNotNull);
expect(statement.semicolon, isNotNull);
}
void test_partial_typeArg1_34850() {
var unit = parseCompilationUnit(
'<bar<',
diagnostics: [
expectedError(ParserErrorCode.expectedExecutable, 0, 1),
expectedError(ParserErrorCode.expectedToken, 4, 1),
expectedError(ParserErrorCode.missingIdentifier, 5, 0),
expectedError(ParserErrorCode.expectedTypeName, 5, 0),
expectedError(ParserErrorCode.missingIdentifier, 5, 0),
],
);
// Validate that recovery has properly updated the token stream.
analyzer.Token token = unit.beginToken;
while (!token.isEof) {
expect(token.type, isNot(TokenType.GT_GT));
analyzer.Token next = token.next!;
expect(next.previous, token);
token = next;
}
}
void test_partial_typeArg2_34850() {
var unit = parseCompilationUnit(
'foo <bar<',
diagnostics: [
expectedError(ParserErrorCode.expectedToken, 8, 1),
expectedError(ParserErrorCode.missingIdentifier, 9, 0),
expectedError(ParserErrorCode.expectedTypeName, 9, 0),
expectedError(ParserErrorCode.missingIdentifier, 9, 0),
],
);
// Validate that recovery has properly updated the token stream.
analyzer.Token token = unit.beginToken;
while (!token.isEof) {
expect(token.type, isNot(TokenType.GT_GT));
analyzer.Token next = token.next!;
expect(next.previous, token);
token = next;
}
}
Statement _parseAsyncStatement(String code, {bool isGenerator = false}) {
var star = isGenerator ? '*' : '';
var localFunction =
parseStatement('wrapper() async$star { $code }')
as FunctionDeclarationStatement;
var localBody =
localFunction.functionDeclaration.functionExpression.body
as BlockFunctionBody;
return localBody.block.statements.single;
}
}