// 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:_fe_analyzer_shared/src/scanner/abstract_scanner.dart' show AbstractScanner; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/src/dart/ast/ast.dart' show InstanceCreationExpressionImpl; import 'package:analyzer/src/dart/scanner/scanner.dart'; import 'package:analyzer/src/generated/testing/token_factory.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(ExpressionParserTest); }); } /// Tests of the parser based on [FastaParserTestCase]. @reflectiveTest class ExpressionParserTest extends FastaParserTestCase { void test_binaryExpression_allOperators() { // https://github.com/dart-lang/sdk/issues/36255 for (TokenType type in TokenType.all) { if (type.precedence > 0) { var source = 'a ${type.lexeme} b'; try { parseExpression(source); } on TestFailure { // Ensure that there are no infinite loops or exceptions thrown // by the parser. Test failures are fine. } } } } void test_invalidExpression_37706() { // https://github.com/dart-lang/sdk/issues/37706 parseExpression( '()', errors: [ expectedError(ParserErrorCode.EXPECTED_TOKEN, 1, 1), expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 0), expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 7, 0), ], ); } void test_listLiteral_invalid_assert() { // https://github.com/dart-lang/sdk/issues/37674 parseExpression( 'n=<.["\$assert', errors: [ expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 3, 1), expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 4, 1), expectedError( ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 7, 6, ), expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 12, 1), expectedError(ScannerErrorCode.EXPECTED_TOKEN, 13, 1), ], ); } void test_listLiteral_invalidElement_37697() { // https://github.com/dart-lang/sdk/issues/37674 parseExpression( '[(){}]', errors: [ expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 4, 1), expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1), ], ); } void test_lt_dot_bracket_quote() { // https://github.com/dart-lang/sdk/issues/37674 var list = parseExpression( '<.["', errors: [ expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 1, 1), expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 2, 1), expectedError( ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 3, 1, ), expectedError(ScannerErrorCode.EXPECTED_TOKEN, 4, 1), ], ) as ListLiteral; expect(list.elements, hasLength(1)); var first = list.elements[0] as StringLiteral; expect(first.length, 1); } void test_lt_dot_listLiteral() { // https://github.com/dart-lang/sdk/issues/37674 var list = parseExpression( '<.[]', errors: [ expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 1, 1), expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 2, 2), ], ) as ListLiteral; expect(list.elements, hasLength(0)); } void test_mapLiteral() { var map = parseExpression('{3: 6}') as SetOrMapLiteral; expect(map.constKeyword, isNull); expect(map.typeArguments, isNull); expect(map.elements, hasLength(1)); var entry = map.elements[0] as MapLiteralEntry; var key = entry.key as IntegerLiteral; expect(key.value, 3); var value = entry.value as IntegerLiteral; expect(value.value, 6); } void test_mapLiteral_const() { var map = parseExpression('const {3: 6}') as SetOrMapLiteral; expect(map.constKeyword, isNotNull); expect(map.typeArguments, isNull); expect(map.elements, hasLength(1)); var entry = map.elements[0] as MapLiteralEntry; var key = entry.key as IntegerLiteral; expect(key.value, 3); var value = entry.value as IntegerLiteral; expect(value.value, 6); } @failingTest void test_mapLiteral_invalid_too_many_type_arguments1() { var map = parseExpression( '{}', errors: [ // TODO(danrubel): Currently the resolver reports invalid number of // type arguments, but the parser could report this. expectedError( /* ParserErrorCode.EXPECTED_ONE_OR_TWO_TYPE_VARIABLES */ ParserErrorCode.EXPECTED_TOKEN, 11, 3, ), ], ) as SetOrMapLiteral; expect(map.constKeyword, isNull); expect(map.elements, hasLength(0)); } @failingTest void test_mapLiteral_invalid_too_many_type_arguments2() { var map = parseExpression( '{1}', errors: [ // TODO(danrubel): Currently the resolver reports invalid number of // type arguments, but the parser could report this. expectedError( /* ParserErrorCode.EXPECTED_ONE_OR_TWO_TYPE_VARIABLES */ ParserErrorCode.EXPECTED_TOKEN, 11, 3, ), ], ) as SetOrMapLiteral; expect(map.constKeyword, isNull); expect(map.elements, hasLength(0)); } void test_namedArgument() { var invocation = parseExpression('m(a: 1, b: 2)') as MethodInvocation; List arguments = invocation.argumentList.arguments; var a = arguments[0] as NamedExpression; expect(a.name.label.name, 'a'); expect(a.expression, isNotNull); var b = arguments[1] as NamedExpression; expect(b.name.label.name, 'b'); expect(b.expression, isNotNull); } void test_nullableTypeInStringInterpolations_as_48999() { // https://github.com/dart-lang/sdk/issues/48999 Expression expression = parseExpression(r'"${i as int?}"'); expect(expression, isNotNull); assertNoErrors(); var interpolation = expression as StringInterpolation; expect(interpolation.elements, hasLength(3)); expect(interpolation.elements[0], isInterpolationString); var element0 = interpolation.elements[0] as InterpolationString; expect(element0.value, ''); expect(interpolation.elements[1], isInterpolationExpression); var element1 = interpolation.elements[1] as InterpolationExpression; expect(element1.expression, isAsExpression); var asExpression = element1.expression as AsExpression; expect(asExpression.expression, isSimpleIdentifier); expect(asExpression.type, isNamedType); var namedType = asExpression.type as NamedType; expect(namedType.name.lexeme, "int"); expect(namedType.question, isNotNull); expect(interpolation.elements[2], isInterpolationString); var element2 = interpolation.elements[2] as InterpolationString; expect(element2.value, ''); } void test_nullableTypeInStringInterpolations_is_48999() { // https://github.com/dart-lang/sdk/issues/48999 Expression expression = parseExpression(r'"${i is int?}"'); expect(expression, isNotNull); assertNoErrors(); var interpolation = expression as StringInterpolation; expect(interpolation.elements, hasLength(3)); expect(interpolation.elements[0], isInterpolationString); var element0 = interpolation.elements[0] as InterpolationString; expect(element0.value, ''); expect(interpolation.elements[1], isInterpolationExpression); var element1 = interpolation.elements[1] as InterpolationExpression; expect(element1.expression, isIsExpression); var isExpression = element1.expression as IsExpression; expect(isExpression.expression, isSimpleIdentifier); expect(isExpression.type, isNamedType); var namedType = isExpression.type as NamedType; expect(namedType.name.lexeme, "int"); expect(namedType.question, isNotNull); expect(interpolation.elements[2], isInterpolationString); var element2 = interpolation.elements[2] as InterpolationString; expect(element2.value, ''); } void test_parseAdditiveExpression_normal() { Expression expression = parseAdditiveExpression('x + y'); expect(expression, isNotNull); assertNoErrors(); var binaryExpression = expression as BinaryExpression; expect(binaryExpression.leftOperand, isNotNull); expect(binaryExpression.operator, isNotNull); expect(binaryExpression.operator.type, TokenType.PLUS); expect(binaryExpression.rightOperand, isNotNull); } void test_parseAdditiveExpression_super() { Expression expression = parseAdditiveExpression('super + y'); expect(expression, isNotNull); assertNoErrors(); var binaryExpression = expression as BinaryExpression; expect(binaryExpression.leftOperand, isSuperExpression); expect(binaryExpression.operator, isNotNull); expect(binaryExpression.operator.type, TokenType.PLUS); expect(binaryExpression.rightOperand, isNotNull); } void test_parseAssignableExpression_expression_args_dot() { Expression expression = parseAssignableExpression('(x)(y).z', false); expect(expression, isNotNull); assertNoErrors(); var propertyAccess = expression as PropertyAccess; FunctionExpressionInvocation invocation = propertyAccess.target as FunctionExpressionInvocation; expect(invocation.function, isNotNull); expect(invocation.typeArguments, isNull); ArgumentList argumentList = invocation.argumentList; expect(argumentList, isNotNull); expect(argumentList.arguments, hasLength(1)); expect(propertyAccess.operator, isNotNull); expect(propertyAccess.propertyName, isNotNull); } void test_parseAssignableExpression_expression_args_dot_typeArguments() { Expression expression = parseAssignableExpression('(x)(y).z', false); expect(expression, isNotNull); assertNoErrors(); var propertyAccess = expression as PropertyAccess; FunctionExpressionInvocation invocation = propertyAccess.target as FunctionExpressionInvocation; expect(invocation.function, isNotNull); expect(invocation.typeArguments, isNotNull); ArgumentList argumentList = invocation.argumentList; expect(argumentList, isNotNull); expect(argumentList.arguments, hasLength(1)); expect(propertyAccess.operator, isNotNull); expect(propertyAccess.propertyName, isNotNull); } void test_parseAssignableExpression_expression_dot() { Expression expression = parseAssignableExpression('(x).y', false); expect(expression, isNotNull); assertNoErrors(); var propertyAccess = expression as PropertyAccess; expect(propertyAccess.target, isNotNull); expect(propertyAccess.operator.type, TokenType.PERIOD); expect(propertyAccess.propertyName, isNotNull); } void test_parseAssignableExpression_expression_index() { Expression expression = parseAssignableExpression('(x)[y]', false); expect(expression, isNotNull); assertNoErrors(); var indexExpression = expression as IndexExpression; expect(indexExpression.target, isNotNull); expect(indexExpression.leftBracket, isNotNull); expect(indexExpression.index, isNotNull); expect(indexExpression.rightBracket, isNotNull); } void test_parseAssignableExpression_expression_question_dot() { Expression expression = parseAssignableExpression('(x)?.y', false); expect(expression, isNotNull); assertNoErrors(); var propertyAccess = expression as PropertyAccess; expect(propertyAccess.target, isNotNull); expect(propertyAccess.operator.type, TokenType.QUESTION_PERIOD); expect(propertyAccess.propertyName, isNotNull); } void test_parseAssignableExpression_identifier() { Expression expression = parseAssignableExpression('x', false); expect(expression, isNotNull); assertNoErrors(); var identifier = expression as SimpleIdentifier; expect(identifier, isNotNull); } void test_parseAssignableExpression_identifier_args_dot() { Expression expression = parseAssignableExpression('x(y).z', false); expect(expression, isNotNull); assertNoErrors(); var propertyAccess = expression as PropertyAccess; MethodInvocation invocation = propertyAccess.target as MethodInvocation; expect(invocation.methodName.name, "x"); expect(invocation.typeArguments, isNull); ArgumentList argumentList = invocation.argumentList; expect(argumentList, isNotNull); expect(argumentList.arguments, hasLength(1)); expect(propertyAccess.operator, isNotNull); expect(propertyAccess.propertyName, isNotNull); } void test_parseAssignableExpression_identifier_args_dot_typeArguments() { Expression expression = parseAssignableExpression('x(y).z', false); expect(expression, isNotNull); assertNoErrors(); var propertyAccess = expression as PropertyAccess; MethodInvocation invocation = propertyAccess.target as MethodInvocation; expect(invocation.methodName.name, "x"); expect(invocation.typeArguments, isNotNull); ArgumentList argumentList = invocation.argumentList; expect(argumentList, isNotNull); expect(argumentList.arguments, hasLength(1)); expect(propertyAccess.operator, isNotNull); expect(propertyAccess.propertyName, isNotNull); } void test_parseAssignableExpression_identifier_dot() { Expression expression = parseAssignableExpression('x.y', false); expect(expression, isNotNull); assertNoErrors(); var identifier = expression as PrefixedIdentifier; expect(identifier.prefix.name, 'x'); expect(identifier.period, isNotNull); expect(identifier.period.type, TokenType.PERIOD); expect(identifier.identifier.name, 'y'); } void test_parseAssignableExpression_identifier_index() { Expression expression = parseAssignableExpression('x[y]', false); expect(expression, isNotNull); assertNoErrors(); var indexExpression = expression as IndexExpression; expect(indexExpression.target, isNotNull); expect(indexExpression.leftBracket, isNotNull); expect(indexExpression.index, isNotNull); expect(indexExpression.rightBracket, isNotNull); } void test_parseAssignableExpression_identifier_question_dot() { Expression expression = parseAssignableExpression('x?.y', false); expect(expression, isNotNull); assertNoErrors(); var propertyAccess = expression as PropertyAccess; expect(propertyAccess.target, isNotNull); expect(propertyAccess.operator.type, TokenType.QUESTION_PERIOD); expect(propertyAccess.propertyName, isNotNull); } void test_parseAssignableExpression_super_dot() { Expression expression = parseAssignableExpression('super.y', false); expect(expression, isNotNull); assertNoErrors(); var propertyAccess = expression as PropertyAccess; expect(propertyAccess.target, isSuperExpression); expect(propertyAccess.operator, isNotNull); expect(propertyAccess.propertyName, isNotNull); } void test_parseAssignableExpression_super_index() { Expression expression = parseAssignableExpression('super[y]', false); expect(expression, isNotNull); assertNoErrors(); var indexExpression = expression as IndexExpression; expect(indexExpression.target, isSuperExpression); expect(indexExpression.leftBracket, isNotNull); expect(indexExpression.index, isNotNull); expect(indexExpression.rightBracket, isNotNull); } void test_parseAssignableSelector_dot() { Expression expression = parseAssignableSelector('.x', true); expect(expression, isNotNull); assertNoErrors(); var propertyAccess = expression as PropertyAccess; expect(propertyAccess.operator.type, TokenType.PERIOD); expect(propertyAccess.propertyName, isNotNull); } void test_parseAssignableSelector_index() { Expression expression = parseAssignableSelector('[x]', true); expect(expression, isNotNull); assertNoErrors(); var indexExpression = expression as IndexExpression; expect(indexExpression.leftBracket, isNotNull); expect(indexExpression.index, isNotNull); expect(indexExpression.rightBracket, isNotNull); } void test_parseAssignableSelector_none() { Expression expression = parseAssignableSelector('', true); expect(expression, isNotNull); assertNoErrors(); var identifier = expression as SimpleIdentifier; expect(identifier, isNotNull); } void test_parseAssignableSelector_question_dot() { Expression expression = parseAssignableSelector('?.x', true); expect(expression, isNotNull); assertNoErrors(); var propertyAccess = expression as PropertyAccess; expect(propertyAccess.operator.type, TokenType.QUESTION_PERIOD); expect(propertyAccess.propertyName, isNotNull); } void test_parseAwaitExpression() { AwaitExpression expression = parseAwaitExpression('await x'); expect(expression, isNotNull); assertNoErrors(); expect(expression.awaitKeyword, isNotNull); expect(expression.expression, isNotNull); } void test_parseBitwiseAndExpression_normal() { Expression expression = parseBitwiseAndExpression('x & y'); expect(expression, isNotNull); assertNoErrors(); var binaryExpression = expression as BinaryExpression; expect(binaryExpression.leftOperand, isNotNull); expect(binaryExpression.operator, isNotNull); expect(binaryExpression.operator.type, TokenType.AMPERSAND); expect(binaryExpression.rightOperand, isNotNull); } void test_parseBitwiseAndExpression_super() { Expression expression = parseBitwiseAndExpression('super & y'); expect(expression, isNotNull); assertNoErrors(); var binaryExpression = expression as BinaryExpression; expect(binaryExpression.leftOperand, isSuperExpression); expect(binaryExpression.operator, isNotNull); expect(binaryExpression.operator.type, TokenType.AMPERSAND); expect(binaryExpression.rightOperand, isNotNull); } void test_parseBitwiseOrExpression_normal() { Expression expression = parseBitwiseOrExpression('x | y'); expect(expression, isNotNull); assertNoErrors(); var binaryExpression = expression as BinaryExpression; expect(binaryExpression.leftOperand, isNotNull); expect(binaryExpression.operator, isNotNull); expect(binaryExpression.operator.type, TokenType.BAR); expect(binaryExpression.rightOperand, isNotNull); } void test_parseBitwiseOrExpression_super() { Expression expression = parseBitwiseOrExpression('super | y'); expect(expression, isNotNull); assertNoErrors(); var binaryExpression = expression as BinaryExpression; expect(binaryExpression.leftOperand, isSuperExpression); expect(binaryExpression.operator, isNotNull); expect(binaryExpression.operator.type, TokenType.BAR); expect(binaryExpression.rightOperand, isNotNull); } void test_parseBitwiseXorExpression_normal() { Expression expression = parseBitwiseXorExpression('x ^ y'); expect(expression, isNotNull); assertNoErrors(); var binaryExpression = expression as BinaryExpression; expect(binaryExpression.leftOperand, isNotNull); expect(binaryExpression.operator, isNotNull); expect(binaryExpression.operator.type, TokenType.CARET); expect(binaryExpression.rightOperand, isNotNull); } void test_parseBitwiseXorExpression_super() { Expression expression = parseBitwiseXorExpression('super ^ y'); expect(expression, isNotNull); assertNoErrors(); var binaryExpression = expression as BinaryExpression; expect(binaryExpression.leftOperand, isSuperExpression); expect(binaryExpression.operator, isNotNull); expect(binaryExpression.operator.type, TokenType.CARET); expect(binaryExpression.rightOperand, isNotNull); } void test_parseCascadeSection_i() { Expression expression = parseCascadeSection('..[i]'); expect(expression, isNotNull); assertNoErrors(); var section = expression as IndexExpression; expect(section.target, isNull); expect(section.leftBracket, isNotNull); expect(section.index, isNotNull); expect(section.rightBracket, isNotNull); } void test_parseCascadeSection_ia() { Expression expression = parseCascadeSection('..[i](b)'); expect(expression, isNotNull); assertNoErrors(); var section = expression as FunctionExpressionInvocation; expect(section.function, isIndexExpression); expect(section.typeArguments, isNull); expect(section.argumentList, isNotNull); } void test_parseCascadeSection_ia_typeArguments() { Expression expression = parseCascadeSection('..[i](b)'); expect(expression, isNotNull); assertNoErrors(); var section = expression as FunctionExpressionInvocation; expect(section.function, isIndexExpression); expect(section.typeArguments, isNotNull); expect(section.argumentList, isNotNull); } void test_parseCascadeSection_ii() { Expression expression = parseCascadeSection('..a(b).c(d)'); expect(expression, isNotNull); assertNoErrors(); var section = expression as MethodInvocation; expect(section.target, isMethodInvocation); expect(section.operator, isNotNull); expect(section.methodName, isNotNull); expect(section.typeArguments, isNull); expect(section.argumentList, isNotNull); expect(section.argumentList.arguments, hasLength(1)); } void test_parseCascadeSection_ii_typeArguments() { Expression expression = parseCascadeSection('..a(b).c(d)'); expect(expression, isNotNull); assertNoErrors(); var section = expression as MethodInvocation; expect(section.target, isMethodInvocation); expect(section.operator, isNotNull); expect(section.methodName, isNotNull); expect(section.typeArguments, isNotNull); expect(section.argumentList, isNotNull); expect(section.argumentList.arguments, hasLength(1)); } void test_parseCascadeSection_p() { Expression expression = parseCascadeSection('..a'); expect(expression, isNotNull); assertNoErrors(); var section = expression as PropertyAccess; expect(section.target, isNull); expect(section.operator, isNotNull); expect(section.propertyName, isNotNull); } void test_parseCascadeSection_p_assign() { Expression expression = parseCascadeSection('..a = 3'); expect(expression, isNotNull); assertNoErrors(); var section = expression as AssignmentExpression; expect(section.leftHandSide, isNotNull); expect(section.operator, isNotNull); Expression rhs = section.rightHandSide; expect(rhs, isNotNull); } void test_parseCascadeSection_p_assign_withCascade() { Expression expression = parseCascadeSection('..a = 3..m()'); expect(expression, isNotNull); assertNoErrors(); var section = expression as AssignmentExpression; expect(section.leftHandSide, isNotNull); expect(section.operator, isNotNull); Expression rhs = section.rightHandSide; expect(rhs, isIntegerLiteral); } void test_parseCascadeSection_p_assign_withCascade_typeArguments() { Expression expression = parseCascadeSection('..a = 3..m()'); expect(expression, isNotNull); assertNoErrors(); var section = expression as AssignmentExpression; expect(section.leftHandSide, isNotNull); expect(section.operator, isNotNull); Expression rhs = section.rightHandSide; expect(rhs, isIntegerLiteral); } void test_parseCascadeSection_p_builtIn() { Expression expression = parseCascadeSection('..as'); expect(expression, isNotNull); assertNoErrors(); var section = expression as PropertyAccess; expect(section.target, isNull); expect(section.operator, isNotNull); expect(section.propertyName, isNotNull); } void test_parseCascadeSection_pa() { Expression expression = parseCascadeSection('..a(b)'); expect(expression, isNotNull); assertNoErrors(); var section = expression as MethodInvocation; expect(section.target, isNull); expect(section.operator, isNotNull); expect(section.methodName, isNotNull); expect(section.typeArguments, isNull); expect(section.argumentList, isNotNull); expect(section.argumentList.arguments, hasLength(1)); } void test_parseCascadeSection_pa_typeArguments() { Expression expression = parseCascadeSection('..a(b)'); expect(expression, isNotNull); assertNoErrors(); var section = expression as MethodInvocation; expect(section.target, isNull); expect(section.operator, isNotNull); expect(section.methodName, isNotNull); expect(section.typeArguments, isNotNull); expect(section.argumentList, isNotNull); expect(section.argumentList.arguments, hasLength(1)); } void test_parseCascadeSection_paa() { Expression expression = parseCascadeSection('..a(b)(c)'); expect(expression, isNotNull); assertNoErrors(); var section = expression as FunctionExpressionInvocation; expect(section.function, isMethodInvocation); expect(section.typeArguments, isNull); expect(section.argumentList, isNotNull); expect(section.argumentList.arguments, hasLength(1)); } void test_parseCascadeSection_paa_typeArguments() { Expression expression = parseCascadeSection('..a(b)(c)'); expect(expression, isNotNull); assertNoErrors(); var section = expression as FunctionExpressionInvocation; expect(section.function, isMethodInvocation); expect(section.typeArguments, isNotNull); expect(section.argumentList, isNotNull); expect(section.argumentList.arguments, hasLength(1)); } void test_parseCascadeSection_paapaa() { Expression expression = parseCascadeSection('..a(b)(c).d(e)(f)'); expect(expression, isNotNull); assertNoErrors(); var section = expression as FunctionExpressionInvocation; expect(section.function, isMethodInvocation); expect(section.typeArguments, isNull); expect(section.argumentList, isNotNull); expect(section.argumentList.arguments, hasLength(1)); } void test_parseCascadeSection_paapaa_typeArguments() { Expression expression = parseCascadeSection( '..a(b)(c).d(e)(f)', ); expect(expression, isNotNull); assertNoErrors(); var section = expression as FunctionExpressionInvocation; expect(section.function, isMethodInvocation); expect(section.typeArguments, isNotNull); expect(section.argumentList, isNotNull); expect(section.argumentList.arguments, hasLength(1)); } void test_parseCascadeSection_pap() { Expression expression = parseCascadeSection('..a(b).c'); expect(expression, isNotNull); assertNoErrors(); var section = expression as PropertyAccess; expect(section.target, isNotNull); expect(section.operator, isNotNull); expect(section.propertyName, isNotNull); } void test_parseCascadeSection_pap_typeArguments() { Expression expression = parseCascadeSection('..a(b).c'); expect(expression, isNotNull); assertNoErrors(); var section = expression as PropertyAccess; expect(section.target, isNotNull); expect(section.operator, isNotNull); expect(section.propertyName, isNotNull); } void test_parseConditionalExpression() { ConditionalExpression expression = parseConditionalExpression('x ? y : z'); expect(expression, isNotNull); assertNoErrors(); expect(expression.condition, isNotNull); expect(expression.question, isNotNull); expect(expression.thenExpression, isNotNull); expect(expression.colon, isNotNull); expect(expression.elseExpression, isNotNull); } void test_parseConstExpression_instanceCreation() { Expression expression = parseConstExpression('const A()'); expect(expression, isNotNull); assertNoErrors(); expect(expression, isInstanceCreationExpression); var instanceCreation = expression as InstanceCreationExpression; expect(instanceCreation.keyword, isNotNull); ConstructorName name = instanceCreation.constructorName; expect(name, isNotNull); expect(name.type, isNotNull); expect(name.period, isNull); expect(name.name, isNull); expect(instanceCreation.argumentList, isNotNull); } void test_parseConstExpression_listLiteral_typed() { Expression expression = parseConstExpression('const []'); expect(expression, isNotNull); assertNoErrors(); var literal = expression as ListLiteral; expect(literal.constKeyword, isNotNull); expect(literal.typeArguments, isNotNull); expect(literal.leftBracket, isNotNull); expect(literal.elements, hasLength(0)); expect(literal.rightBracket, isNotNull); } void test_parseConstExpression_listLiteral_untyped() { Expression expression = parseConstExpression('const []'); expect(expression, isNotNull); assertNoErrors(); var literal = expression as ListLiteral; expect(literal.constKeyword, isNotNull); expect(literal.typeArguments, isNull); expect(literal.leftBracket, isNotNull); expect(literal.elements, hasLength(0)); expect(literal.rightBracket, isNotNull); } void test_parseConstExpression_mapLiteral_typed() { Expression expression = parseConstExpression('const {}'); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SetOrMapLiteral; expect(literal.leftBracket, isNotNull); expect(literal.elements, hasLength(0)); expect(literal.rightBracket, isNotNull); expect(literal.typeArguments, isNotNull); } void test_parseConstExpression_mapLiteral_typed_missingGt() { Expression expression = parseExpression( 'const ', codes: [ // TODO(danrubel): Improve this error message. ParserErrorCode.EXPECTED_TOKEN, ], ); expect(expression, isNotNull); } void test_parseExpression_function_async() { Expression expression = parseExpression('() async {}'); var functionExpression = expression as FunctionExpression; expect(functionExpression.body, isNotNull); expect(functionExpression.body.isAsynchronous, isTrue); expect(functionExpression.body.isGenerator, isFalse); expect(functionExpression.parameters, isNotNull); } void test_parseExpression_function_asyncStar() { Expression expression = parseExpression('() async* {}'); var functionExpression = expression as FunctionExpression; expect(functionExpression.body, isNotNull); expect(functionExpression.body.isAsynchronous, isTrue); expect(functionExpression.body.isGenerator, isTrue); expect(functionExpression.parameters, isNotNull); } void test_parseExpression_function_sync() { Expression expression = parseExpression('() {}'); var functionExpression = expression as FunctionExpression; expect(functionExpression.body, isNotNull); expect(functionExpression.body.isAsynchronous, isFalse); expect(functionExpression.body.isGenerator, isFalse); expect(functionExpression.parameters, isNotNull); } void test_parseExpression_function_syncStar() { Expression expression = parseExpression('() sync* {}'); var functionExpression = expression as FunctionExpression; expect(functionExpression.body, isNotNull); expect(functionExpression.body.isAsynchronous, isFalse); expect(functionExpression.body.isGenerator, isTrue); expect(functionExpression.parameters, isNotNull); } void test_parseExpression_invokeFunctionExpression() { Expression expression = parseExpression('(a) {return a + a;} (3)'); var invocation = expression as FunctionExpressionInvocation; expect(invocation.function, isFunctionExpression); FunctionExpression functionExpression = invocation.function as FunctionExpression; expect(functionExpression.parameters, isNotNull); expect(functionExpression.body, isNotNull); expect(invocation.typeArguments, isNull); ArgumentList list = invocation.argumentList; expect(list, isNotNull); expect(list.arguments, hasLength(1)); } void test_parseExpression_nonAwait() { Expression expression = parseExpression('await()'); var invocation = expression as MethodInvocation; expect(invocation.methodName.name, 'await'); expect(invocation.typeArguments, isNull); expect(invocation.argumentList, isNotNull); } void test_parseExpression_sendWithTypeParam_afterIndex() { var unit = parseCompilationUnit('main() { factories[C](); }'); expect(unit.declarations, hasLength(1)); var mainMethod = unit.declarations[0] as FunctionDeclaration; var body = mainMethod.functionExpression.body as BlockFunctionBody; NodeList statements = body.block.statements; expect(statements, hasLength(1)); var statement = statements[0] as ExpressionStatement; var expression = statement.expression as FunctionExpressionInvocation; var function = expression.function as IndexExpression; var target = function.target as SimpleIdentifier; expect(target.name, 'factories'); var index = function.index as SimpleIdentifier; expect(index.name, 'C'); List typeArguments = expression.typeArguments!.arguments; expect(typeArguments, hasLength(2)); expect((typeArguments[0] as NamedType).name.lexeme, 'num'); expect((typeArguments[1] as NamedType).name.lexeme, 'int'); expect(expression.argumentList.arguments, hasLength(0)); } void test_parseExpression_sendWithTypeParam_afterSend() { var unit = parseCompilationUnit('main() { factories(C)(); }'); expect(unit.declarations, hasLength(1)); var mainMethod = unit.declarations[0] as FunctionDeclaration; var body = mainMethod.functionExpression.body as BlockFunctionBody; NodeList statements = body.block.statements; expect(statements, hasLength(1)); var statement = statements[0] as ExpressionStatement; var expression = statement.expression as FunctionExpressionInvocation; var invocation = expression.function as MethodInvocation; expect(invocation.methodName.name, 'factories'); NodeList invocationArguments = invocation.argumentList.arguments; expect(invocationArguments, hasLength(1)); var index = invocationArguments[0] as SimpleIdentifier; expect(index.name, 'C'); List typeArguments = expression.typeArguments!.arguments; expect(typeArguments, hasLength(2)); expect((typeArguments[0] as NamedType).name.lexeme, 'num'); expect((typeArguments[1] as NamedType).name.lexeme, 'int'); expect(expression.argumentList.arguments, hasLength(0)); } void test_parseExpression_superMethodInvocation() { Expression expression = parseExpression('super.m()'); var invocation = expression as MethodInvocation; expect(invocation.target, isNotNull); expect(invocation.methodName, isNotNull); expect(invocation.typeArguments, isNull); expect(invocation.argumentList, isNotNull); } void test_parseExpression_superMethodInvocation_typeArguments() { Expression expression = parseExpression('super.m()'); var invocation = expression as MethodInvocation; expect(invocation.target, isNotNull); expect(invocation.methodName, isNotNull); expect(invocation.typeArguments, isNotNull); expect(invocation.argumentList, isNotNull); } void test_parseExpression_superMethodInvocation_typeArguments_chained() { Expression expression = parseExpression('super.b.c()'); MethodInvocation invocation = expression as MethodInvocation; var target = invocation.target as Expression; expect(target, isPropertyAccess); expect(invocation.methodName, isNotNull); expect(invocation.methodName.name, 'c'); expect(invocation.typeArguments, isNotNull); expect(invocation.argumentList, isNotNull); } void test_parseExpressionList_multiple() { List result = parseExpressionList('1, 2, 3'); expect(result, isNotNull); assertNoErrors(); expect(result, hasLength(3)); } void test_parseExpressionList_single() { List result = parseExpressionList('1'); expect(result, isNotNull); assertNoErrors(); expect(result, hasLength(1)); } void test_parseExpressionWithoutCascade_assign() { // TODO(brianwilkerson): Implement more tests for this method. Expression expression = parseExpressionWithoutCascade('x = y'); expect(expression, isNotNull); assertNoErrors(); var assignmentExpression = expression as AssignmentExpression; expect(assignmentExpression.leftHandSide, isNotNull); expect(assignmentExpression.operator, isNotNull); expect(assignmentExpression.operator.type, TokenType.EQ); expect(assignmentExpression.rightHandSide, isNotNull); } void test_parseExpressionWithoutCascade_comparison() { Expression expression = parseExpressionWithoutCascade('--a.b == c'); expect(expression, isNotNull); assertNoErrors(); var binaryExpression = expression as BinaryExpression; expect(binaryExpression.leftOperand, isNotNull); expect(binaryExpression.operator, isNotNull); expect(binaryExpression.operator.type, TokenType.EQ_EQ); expect(binaryExpression.rightOperand, isNotNull); } void test_parseExpressionWithoutCascade_superMethodInvocation() { Expression expression = parseExpressionWithoutCascade('super.m()'); expect(expression, isNotNull); assertNoErrors(); var invocation = expression as MethodInvocation; expect(invocation.target, isNotNull); expect(invocation.methodName, isNotNull); expect(invocation.typeArguments, isNull); expect(invocation.argumentList, isNotNull); } void test_parseExpressionWithoutCascade_superMethodInvocation_typeArguments() { Expression expression = parseExpressionWithoutCascade('super.m()'); expect(expression, isNotNull); assertNoErrors(); var invocation = expression as MethodInvocation; expect(invocation.target, isNotNull); expect(invocation.methodName, isNotNull); expect(invocation.typeArguments, isNotNull); expect(invocation.argumentList, isNotNull); } void test_parseFunctionExpression_body_inExpression() { FunctionExpression expression = parseFunctionExpression('(int i) => i++'); expect(expression, isNotNull); assertNoErrors(); expect(expression.body, isNotNull); expect(expression.typeParameters, isNull); expect(expression.parameters, isNotNull); expect((expression.body as ExpressionFunctionBody).semicolon, isNull); } void test_parseFunctionExpression_constAndTypeParameters2() { FunctionExpression expression = parseFunctionExpression( 'const (E i) => i++', ); expect(expression, isNotNull); assertErrorsWithCodes([ParserErrorCode.UNEXPECTED_TOKEN]); expect(expression.body, isNotNull); expect(expression.typeParameters, isNotNull); expect(expression.parameters, isNotNull); expect((expression.body as ExpressionFunctionBody).semicolon, isNull); } void test_parseFunctionExpression_functionInPlaceOfTypeName() { Expression expression = parseExpression( '[0, 1, 2]', codes: [ParserErrorCode.EXPECTED_TOKEN], ); expect(expression, isNotNull); var literal = expression as ListLiteral; expect(literal.typeArguments!.arguments, hasLength(1)); } void test_parseFunctionExpression_typeParameters() { FunctionExpression expression = parseFunctionExpression('(E i) => i++'); expect(expression, isNotNull); assertNoErrors(); expect(expression.body, isNotNull); expect(expression.typeParameters, isNotNull); expect(expression.parameters, isNotNull); expect((expression.body as ExpressionFunctionBody).semicolon, isNull); } void test_parseInstanceCreationExpression_qualifiedType() { Token token = TokenFactory.tokenFromKeyword(Keyword.NEW); InstanceCreationExpression expression = parseInstanceCreationExpression( 'A.B()', token, ); expect(expression, isNotNull); assertNoErrors(); expect(expression.keyword!.keyword, Keyword.NEW); ConstructorName name = expression.constructorName; expect(name, isNotNull); NamedType type = name.type; expect(type.importPrefix!.name.lexeme, 'A'); expect(type.name.lexeme, 'B'); expect(type.typeArguments, isNull); expect(name.period, isNull); expect(name.name, isNull); expect(expression.argumentList, isNotNull); } void test_parseInstanceCreationExpression_qualifiedType_named() { Token token = TokenFactory.tokenFromKeyword(Keyword.NEW); InstanceCreationExpression expression = parseInstanceCreationExpression( 'A.B.c()', token, ); expect(expression, isNotNull); assertNoErrors(); expect(expression.keyword!.keyword, Keyword.NEW); ConstructorName name = expression.constructorName; expect(name, isNotNull); NamedType type = name.type; expect(type, isNotNull); expect(type.typeArguments, isNull); expect(name.period, isNotNull); expect(name.name, isNotNull); expect(expression.argumentList, isNotNull); } void test_parseInstanceCreationExpression_qualifiedType_named_typeArguments() { Token token = TokenFactory.tokenFromKeyword(Keyword.NEW); InstanceCreationExpression expression = parseInstanceCreationExpression( 'A.B.c()', token, ); expect(expression, isNotNull); assertNoErrors(); expect(expression.keyword!.keyword, Keyword.NEW); ConstructorName name = expression.constructorName; expect(name, isNotNull); NamedType type = name.type; expect(type, isNotNull); expect(type.typeArguments!.arguments, hasLength(1)); expect(name.period, isNotNull); expect(name.name, isNotNull); expect(expression.argumentList, isNotNull); } void test_parseInstanceCreationExpression_qualifiedType_typeArguments() { Token token = TokenFactory.tokenFromKeyword(Keyword.NEW); InstanceCreationExpression expression = parseInstanceCreationExpression( 'A.B()', token, ); expect(expression, isNotNull); assertNoErrors(); expect(expression.keyword!.keyword, Keyword.NEW); ConstructorName name = expression.constructorName; expect(name, isNotNull); NamedType type = name.type; expect(type, isNotNull); expect(type.typeArguments!.arguments, hasLength(1)); expect(name.period, isNull); expect(name.name, isNull); expect(expression.argumentList, isNotNull); } void test_parseInstanceCreationExpression_type() { Token token = TokenFactory.tokenFromKeyword(Keyword.NEW); InstanceCreationExpression expression = parseInstanceCreationExpression( 'A()', token, ); expect(expression, isNotNull); assertNoErrors(); expect(expression.keyword!.keyword, Keyword.NEW); ConstructorName name = expression.constructorName; expect(name, isNotNull); NamedType type = name.type; expect(type, isNotNull); expect(type.typeArguments, isNull); expect(name.period, isNull); expect(name.name, isNull); expect(expression.argumentList, isNotNull); } void test_parseInstanceCreationExpression_type_named() { Token token = TokenFactory.tokenFromKeyword(Keyword.NEW); InstanceCreationExpression expression = parseInstanceCreationExpression( 'A.c()', token, ); expect(expression, isNotNull); assertNoErrors(); expect(expression.keyword!.keyword, Keyword.NEW); ConstructorName name = expression.constructorName; expect(name, isNotNull); NamedType type = name.type; expect(type, isNotNull); expect(type.typeArguments, isNull); expect(name.period, isNull); expect(name.name, isNull); expect(expression.argumentList, isNotNull); } void test_parseInstanceCreationExpression_type_named_typeArguments() { Token token = TokenFactory.tokenFromKeyword(Keyword.NEW); var expression = parseInstanceCreationExpression('A.c()', token) as InstanceCreationExpressionImpl; expect(expression, isNotNull); assertNoErrors(); expect(expression.keyword!.keyword, Keyword.NEW); ConstructorName name = expression.constructorName; expect(name, isNotNull); NamedType type = name.type; expect(type, isNotNull); expect(type.typeArguments!.arguments, hasLength(1)); expect(name.period, isNotNull); expect(name.name, isNotNull); expect(expression.argumentList, isNotNull); expect(expression.typeArguments, isNull); } void test_parseInstanceCreationExpression_type_named_typeArguments_34403() { var expression = parseExpression( 'new a.b.c()', errors: [ expectedError( ParserErrorCode.CONSTRUCTOR_WITH_TYPE_ARGUMENTS, 8, 1, ), ], ) as InstanceCreationExpressionImpl; expect(expression, isNotNull); expect(expression.keyword!.keyword, Keyword.NEW); ConstructorName name = expression.constructorName; expect(name, isNotNull); NamedType type = name.type; expect(type, isNotNull); expect(type.typeArguments, isNull); expect(name.period, isNotNull); expect(name.name, isNotNull); expect(expression.argumentList, isNotNull); expect(expression.typeArguments!.arguments, hasLength(1)); } void test_parseInstanceCreationExpression_type_typeArguments() { Token token = TokenFactory.tokenFromKeyword(Keyword.NEW); InstanceCreationExpression expression = parseInstanceCreationExpression( 'A()', token, ); expect(expression, isNotNull); assertNoErrors(); expect(expression.keyword!.keyword, Keyword.NEW); ConstructorName name = expression.constructorName; expect(name, isNotNull); NamedType type = name.type; expect(type, isNotNull); expect(type.typeArguments!.arguments, hasLength(1)); expect(name.period, isNull); expect(name.name, isNull); expect(expression.argumentList, isNotNull); } void test_parseListLiteral_empty_oneToken() { Token token = TokenFactory.tokenFromKeyword(Keyword.CONST); ListLiteral literal = parseListLiteral(token, null, '[]'); expect(literal, isNotNull); assertNoErrors(); expect(literal.constKeyword!.keyword, Keyword.CONST); expect(literal.typeArguments, isNull); expect(literal.leftBracket, isNotNull); expect(literal.elements, hasLength(0)); expect(literal.rightBracket, isNotNull); } void test_parseListLiteral_empty_oneToken_withComment() { ListLiteral literal = parseListLiteral(null, null, '/* 0 */ []'); expect(literal, isNotNull); assertNoErrors(); expect(literal.constKeyword, isNull); expect(literal.typeArguments, isNull); Token leftBracket = literal.leftBracket; expect(leftBracket, isNotNull); expect(leftBracket.precedingComments, isNotNull); expect(literal.elements, hasLength(0)); expect(literal.rightBracket, isNotNull); } void test_parseListLiteral_empty_twoTokens() { Token token = TokenFactory.tokenFromKeyword(Keyword.CONST); ListLiteral literal = parseListLiteral(token, null, '[ ]'); expect(literal, isNotNull); assertNoErrors(); expect(literal.constKeyword!.keyword, Keyword.CONST); expect(literal.typeArguments, isNull); expect(literal.leftBracket, isNotNull); expect(literal.elements, hasLength(0)); expect(literal.rightBracket, isNotNull); } void test_parseListLiteral_multiple() { ListLiteral literal = parseListLiteral(null, null, '[1, 2, 3]'); expect(literal, isNotNull); assertNoErrors(); expect(literal.constKeyword, isNull); expect(literal.typeArguments, isNull); expect(literal.leftBracket, isNotNull); expect(literal.elements, hasLength(3)); expect(literal.rightBracket, isNotNull); } void test_parseListLiteral_single() { ListLiteral literal = parseListLiteral(null, null, '[1]'); expect(literal, isNotNull); assertNoErrors(); expect(literal.constKeyword, isNull); expect(literal.typeArguments, isNull); expect(literal.leftBracket, isNotNull); expect(literal.elements, hasLength(1)); expect(literal.rightBracket, isNotNull); } void test_parseListLiteral_single_withTypeArgument() { ListLiteral literal = parseListLiteral(null, '', '[1]'); expect(literal, isNotNull); assertNoErrors(); expect(literal.constKeyword, isNull); expect(literal.typeArguments, isNotNull); expect(literal.leftBracket, isNotNull); expect(literal.elements, hasLength(1)); expect(literal.rightBracket, isNotNull); } void test_parseListOrMapLiteral_list_noType() { TypedLiteral literal = parseListOrMapLiteral(null, '[1]'); expect(literal, isNotNull); assertNoErrors(); var listLiteral = literal as ListLiteral; expect(listLiteral.constKeyword, isNull); expect(listLiteral.typeArguments, isNull); expect(listLiteral.leftBracket, isNotNull); expect(listLiteral.elements, hasLength(1)); expect(listLiteral.rightBracket, isNotNull); } void test_parseListOrMapLiteral_list_type() { TypedLiteral literal = parseListOrMapLiteral(null, ' [1]'); expect(literal, isNotNull); assertNoErrors(); var listLiteral = literal as ListLiteral; expect(listLiteral.constKeyword, isNull); expect(listLiteral.typeArguments, isNotNull); expect(listLiteral.leftBracket, isNotNull); expect(listLiteral.elements, hasLength(1)); expect(listLiteral.rightBracket, isNotNull); } void test_parseListOrMapLiteral_map_noType() { TypedLiteral literal = parseListOrMapLiteral(null, "{'1' : 1}"); expect(literal, isNotNull); assertNoErrors(); var mapLiteral = literal as SetOrMapLiteral; expect(mapLiteral.constKeyword, isNull); expect(mapLiteral.typeArguments, isNull); expect(mapLiteral.leftBracket, isNotNull); expect(mapLiteral.elements, hasLength(1)); expect(mapLiteral.rightBracket, isNotNull); } void test_parseListOrMapLiteral_map_type() { TypedLiteral literal = parseListOrMapLiteral( null, " {'1' : 1}", ); expect(literal, isNotNull); assertNoErrors(); var mapLiteral = literal as SetOrMapLiteral; expect(mapLiteral.constKeyword, isNull); expect(mapLiteral.typeArguments, isNotNull); expect(mapLiteral.leftBracket, isNotNull); expect(mapLiteral.elements, hasLength(1)); expect(mapLiteral.rightBracket, isNotNull); } void test_parseLogicalAndExpression() { Expression expression = parseLogicalAndExpression('x && y'); expect(expression, isNotNull); assertNoErrors(); var binaryExpression = expression as BinaryExpression; expect(binaryExpression.leftOperand, isNotNull); expect(binaryExpression.operator, isNotNull); expect(binaryExpression.operator.type, TokenType.AMPERSAND_AMPERSAND); expect(binaryExpression.rightOperand, isNotNull); } void test_parseLogicalOrExpression() { Expression expression = parseLogicalOrExpression('x || y'); expect(expression, isNotNull); assertNoErrors(); var binaryExpression = expression as BinaryExpression; expect(binaryExpression.leftOperand, isNotNull); expect(binaryExpression.operator, isNotNull); expect(binaryExpression.operator.type, TokenType.BAR_BAR); expect(binaryExpression.rightOperand, isNotNull); } void test_parseMapLiteral_empty() { Token token = TokenFactory.tokenFromKeyword(Keyword.CONST); SetOrMapLiteral literal = parseMapLiteral(token, '', '{}'); expect(literal, isNotNull); assertNoErrors(); expect(literal.constKeyword!.keyword, Keyword.CONST); expect(literal.typeArguments, isNotNull); expect(literal.leftBracket, isNotNull); expect(literal.elements, hasLength(0)); expect(literal.rightBracket, isNotNull); } void test_parseMapLiteral_multiple() { SetOrMapLiteral literal = parseMapLiteral(null, null, "{'a' : b, 'x' : y}"); expect(literal, isNotNull); assertNoErrors(); expect(literal.leftBracket, isNotNull); expect(literal.elements, hasLength(2)); expect(literal.rightBracket, isNotNull); } void test_parseMapLiteral_multiple_trailing_comma() { SetOrMapLiteral literal = parseMapLiteral( null, null, "{'a' : b, 'x' : y,}", ); expect(literal, isNotNull); assertNoErrors(); expect(literal.leftBracket, isNotNull); expect(literal.elements, hasLength(2)); expect(literal.rightBracket, isNotNull); } void test_parseMapLiteral_single() { SetOrMapLiteral literal = parseMapLiteral(null, null, "{'x' : y}"); expect(literal, isNotNull); assertNoErrors(); expect(literal.leftBracket, isNotNull); expect(literal.elements, hasLength(1)); expect(literal.rightBracket, isNotNull); } void test_parseMapLiteralEntry_complex() { MapLiteralEntry entry = parseMapLiteralEntry('2 + 2 : y'); expect(entry, isNotNull); assertNoErrors(); expect(entry.key, isNotNull); expect(entry.separator, isNotNull); expect(entry.value, isNotNull); } void test_parseMapLiteralEntry_int() { MapLiteralEntry entry = parseMapLiteralEntry('0 : y'); expect(entry, isNotNull); assertNoErrors(); expect(entry.key, isNotNull); expect(entry.separator, isNotNull); expect(entry.value, isNotNull); } void test_parseMapLiteralEntry_string() { MapLiteralEntry entry = parseMapLiteralEntry("'x' : y"); expect(entry, isNotNull); assertNoErrors(); expect(entry.key, isNotNull); expect(entry.separator, isNotNull); expect(entry.value, isNotNull); } void test_parseMultiplicativeExpression_normal() { Expression expression = parseMultiplicativeExpression('x * y'); expect(expression, isNotNull); assertNoErrors(); var binaryExpression = expression as BinaryExpression; expect(binaryExpression.leftOperand, isNotNull); expect(binaryExpression.operator, isNotNull); expect(binaryExpression.operator.type, TokenType.STAR); expect(binaryExpression.rightOperand, isNotNull); } void test_parseMultiplicativeExpression_super() { Expression expression = parseMultiplicativeExpression('super * y'); expect(expression, isNotNull); assertNoErrors(); var binaryExpression = expression as BinaryExpression; expect(binaryExpression.leftOperand, isSuperExpression); expect(binaryExpression.operator, isNotNull); expect(binaryExpression.operator.type, TokenType.STAR); expect(binaryExpression.rightOperand, isNotNull); } void test_parseNewExpression() { InstanceCreationExpression expression = parseNewExpression('new A()'); expect(expression, isNotNull); assertNoErrors(); expect(expression.keyword, isNotNull); ConstructorName name = expression.constructorName; expect(name, isNotNull); expect(name.type, isNotNull); expect(name.period, isNull); expect(name.name, isNull); expect(expression.argumentList, isNotNull); } void test_parsePostfixExpression_decrement() { Expression expression = parsePostfixExpression('i--'); expect(expression, isNotNull); assertNoErrors(); var postfixExpression = expression as PostfixExpression; expect(postfixExpression.operand, isNotNull); expect(postfixExpression.operator, isNotNull); expect(postfixExpression.operator.type, TokenType.MINUS_MINUS); } void test_parsePostfixExpression_increment() { Expression expression = parsePostfixExpression('i++'); expect(expression, isNotNull); assertNoErrors(); var postfixExpression = expression as PostfixExpression; expect(postfixExpression.operand, isNotNull); expect(postfixExpression.operator, isNotNull); expect(postfixExpression.operator.type, TokenType.PLUS_PLUS); } void test_parsePostfixExpression_none_indexExpression() { Expression expression = parsePostfixExpression('a[0]'); expect(expression, isNotNull); assertNoErrors(); var indexExpression = expression as IndexExpression; expect(indexExpression.target, isNotNull); expect(indexExpression.index, isNotNull); } void test_parsePostfixExpression_none_methodInvocation() { Expression expression = parsePostfixExpression('a.m()'); expect(expression, isNotNull); assertNoErrors(); var methodInvocation = expression as MethodInvocation; expect(methodInvocation.target, isNotNull); expect(methodInvocation.operator!.type, TokenType.PERIOD); expect(methodInvocation.methodName, isNotNull); expect(methodInvocation.typeArguments, isNull); expect(methodInvocation.argumentList, isNotNull); } void test_parsePostfixExpression_none_methodInvocation_question_dot() { Expression expression = parsePostfixExpression('a?.m()'); expect(expression, isNotNull); assertNoErrors(); var methodInvocation = expression as MethodInvocation; expect(methodInvocation.target, isNotNull); expect(methodInvocation.operator!.type, TokenType.QUESTION_PERIOD); expect(methodInvocation.methodName, isNotNull); expect(methodInvocation.typeArguments, isNull); expect(methodInvocation.argumentList, isNotNull); } void test_parsePostfixExpression_none_methodInvocation_question_dot_typeArguments() { Expression expression = parsePostfixExpression('a?.m()'); expect(expression, isNotNull); assertNoErrors(); var methodInvocation = expression as MethodInvocation; expect(methodInvocation.target, isNotNull); expect(methodInvocation.operator!.type, TokenType.QUESTION_PERIOD); expect(methodInvocation.methodName, isNotNull); expect(methodInvocation.typeArguments, isNotNull); expect(methodInvocation.argumentList, isNotNull); } void test_parsePostfixExpression_none_methodInvocation_typeArguments() { Expression expression = parsePostfixExpression('a.m()'); expect(expression, isNotNull); assertNoErrors(); var methodInvocation = expression as MethodInvocation; expect(methodInvocation.target, isNotNull); expect(methodInvocation.operator!.type, TokenType.PERIOD); expect(methodInvocation.methodName, isNotNull); expect(methodInvocation.typeArguments, isNotNull); expect(methodInvocation.argumentList, isNotNull); } void test_parsePostfixExpression_none_propertyAccess() { Expression expression = parsePostfixExpression('a.b'); expect(expression, isNotNull); assertNoErrors(); var identifier = expression as PrefixedIdentifier; expect(identifier.prefix, isNotNull); expect(identifier.identifier, isNotNull); } void test_parsePrefixedIdentifier_noPrefix() { String lexeme = "bar"; Identifier identifier = parsePrefixedIdentifier(lexeme); expect(identifier, isNotNull); assertNoErrors(); var simpleIdentifier = identifier as SimpleIdentifier; expect(simpleIdentifier.token, isNotNull); expect(simpleIdentifier.name, lexeme); } void test_parsePrefixedIdentifier_prefix() { String lexeme = "foo.bar"; Identifier identifier = parsePrefixedIdentifier(lexeme); expect(identifier, isNotNull); assertNoErrors(); var prefixedIdentifier = identifier as PrefixedIdentifier; expect(prefixedIdentifier.prefix.name, "foo"); expect(prefixedIdentifier.period, isNotNull); expect(prefixedIdentifier.identifier.name, "bar"); } void test_parsePrimaryExpression_const() { Expression expression = parsePrimaryExpression('const A()'); expect(expression, isNotNull); assertNoErrors(); expect(expression, isNotNull); } void test_parsePrimaryExpression_double() { String doubleLiteral = "3.2e4"; Expression expression = parsePrimaryExpression(doubleLiteral); expect(expression, isNotNull); assertNoErrors(); var literal = expression as DoubleLiteral; expect(literal.literal, isNotNull); expect(literal.value, double.parse(doubleLiteral)); } void test_parsePrimaryExpression_false() { Expression expression = parsePrimaryExpression('false'); expect(expression, isNotNull); assertNoErrors(); var literal = expression as BooleanLiteral; expect(literal.literal, isNotNull); expect(literal.value, isFalse); } void test_parsePrimaryExpression_function_arguments() { Expression expression = parsePrimaryExpression('(int i) => i + 1'); expect(expression, isNotNull); assertNoErrors(); var functionExpression = expression as FunctionExpression; expect(functionExpression.parameters, isNotNull); expect(functionExpression.body, isNotNull); } void test_parsePrimaryExpression_function_noArguments() { Expression expression = parsePrimaryExpression('() => 42'); expect(expression, isNotNull); assertNoErrors(); var functionExpression = expression as FunctionExpression; expect(functionExpression.parameters, isNotNull); expect(functionExpression.body, isNotNull); } void test_parsePrimaryExpression_genericFunctionExpression() { Expression expression = parsePrimaryExpression( '(Map m, X x) => m[x]', ); expect(expression, isNotNull); assertNoErrors(); var functionExpression = expression as FunctionExpression; expect(functionExpression.typeParameters, isNotNull); } void test_parsePrimaryExpression_hex() { String hexLiteral = "3F"; Expression expression = parsePrimaryExpression('0x$hexLiteral'); expect(expression, isNotNull); assertNoErrors(); var literal = expression as IntegerLiteral; expect(literal.literal, isNotNull); expect(literal.value, int.parse(hexLiteral, radix: 16)); } void test_parsePrimaryExpression_identifier() { Expression expression = parsePrimaryExpression('a'); expect(expression, isNotNull); assertNoErrors(); var identifier = expression as SimpleIdentifier; expect(identifier, isNotNull); } void test_parsePrimaryExpression_int() { String intLiteral = "472"; Expression expression = parsePrimaryExpression(intLiteral); expect(expression, isNotNull); assertNoErrors(); var literal = expression as IntegerLiteral; expect(literal.literal, isNotNull); expect(literal.value, int.parse(intLiteral)); } void test_parsePrimaryExpression_listLiteral() { Expression expression = parsePrimaryExpression('[ ]'); expect(expression, isNotNull); assertNoErrors(); var literal = expression as ListLiteral; expect(literal, isNotNull); } void test_parsePrimaryExpression_listLiteral_index() { Expression expression = parsePrimaryExpression('[]'); expect(expression, isNotNull); assertNoErrors(); var literal = expression as ListLiteral; expect(literal, isNotNull); } void test_parsePrimaryExpression_listLiteral_typed() { Expression expression = parsePrimaryExpression('[ ]'); expect(expression, isNotNull); assertNoErrors(); var literal = expression as ListLiteral; expect(literal.typeArguments, isNotNull); expect(literal.typeArguments!.arguments, hasLength(1)); } void test_parsePrimaryExpression_mapLiteral() { Expression expression = parsePrimaryExpression('{}'); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SetOrMapLiteral; expect(literal.typeArguments, isNull); expect(literal, isNotNull); } void test_parsePrimaryExpression_mapLiteral_typed() { Expression expression = parsePrimaryExpression('{}'); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SetOrMapLiteral; expect(literal.typeArguments, isNotNull); expect(literal.typeArguments!.arguments, hasLength(2)); } void test_parsePrimaryExpression_new() { Expression expression = parsePrimaryExpression('new A()'); expect(expression, isNotNull); assertNoErrors(); var creation = expression as InstanceCreationExpression; expect(creation, isNotNull); } void test_parsePrimaryExpression_null() { Expression expression = parsePrimaryExpression('null'); expect(expression, isNotNull); assertNoErrors(); expect(expression, isNullLiteral); var literal = expression as NullLiteral; expect(literal.literal, isNotNull); } void test_parsePrimaryExpression_parenthesized() { Expression expression = parsePrimaryExpression('(x)'); expect(expression, isNotNull); assertNoErrors(); var parens = expression as ParenthesizedExpression; expect(parens, isNotNull); } void test_parsePrimaryExpression_string() { Expression expression = parsePrimaryExpression('"string"'); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SimpleStringLiteral; expect(literal.isMultiline, isFalse); expect(literal.isRaw, isFalse); expect(literal.value, "string"); } void test_parsePrimaryExpression_string_multiline() { Expression expression = parsePrimaryExpression("'''string'''"); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SimpleStringLiteral; expect(literal.isMultiline, isTrue); expect(literal.isRaw, isFalse); expect(literal.value, "string"); } void test_parsePrimaryExpression_string_raw() { Expression expression = parsePrimaryExpression("r'string'"); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SimpleStringLiteral; expect(literal.isMultiline, isFalse); expect(literal.isRaw, isTrue); expect(literal.value, "string"); } void test_parsePrimaryExpression_super() { Expression expression = parseExpression('super.x'); expect(expression, isNotNull); assertNoErrors(); var propertyAccess = expression as PropertyAccess; expect(propertyAccess.target is SuperExpression, isTrue); expect(propertyAccess.operator, isNotNull); expect(propertyAccess.operator.type, TokenType.PERIOD); expect(propertyAccess.propertyName, isNotNull); } void test_parsePrimaryExpression_this() { Expression expression = parsePrimaryExpression('this'); expect(expression, isNotNull); assertNoErrors(); var thisExpression = expression as ThisExpression; expect(thisExpression.thisKeyword, isNotNull); } void test_parsePrimaryExpression_true() { Expression expression = parsePrimaryExpression('true'); expect(expression, isNotNull); assertNoErrors(); var literal = expression as BooleanLiteral; expect(literal.literal, isNotNull); expect(literal.value, isTrue); } void test_parseRedirectingConstructorInvocation_named() { var invocation = parseConstructorInitializer('this.a()') as RedirectingConstructorInvocation; assertNoErrors(); expect(invocation.argumentList, isNotNull); expect(invocation.constructorName, isNotNull); expect(invocation.thisKeyword, isNotNull); expect(invocation.period, isNotNull); } void test_parseRedirectingConstructorInvocation_unnamed() { var invocation = parseConstructorInitializer('this()') as RedirectingConstructorInvocation; assertNoErrors(); expect(invocation.argumentList, isNotNull); expect(invocation.constructorName, isNull); expect(invocation.thisKeyword, isNotNull); expect(invocation.period, isNull); } void test_parseRelationalExpression_as_chained() { var asExpression = parseExpression( 'x as Y as Z', errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 2)], ) as AsExpression; expect(asExpression, isNotNull); var identifier = asExpression.expression as SimpleIdentifier; expect(identifier.name, 'x'); expect(asExpression.asOperator, isNotNull); var namedType = asExpression.type as NamedType; expect(namedType.name.lexeme, 'Y'); } void test_parseRelationalExpression_as_functionType_noReturnType() { Expression expression = parseRelationalExpression('x as Function(int)'); expect(expression, isNotNull); assertNoErrors(); var asExpression = expression as AsExpression; expect(asExpression.expression, isNotNull); expect(asExpression.asOperator, isNotNull); expect(asExpression.type, isGenericFunctionType); } void test_parseRelationalExpression_as_functionType_returnType() { Expression expression = parseRelationalExpression( 'x as String Function(int)', ); expect(expression, isNotNull); assertNoErrors(); var asExpression = expression as AsExpression; expect(asExpression.expression, isNotNull); expect(asExpression.asOperator, isNotNull); expect(asExpression.type, isGenericFunctionType); } void test_parseRelationalExpression_as_generic() { Expression expression = parseRelationalExpression('x as C'); expect(expression, isNotNull); assertNoErrors(); var asExpression = expression as AsExpression; expect(asExpression.expression, isNotNull); expect(asExpression.asOperator, isNotNull); expect(asExpression.type, isNamedType); } void test_parseRelationalExpression_as_simple() { Expression expression = parseRelationalExpression('x as Y'); expect(expression, isNotNull); assertNoErrors(); var asExpression = expression as AsExpression; expect(asExpression.expression, isNotNull); expect(asExpression.asOperator, isNotNull); expect(asExpression.type, isNamedType); } void test_parseRelationalExpression_as_simple_function() { Expression expression = parseRelationalExpression('x as Function'); expect(expression, isNotNull); assertNoErrors(); var asExpression = expression as AsExpression; expect(asExpression.expression, isNotNull); expect(asExpression.asOperator, isNotNull); expect(asExpression.type, isNamedType); } void test_parseRelationalExpression_is() { Expression expression = parseRelationalExpression('x is y'); expect(expression, isNotNull); assertNoErrors(); var isExpression = expression as IsExpression; expect(isExpression.expression, isNotNull); expect(isExpression.isOperator, isNotNull); expect(isExpression.notOperator, isNull); expect(isExpression.type, isNotNull); } void test_parseRelationalExpression_is_chained() { var isExpression = parseExpression( 'x is Y is! Z', errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 2)], ) as IsExpression; expect(isExpression, isNotNull); var identifier = isExpression.expression as SimpleIdentifier; expect(identifier.name, 'x'); expect(isExpression.isOperator, isNotNull); var namedType = isExpression.type as NamedType; expect(namedType.name.lexeme, 'Y'); } void test_parseRelationalExpression_isNot() { Expression expression = parseRelationalExpression('x is! y'); expect(expression, isNotNull); assertNoErrors(); var isExpression = expression as IsExpression; expect(isExpression.expression, isNotNull); expect(isExpression.isOperator, isNotNull); expect(isExpression.notOperator, isNotNull); expect(isExpression.type, isNotNull); } void test_parseRelationalExpression_normal() { Expression expression = parseRelationalExpression('x < y'); expect(expression, isNotNull); assertNoErrors(); var binaryExpression = expression as BinaryExpression; expect(binaryExpression.leftOperand, isNotNull); expect(binaryExpression.operator, isNotNull); expect(binaryExpression.operator.type, TokenType.LT); expect(binaryExpression.rightOperand, isNotNull); } void test_parseRelationalExpression_super() { Expression expression = parseRelationalExpression('super < y'); expect(expression, isNotNull); assertNoErrors(); var binaryExpression = expression as BinaryExpression; expect(binaryExpression.leftOperand, isNotNull); expect(binaryExpression.operator, isNotNull); expect(binaryExpression.operator.type, TokenType.LT); expect(binaryExpression.rightOperand, isNotNull); } void test_parseRethrowExpression() { RethrowExpression expression = parseRethrowExpression('rethrow'); expect(expression, isNotNull); assertNoErrors(); expect(expression.rethrowKeyword, isNotNull); } void test_parseShiftExpression_normal() { BinaryExpression expression = parseShiftExpression('x << y'); expect(expression, isNotNull); assertNoErrors(); expect(expression.leftOperand, isNotNull); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.LT_LT); expect(expression.rightOperand, isNotNull); } void test_parseShiftExpression_super() { BinaryExpression expression = parseShiftExpression('super << y'); expect(expression, isNotNull); assertNoErrors(); expect(expression.leftOperand, isNotNull); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.LT_LT); expect(expression.rightOperand, isNotNull); } void test_parseSimpleIdentifier1_normalIdentifier() { // TODO(brianwilkerson): Implement tests for this method. } void test_parseSimpleIdentifier_builtInIdentifier() { String lexeme = "as"; SimpleIdentifier identifier = parseSimpleIdentifier(lexeme); expect(identifier, isNotNull); assertNoErrors(); expect(identifier.token, isNotNull); expect(identifier.name, lexeme); } void test_parseSimpleIdentifier_normalIdentifier() { String lexeme = "foo"; SimpleIdentifier identifier = parseSimpleIdentifier(lexeme); expect(identifier, isNotNull); assertNoErrors(); expect(identifier.token, isNotNull); expect(identifier.name, lexeme); } void test_parseStringLiteral_adjacent() { Expression expression = parseStringLiteral("'a' 'b'"); expect(expression, isNotNull); assertNoErrors(); var literal = expression as AdjacentStrings; NodeList strings = literal.strings; expect(strings, hasLength(2)); StringLiteral firstString = strings[0]; StringLiteral secondString = strings[1]; expect((firstString as SimpleStringLiteral).value, "a"); expect((secondString as SimpleStringLiteral).value, "b"); } void test_parseStringLiteral_endsWithInterpolation() { Expression expression = parseStringLiteral(r"'x$y'"); expect(expression, isNotNull); assertNoErrors(); var interpolation = expression as StringInterpolation; expect(interpolation.elements, hasLength(3)); expect(interpolation.elements[0], isInterpolationString); var element0 = interpolation.elements[0] as InterpolationString; expect(element0.value, 'x'); expect(interpolation.elements[1], isInterpolationExpression); var element1 = interpolation.elements[1] as InterpolationExpression; expect(element1.leftBracket.lexeme, '\$'); expect(element1.expression, isSimpleIdentifier); expect(element1.rightBracket, isNull); expect(interpolation.elements[2], isInterpolationString); var element2 = interpolation.elements[2] as InterpolationString; expect(element2.value, ''); } void test_parseStringLiteral_interpolated() { Expression expression = parseStringLiteral("'a \${b} c \$this d'"); expect(expression, isNotNull); assertNoErrors(); expect(expression, isStringInterpolation); var literal = expression as StringInterpolation; NodeList elements = literal.elements; expect(elements, hasLength(5)); expect(elements[0] is InterpolationString, isTrue); expect(elements[1] is InterpolationExpression, isTrue); expect(elements[2] is InterpolationString, isTrue); expect(elements[3] is InterpolationExpression, isTrue); expect(elements[4] is InterpolationString, isTrue); expect((elements[1] as InterpolationExpression).leftBracket.lexeme, '\${'); expect((elements[1] as InterpolationExpression).rightBracket!.lexeme, '}'); expect((elements[3] as InterpolationExpression).leftBracket.lexeme, '\$'); expect((elements[3] as InterpolationExpression).rightBracket, isNull); } void test_parseStringLiteral_interpolated_void() { Expression expression = parseStringLiteral(r"'$void'"); expect(expression, isNotNull); assertErrors( errors: [ expectedError( ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 8, 4, ), ], ); expect(expression, isStringInterpolation); var literal = expression as StringInterpolation; NodeList elements = literal.elements; expect(elements, hasLength(3)); expect(elements[0] is InterpolationString, isTrue); expect(elements[1] is InterpolationExpression, isTrue); expect(elements[2] is InterpolationString, isTrue); expect((elements[1] as InterpolationExpression).leftBracket.lexeme, '\$'); expect((elements[1] as InterpolationExpression).rightBracket, isNull); } void test_parseStringLiteral_multiline_encodedSpace() { Expression expression = parseStringLiteral("'''\\x20\na'''"); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SimpleStringLiteral; expect(literal.literal, isNotNull); expect(literal.value, " \na"); } void test_parseStringLiteral_multiline_endsWithInterpolation() { Expression expression = parseStringLiteral(r"'''x$y'''"); expect(expression, isNotNull); assertNoErrors(); var interpolation = expression as StringInterpolation; expect(interpolation.elements, hasLength(3)); expect(interpolation.elements[0], isInterpolationString); var element0 = interpolation.elements[0] as InterpolationString; expect(element0.value, 'x'); expect(interpolation.elements[1], isInterpolationExpression); var element1 = interpolation.elements[1] as InterpolationExpression; expect(element1.expression, isSimpleIdentifier); expect(interpolation.elements[2], isInterpolationString); var element2 = interpolation.elements[2] as InterpolationString; expect(element2.value, ''); } void test_parseStringLiteral_multiline_escapedBackslash() { Expression expression = parseStringLiteral("'''\\\\\na'''"); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SimpleStringLiteral; expect(literal.literal, isNotNull); expect(literal.value, "\\\na"); } void test_parseStringLiteral_multiline_escapedBackslash_raw() { Expression expression = parseStringLiteral("r'''\\\\\na'''"); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SimpleStringLiteral; expect(literal.literal, isNotNull); expect(literal.value, "\\\\\na"); } void test_parseStringLiteral_multiline_escapedEolMarker() { Expression expression = parseStringLiteral("'''\\\na'''"); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SimpleStringLiteral; expect(literal.literal, isNotNull); expect(literal.value, "a"); } void test_parseStringLiteral_multiline_escapedEolMarker_raw() { Expression expression = parseStringLiteral("r'''\\\na'''"); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SimpleStringLiteral; expect(literal.literal, isNotNull); expect(literal.value, "a"); } void test_parseStringLiteral_multiline_escapedSpaceAndEolMarker() { Expression expression = parseStringLiteral("'''\\ \\\na'''"); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SimpleStringLiteral; expect(literal.literal, isNotNull); expect(literal.value, "a"); } void test_parseStringLiteral_multiline_escapedSpaceAndEolMarker_raw() { Expression expression = parseStringLiteral("r'''\\ \\\na'''"); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SimpleStringLiteral; expect(literal.literal, isNotNull); expect(literal.value, "a"); } void test_parseStringLiteral_multiline_escapedTab() { Expression expression = parseStringLiteral("'''\\t\na'''"); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SimpleStringLiteral; expect(literal.literal, isNotNull); expect(literal.value, "\t\na"); } void test_parseStringLiteral_multiline_escapedTab_raw() { Expression expression = parseStringLiteral("r'''\\t\na'''"); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SimpleStringLiteral; expect(literal.literal, isNotNull); expect(literal.value, "\\t\na"); } void test_parseStringLiteral_multiline_quoteAfterInterpolation() { Expression expression = parseStringLiteral(r"""'''$x'y'''"""); expect(expression, isNotNull); assertNoErrors(); var interpolation = expression as StringInterpolation; expect(interpolation.elements, hasLength(3)); expect(interpolation.elements[0], isInterpolationString); var element0 = interpolation.elements[0] as InterpolationString; expect(element0.value, ''); expect(interpolation.elements[1], isInterpolationExpression); var element1 = interpolation.elements[1] as InterpolationExpression; expect(element1.expression, isSimpleIdentifier); expect(interpolation.elements[2], isInterpolationString); var element2 = interpolation.elements[2] as InterpolationString; expect(element2.value, "'y"); } void test_parseStringLiteral_multiline_startsWithInterpolation() { Expression expression = parseStringLiteral(r"'''${x}y'''"); expect(expression, isNotNull); assertNoErrors(); var interpolation = expression as StringInterpolation; expect(interpolation.elements, hasLength(3)); expect(interpolation.elements[0], isInterpolationString); var element0 = interpolation.elements[0] as InterpolationString; expect(element0.value, ''); expect(interpolation.elements[1], isInterpolationExpression); var element1 = interpolation.elements[1] as InterpolationExpression; expect(element1.expression, isSimpleIdentifier); expect(interpolation.elements[2], isInterpolationString); var element2 = interpolation.elements[2] as InterpolationString; expect(element2.value, 'y'); } void test_parseStringLiteral_multiline_twoSpaces() { Expression expression = parseStringLiteral("''' \na'''"); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SimpleStringLiteral; expect(literal.literal, isNotNull); expect(literal.value, "a"); } void test_parseStringLiteral_multiline_twoSpaces_raw() { Expression expression = parseStringLiteral("r''' \na'''"); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SimpleStringLiteral; expect(literal.literal, isNotNull); expect(literal.value, "a"); } void test_parseStringLiteral_multiline_untrimmed() { Expression expression = parseStringLiteral("''' a\nb'''"); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SimpleStringLiteral; expect(literal.literal, isNotNull); expect(literal.value, " a\nb"); } void test_parseStringLiteral_quoteAfterInterpolation() { Expression expression = parseStringLiteral(r"""'$x"'"""); expect(expression, isNotNull); assertNoErrors(); var interpolation = expression as StringInterpolation; expect(interpolation.elements, hasLength(3)); expect(interpolation.elements[0], isInterpolationString); var element0 = interpolation.elements[0] as InterpolationString; expect(element0.value, ''); expect(interpolation.elements[1], isInterpolationExpression); var element1 = interpolation.elements[1] as InterpolationExpression; expect(element1.expression, isSimpleIdentifier); expect(interpolation.elements[2], isInterpolationString); var element2 = interpolation.elements[2] as InterpolationString; expect(element2.value, '"'); } void test_parseStringLiteral_single() { Expression expression = parseStringLiteral("'a'"); expect(expression, isNotNull); assertNoErrors(); var literal = expression as SimpleStringLiteral; expect(literal.literal, isNotNull); expect(literal.value, "a"); } void test_parseStringLiteral_startsWithInterpolation() { Expression expression = parseStringLiteral(r"'${x}y'"); expect(expression, isNotNull); assertNoErrors(); var interpolation = expression as StringInterpolation; expect(interpolation.elements, hasLength(3)); expect(interpolation.elements[0], isInterpolationString); var element0 = interpolation.elements[0] as InterpolationString; expect(element0.value, ''); expect(interpolation.elements[1], isInterpolationExpression); var element1 = interpolation.elements[1] as InterpolationExpression; expect(element1.expression, isSimpleIdentifier); expect(interpolation.elements[2], isInterpolationString); var element2 = interpolation.elements[2] as InterpolationString; expect(element2.value, 'y'); } void test_parseSuperConstructorInvocation_named() { var invocation = parseConstructorInitializer('super.a()') as SuperConstructorInvocation; expect(invocation, isNotNull); assertNoErrors(); expect(invocation.argumentList, isNotNull); expect(invocation.constructorName, isNotNull); expect(invocation.superKeyword, isNotNull); expect(invocation.period, isNotNull); } void test_parseSuperConstructorInvocation_unnamed() { var invocation = parseConstructorInitializer('super()') as SuperConstructorInvocation; assertNoErrors(); expect(invocation.argumentList, isNotNull); expect(invocation.constructorName, isNull); expect(invocation.superKeyword, isNotNull); expect(invocation.period, isNull); } void test_parseSymbolLiteral_builtInIdentifier() { SymbolLiteral literal = parseSymbolLiteral('#dynamic.static.abstract'); expect(literal, isNotNull); assertNoErrors(); expect(literal.poundSign, isNotNull); List components = literal.components; expect(components, hasLength(3)); expect(components[0].lexeme, "dynamic"); expect(components[1].lexeme, "static"); expect(components[2].lexeme, "abstract"); } void test_parseSymbolLiteral_multiple() { SymbolLiteral literal = parseSymbolLiteral('#a.b.c'); expect(literal, isNotNull); assertNoErrors(); expect(literal.poundSign, isNotNull); List components = literal.components; expect(components, hasLength(3)); expect(components[0].lexeme, "a"); expect(components[1].lexeme, "b"); expect(components[2].lexeme, "c"); } void test_parseSymbolLiteral_operator() { SymbolLiteral literal = parseSymbolLiteral('#=='); expect(literal, isNotNull); assertNoErrors(); expect(literal.poundSign, isNotNull); List components = literal.components; expect(components, hasLength(1)); expect(components[0].lexeme, "=="); } void test_parseSymbolLiteral_single() { SymbolLiteral literal = parseSymbolLiteral('#a'); expect(literal, isNotNull); assertNoErrors(); expect(literal.poundSign, isNotNull); List components = literal.components; expect(components, hasLength(1)); expect(components[0].lexeme, "a"); } void test_parseSymbolLiteral_void() { SymbolLiteral literal = parseSymbolLiteral('#void'); expect(literal, isNotNull); assertNoErrors(); expect(literal.poundSign, isNotNull); List components = literal.components; expect(components, hasLength(1)); expect(components[0].lexeme, "void"); } void test_parseThrowExpression() { Expression expression = parseThrowExpression('throw x'); expect(expression, isNotNull); assertNoErrors(); var throwExpression = expression as ThrowExpression; expect(throwExpression.throwKeyword, isNotNull); expect(throwExpression.expression, isNotNull); } void test_parseThrowExpressionWithoutCascade() { Expression expression = parseThrowExpressionWithoutCascade('throw x'); expect(expression, isNotNull); assertNoErrors(); var throwExpression = expression as ThrowExpression; expect(throwExpression.throwKeyword, isNotNull); expect(throwExpression.expression, isNotNull); } void test_parseUnaryExpression_decrement_identifier_index() { var expression = parseExpression('--a[0]') as PrefixExpression; expect(expression, isNotNull); assertNoErrors(); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.MINUS_MINUS); expect(expression.operand, isNotNull); IndexExpression operand = expression.operand as IndexExpression; expect(operand.realTarget, const TypeMatcher()); expect(operand.index is IntegerLiteral, isTrue); } void test_parseUnaryExpression_decrement_normal() { PrefixExpression expression = parseUnaryExpression('--x'); expect(expression, isNotNull); assertNoErrors(); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.MINUS_MINUS); expect(expression.operand, isNotNull); } @failingTest void test_parseUnaryExpression_decrement_super() { // TODO(danrubel): Reports a different error and different token stream. // Expected: TokenType: // Actual: TokenType: PrefixExpression expression = parseUnaryExpression('--super'); expect(expression, isNotNull); assertNoErrors(); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.MINUS); Expression innerExpression = expression.operand; expect(innerExpression, isNotNull); expect(innerExpression is PrefixExpression, isTrue); PrefixExpression operand = innerExpression as PrefixExpression; expect(operand.operator, isNotNull); expect(operand.operator.type, TokenType.MINUS); expect(operand.operand, isNotNull); } void test_parseUnaryExpression_decrement_super_propertyAccess() { PrefixExpression expression = parseUnaryExpression('--super.x'); expect(expression, isNotNull); assertNoErrors(); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.MINUS_MINUS); expect(expression.operand, isNotNull); PropertyAccess operand = expression.operand as PropertyAccess; expect(operand.target is SuperExpression, isTrue); expect(operand.propertyName.name, "x"); } @failingTest void test_parseUnaryExpression_decrement_super_withComment() { // TODO(danrubel): Reports a different error and different token stream. // Expected: TokenType: // Actual: TokenType: PrefixExpression expression = parseUnaryExpression('/* 0 */ --super'); expect(expression, isNotNull); assertNoErrors(); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.MINUS); expect(expression.operator.precedingComments, isNotNull); Expression innerExpression = expression.operand; expect(innerExpression, isNotNull); expect(innerExpression is PrefixExpression, isTrue); PrefixExpression operand = innerExpression as PrefixExpression; expect(operand.operator, isNotNull); expect(operand.operator.type, TokenType.MINUS); expect(operand.operand, isNotNull); } void test_parseUnaryExpression_increment_identifier_index() { var expression = parseExpression('++a[0]') as PrefixExpression; expect(expression, isNotNull); assertNoErrors(); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.PLUS_PLUS); expect(expression.operand, isNotNull); IndexExpression operand = expression.operand as IndexExpression; expect(operand.realTarget, const TypeMatcher()); expect(operand.index is IntegerLiteral, isTrue); } void test_parseUnaryExpression_increment_normal() { PrefixExpression expression = parseUnaryExpression('++x'); expect(expression, isNotNull); assertNoErrors(); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.PLUS_PLUS); expect(expression.operand, isNotNull); } void test_parseUnaryExpression_increment_super_index() { PrefixExpression expression = parseUnaryExpression('++super[0]'); expect(expression, isNotNull); assertNoErrors(); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.PLUS_PLUS); expect(expression.operand, isNotNull); IndexExpression operand = expression.operand as IndexExpression; expect(operand.realTarget is SuperExpression, isTrue); expect(operand.index is IntegerLiteral, isTrue); } void test_parseUnaryExpression_increment_super_propertyAccess() { PrefixExpression expression = parseUnaryExpression('++super.x'); expect(expression, isNotNull); assertNoErrors(); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.PLUS_PLUS); expect(expression.operand, isNotNull); PropertyAccess operand = expression.operand as PropertyAccess; expect(operand.target is SuperExpression, isTrue); expect(operand.propertyName.name, "x"); } void test_parseUnaryExpression_minus_identifier_index() { var expression = parseExpression('-a[0]') as PrefixExpression; expect(expression, isNotNull); assertNoErrors(); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.MINUS); expect(expression.operand, isNotNull); IndexExpression operand = expression.operand as IndexExpression; expect(operand.realTarget, const TypeMatcher()); expect(operand.index is IntegerLiteral, isTrue); } void test_parseUnaryExpression_minus_normal() { PrefixExpression expression = parseUnaryExpression('-x'); expect(expression, isNotNull); assertNoErrors(); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.MINUS); expect(expression.operand, isNotNull); } void test_parseUnaryExpression_minus_super() { PrefixExpression expression = parseUnaryExpression('-super'); expect(expression, isNotNull); assertNoErrors(); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.MINUS); expect(expression.operand, isNotNull); } void test_parseUnaryExpression_not_normal() { PrefixExpression expression = parseUnaryExpression('!x'); expect(expression, isNotNull); assertNoErrors(); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.BANG); expect(expression.operand, isNotNull); } void test_parseUnaryExpression_not_super() { PrefixExpression expression = parseUnaryExpression('!super'); expect(expression, isNotNull); assertErrors( errors: [error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 1, 5)], ); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.BANG); expect(expression.operand, isNotNull); } void test_parseUnaryExpression_tilda_normal() { PrefixExpression expression = parseUnaryExpression('~x'); expect(expression, isNotNull); assertNoErrors(); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.TILDE); expect(expression.operand, isNotNull); } void test_parseUnaryExpression_tilda_super() { PrefixExpression expression = parseUnaryExpression('~super'); expect(expression, isNotNull); assertNoErrors(); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.TILDE); expect(expression.operand, isNotNull); } void test_parseUnaryExpression_tilde_identifier_index() { var expression = parseExpression('~a[0]') as PrefixExpression; expect(expression, isNotNull); assertNoErrors(); expect(expression.operator, isNotNull); expect(expression.operator.type, TokenType.TILDE); expect(expression.operand, isNotNull); IndexExpression operand = expression.operand as IndexExpression; expect(operand.realTarget, const TypeMatcher()); expect(operand.index is IntegerLiteral, isTrue); } void test_setLiteral() { var set = parseExpression('{3}') as SetOrMapLiteral; expect(set.constKeyword, isNull); expect(set.typeArguments, isNull); expect(set.elements, hasLength(1)); var value = set.elements[0] as IntegerLiteral; expect(value.value, 3); } void test_setLiteral_const() { var set = parseExpression('const {3, 6}') as SetOrMapLiteral; expect(set.constKeyword, isNotNull); expect(set.typeArguments, isNull); expect(set.elements, hasLength(2)); var value1 = set.elements[0] as IntegerLiteral; expect(value1.value, 3); var value2 = set.elements[1] as IntegerLiteral; expect(value2.value, 6); } void test_setLiteral_const_typed() { var set = parseExpression('const {3}') as SetOrMapLiteral; expect(set.constKeyword, isNotNull); expect(set.typeArguments!.arguments, hasLength(1)); var typeArg = set.typeArguments!.arguments[0] as NamedType; expect(typeArg.name.lexeme, 'int'); expect(set.elements.length, 1); var value = set.elements[0] as IntegerLiteral; expect(value.value, 3); } void test_setLiteral_nested_typeArgument() { var set = parseExpression('>{{3}}') as SetOrMapLiteral; expect(set.constKeyword, isNull); expect(set.typeArguments!.arguments, hasLength(1)); var typeArg1 = set.typeArguments!.arguments[0] as NamedType; expect(typeArg1.name.lexeme, 'Set'); expect(typeArg1.typeArguments!.arguments, hasLength(1)); var typeArg2 = typeArg1.typeArguments!.arguments[0] as NamedType; expect(typeArg2.name.lexeme, 'int'); expect(set.elements.length, 1); var intSet = set.elements[0] as SetOrMapLiteral; expect(intSet.elements, hasLength(1)); var value = intSet.elements[0] as IntegerLiteral; expect(value.value, 3); } void test_setLiteral_typed() { var set = parseExpression('{3}') as SetOrMapLiteral; expect(set.constKeyword, isNull); expect(set.typeArguments!.arguments, hasLength(1)); var typeArg = set.typeArguments!.arguments[0] as NamedType; expect(typeArg.name.lexeme, 'int'); expect(set.elements.length, 1); var value = set.elements[0] as IntegerLiteral; expect(value.value, 3); } }