// 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)()();') as ExpressionStatement; var funct1 = statement.expression as FunctionExpressionInvocation; List 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> bar() {}', errors: [ expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 4), expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 4, 6), expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 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; }', errors: [ expectedError(ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT, 11, 4), ], ); } void test_invalid_typeParamAnnotation2() { parseCompilationUnit( 'main() { C<@Foo.bar(1) T> v; }', errors: [ expectedError(ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT, 11, 11), ], ); } void test_invalid_typeParamAnnotation3() { parseCompilationUnit( ''' main() { C<@Foo.bar(const [], const [1], const{"":r""}, 0xFF + 2, .3, 4.5) T, F Function(int, String, {Bar b}), void Function(int i, [String j, K]), A>, W>> > v; }''', errors: [ expectedError(ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT, 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; } ', errors: [ expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1), expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 4), expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 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) 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) 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 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 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( errors: [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 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.c();') as ExpressionStatement; assertNoErrors(); expect(statement.expression, isNotNull); } void test_parseNonLabeledStatement_const_object_named_typeParameters_34403() { var statement = parseStatement('const A.c();') as ExpressionStatement; assertErrorsWithCodes([ParserErrorCode.CONSTRUCTOR_WITH_TYPE_ARGUMENTS]); 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 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 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(int x) v;', ) as VariableDeclarationStatement; assertNoErrors(); VariableDeclarationList variableList = statement.variables; List 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 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 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 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() v;') as VariableDeclarationStatement; assertNoErrors(); VariableDeclarationList variableList = statement.variables; List 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 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 v;') as VariableDeclarationStatement; assertNoErrors(); VariableDeclarationList variableList = statement.variables; List 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 v;') as VariableDeclarationStatement; assertNoErrors(); VariableDeclarationList variableList = statement.variables; List 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 v;') as VariableDeclarationStatement; assertNoErrors(); VariableDeclarationList variableList = statement.variables; List 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.EXPECTED_TYPE_NAME]); 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(core.List 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(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(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