ac9de46499
Change-Id: Ibe2655ed43af3cab632d6e4506f2366c1bfbbc27 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/234803 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Samuel Rawlins <srawlins@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
2549 lines
97 KiB
Dart
2549 lines
97 KiB
Dart
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import 'package:_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 fasta parser based on [ExpressionParserTestMixin].
|
|
@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('<b?c>()', 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('[<y.<z>(){}]', 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('<int, int, int>{}', 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('<int, int, int>{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<Expression> 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_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)<F>(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<E>(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]<E>(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<E>(b).c<F>(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<E>()');
|
|
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<E>(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<E>(b)<F>(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<E>(b)<F>(c).d<G>(e)<H>(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<E>(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 <A> []');
|
|
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 <A, B> {}');
|
|
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 <A, B {}',
|
|
errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1)]);
|
|
expect(expression, isNotNull);
|
|
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_untyped() {
|
|
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, isNull);
|
|
}
|
|
|
|
void test_parseConstructorInitializer_functionExpression() {
|
|
// https://github.com/dart-lang/sdk/issues/37414
|
|
parseCompilationUnit('class C { C.n() : this()(); }', errors: [
|
|
expectedError(ParserErrorCode.INVALID_INITIALIZER, 18, 8),
|
|
]);
|
|
}
|
|
|
|
void test_parseEqualityExpression_normal() {
|
|
BinaryExpression expression = parseEqualityExpression('x == y');
|
|
expect(expression, isNotNull);
|
|
assertNoErrors();
|
|
expect(expression.leftOperand, isNotNull);
|
|
expect(expression.operator, isNotNull);
|
|
expect(expression.operator.type, TokenType.EQ_EQ);
|
|
expect(expression.rightOperand, isNotNull);
|
|
}
|
|
|
|
void test_parseEqualityExpression_super() {
|
|
BinaryExpression expression = parseEqualityExpression('super == y');
|
|
expect(expression, isNotNull);
|
|
assertNoErrors();
|
|
expect(expression.leftOperand, isSuperExpression);
|
|
expect(expression.operator, isNotNull);
|
|
expect(expression.operator.type, TokenType.EQ_EQ);
|
|
expect(expression.rightOperand, isNotNull);
|
|
}
|
|
|
|
void test_parseExpression_assign() {
|
|
// TODO(brianwilkerson) Implement more tests for this method.
|
|
Expression expression = parseExpression('x = y');
|
|
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_parseExpression_assign_compound() {
|
|
if (AbstractScanner.LAZY_ASSIGNMENT_ENABLED) {
|
|
Expression expression = parseExpression('x ||= y');
|
|
var assignmentExpression = expression as AssignmentExpression;
|
|
expect(assignmentExpression.leftHandSide, isNotNull);
|
|
expect(assignmentExpression.operator, isNotNull);
|
|
expect(assignmentExpression.operator.type, TokenType.BAR_BAR_EQ);
|
|
expect(assignmentExpression.rightHandSide, isNotNull);
|
|
}
|
|
}
|
|
|
|
void test_parseExpression_comparison() {
|
|
Expression expression = parseExpression('--a.b == c');
|
|
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_parseExpression_constAndTypeParameters() {
|
|
Expression expression = parseExpression('const <E>', 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() {
|
|
final unit = parseCompilationUnit('main() { factories[C]<num, int>(); }');
|
|
expect(unit.declarations, hasLength(1));
|
|
var mainMethod = unit.declarations[0] as FunctionDeclaration;
|
|
var body = mainMethod.functionExpression.body as BlockFunctionBody;
|
|
NodeList<Statement> 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<TypeAnnotation> typeArguments = expression.typeArguments!.arguments;
|
|
expect(typeArguments, hasLength(2));
|
|
expect((typeArguments[0] as NamedType).name.name, 'num');
|
|
expect((typeArguments[1] as NamedType).name.name, 'int');
|
|
|
|
expect(expression.argumentList.arguments, hasLength(0));
|
|
}
|
|
|
|
void test_parseExpression_sendWithTypeParam_afterSend() {
|
|
final unit = parseCompilationUnit('main() { factories(C)<num, int>(); }');
|
|
expect(unit.declarations, hasLength(1));
|
|
var mainMethod = unit.declarations[0] as FunctionDeclaration;
|
|
var body = mainMethod.functionExpression.body as BlockFunctionBody;
|
|
NodeList<Statement> 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<Expression> invocationArguments =
|
|
invocation.argumentList.arguments;
|
|
expect(invocationArguments, hasLength(1));
|
|
var index = invocationArguments[0] as SimpleIdentifier;
|
|
expect(index.name, 'C');
|
|
|
|
List<TypeAnnotation> typeArguments = expression.typeArguments!.arguments;
|
|
expect(typeArguments, hasLength(2));
|
|
expect((typeArguments[0] as NamedType).name.name, 'num');
|
|
expect((typeArguments[1] as NamedType).name.name, '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<E>()');
|
|
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<D>()');
|
|
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<Expression> result = parseExpressionList('1, 2, 3');
|
|
expect(result, isNotNull);
|
|
assertNoErrors();
|
|
expect(result, hasLength(3));
|
|
}
|
|
|
|
void test_parseExpressionList_single() {
|
|
List<Expression> 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<E>()');
|
|
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>(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('<test(' ', (){});>[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>(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.name.name, 'A.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<E>.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<E>()', 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<B>.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<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<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_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, '<int>', '[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, '<int> [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, "<String, int> {'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, '<String, int>', '{}');
|
|
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<E>()');
|
|
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<E>()');
|
|
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('<X, Y>(Map<X, Y> 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('<A>[ ]');
|
|
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('<A, B>{}');
|
|
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.name, '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<D>');
|
|
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.name, '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<StringLiteral> 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<InterpolationElement> 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"'<html>$void</html>'");
|
|
expect(expression, isNotNull);
|
|
assertErrors(errors: [
|
|
expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 8, 4)
|
|
]);
|
|
expect(expression, isStringInterpolation);
|
|
var literal = expression as StringInterpolation;
|
|
NodeList<InterpolationElement> 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<Token> 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<Token> 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<Token> 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<Token> 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<Token> 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<SimpleIdentifier>());
|
|
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:<MINUS>
|
|
// Actual: TokenType:<MINUS_MINUS>
|
|
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:<MINUS>
|
|
// Actual: TokenType:<MINUS_MINUS>
|
|
|
|
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<SimpleIdentifier>());
|
|
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<SimpleIdentifier>());
|
|
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);
|
|
assertNoErrors();
|
|
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<SimpleIdentifier>());
|
|
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 <int>{3}') as SetOrMapLiteral;
|
|
expect(set.constKeyword, isNotNull);
|
|
expect(set.typeArguments!.arguments, hasLength(1));
|
|
var typeArg = set.typeArguments!.arguments[0] as NamedType;
|
|
expect(typeArg.name.name, '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('<Set<int>>{{3}}') as SetOrMapLiteral;
|
|
expect(set.constKeyword, isNull);
|
|
expect(set.typeArguments!.arguments, hasLength(1));
|
|
var typeArg1 = set.typeArguments!.arguments[0] as NamedType;
|
|
expect(typeArg1.name.name, 'Set');
|
|
expect(typeArg1.typeArguments!.arguments, hasLength(1));
|
|
var typeArg2 = typeArg1.typeArguments!.arguments[0] as NamedType;
|
|
expect(typeArg2.name.name, '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('<int>{3}') as SetOrMapLiteral;
|
|
expect(set.constKeyword, isNull);
|
|
expect(set.typeArguments!.arguments, hasLength(1));
|
|
var typeArg = set.typeArguments!.arguments[0] as NamedType;
|
|
expect(typeArg.name.name, 'int');
|
|
expect(set.elements.length, 1);
|
|
var value = set.elements[0] as IntegerLiteral;
|
|
expect(value.value, 3);
|
|
}
|
|
}
|