blob: 6fd7547d9abcb87e69f17ded85191fffe484db3f [file] [log] [blame]
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../util/ast_type_matchers.dart';
import 'parser_test_base.dart';
import 'test_support.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(NNBDParserTest);
});
}
@reflectiveTest
class NNBDParserTest extends FastaParserTestCase {
@override
CompilationUnit parseCompilationUnit(String content,
{List<ErrorCode> codes,
List<ExpectedError> errors,
FeatureSet featureSet}) =>
super.parseCompilationUnit(content,
codes: codes,
errors: errors,
featureSet: featureSet ?? FeatureSet.latestLanguageVersion());
void test_assignment_complex() {
parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x + bar(7); }');
}
void test_assignment_complex2() {
parseCompilationUnit(r'''
main() {
A? a;
String? s = '';
a?..foo().length..x27 = s!..toString().length;
}
''');
}
void test_assignment_simple() {
parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x; }');
}
void test_bangBeforeFuctionCall1() {
// https://github.com/dart-lang/sdk/issues/39776
var unit = parseCompilationUnit('f() { Function? f1; f1!(42); }');
var funct = unit.declarations[0] as FunctionDeclaration;
var body = funct.functionExpression.body as BlockFunctionBody;
var statement1 = body.block.statements[0] as VariableDeclarationStatement;
expect(statement1.toSource(), "Function? f1;");
var statement2 = body.block.statements[1] as ExpressionStatement;
// expression is "f1!(42)"
var expression = statement2.expression as FunctionExpressionInvocation;
expect(expression.toSource(), "f1!(42)");
var functionExpression = expression.function as PostfixExpression;
SimpleIdentifier identifier = functionExpression.operand;
expect(identifier.name, 'f1');
expect(functionExpression.operator.lexeme, '!');
expect(expression.typeArguments, null);
expect(expression.argumentList.arguments.length, 1);
IntegerLiteral argument = expression.argumentList.arguments.single;
expect(argument.value, 42);
}
void test_bangBeforeFuctionCall2() {
// https://github.com/dart-lang/sdk/issues/39776
var unit = parseCompilationUnit('f() { Function f2; f2!<int>(42); }');
var funct = unit.declarations[0] as FunctionDeclaration;
var body = funct.functionExpression.body as BlockFunctionBody;
var statement1 = body.block.statements[0] as VariableDeclarationStatement;
expect(statement1.toSource(), "Function f2;");
var statement2 = body.block.statements[1] as ExpressionStatement;
// expression is "f2!<int>(42)"
var expression = statement2.expression as FunctionExpressionInvocation;
expect(expression.toSource(), "f2!<int>(42)");
var functionExpression = expression.function as PostfixExpression;
SimpleIdentifier identifier = functionExpression.operand;
expect(identifier.name, 'f2');
expect(functionExpression.operator.lexeme, '!');
expect(expression.typeArguments.arguments.length, 1);
TypeName typeArgument = expression.typeArguments.arguments.single;
expect(typeArgument.name.name, "int");
expect(expression.argumentList.arguments.length, 1);
IntegerLiteral argument = expression.argumentList.arguments.single;
expect(argument.value, 42);
}
void test_bangQuestionIndex() {
// http://dartbug.com/41177
CompilationUnit unit = parseCompilationUnit('f(dynamic a) { a!?[0]; }');
FunctionDeclaration funct = unit.declarations[0];
BlockFunctionBody body = funct.functionExpression.body;
ExpressionStatement statement = body.block.statements[0];
IndexExpression expression = statement.expression;
IntegerLiteral index = expression.index;
expect(index.value, 0);
Token question = expression.question;
expect(question, isNotNull);
expect(question.lexeme, "?");
PostfixExpression target = expression.target;
SimpleIdentifier identifier = target.operand;
expect(identifier.name, 'a');
expect(target.operator.lexeme, '!');
}
void test_binary_expression_statement() {
final unit = parseCompilationUnit('D? foo(X? x) { X ?? x2; }');
FunctionDeclaration funct = unit.declarations[0];
BlockFunctionBody body = funct.functionExpression.body;
ExpressionStatement statement = body.block.statements[0];
BinaryExpression expression = statement.expression;
SimpleIdentifier lhs = expression.leftOperand;
expect(lhs.name, 'X');
expect(expression.operator.lexeme, '??');
SimpleIdentifier rhs = expression.rightOperand;
expect(rhs.name, 'x2');
}
void test_cascade_withNullCheck_indexExpression() {
var unit = parseCompilationUnit('main() { a?..[27]; }');
FunctionDeclaration funct = unit.declarations[0];
BlockFunctionBody body = funct.functionExpression.body;
ExpressionStatement statement = body.block.statements[0];
CascadeExpression cascade = statement.expression;
IndexExpression indexExpression = cascade.cascadeSections[0];
expect(indexExpression.period.lexeme, '?..');
expect(indexExpression.toSource(), '?..[27]');
}
void test_cascade_withNullCheck_invalid() {
parseCompilationUnit('main() { a..[27]?..x; }', errors: [
expectedError(ParserErrorCode.NULL_AWARE_CASCADE_OUT_OF_ORDER, 16, 3),
]);
}
void test_cascade_withNullCheck_methodInvocation() {
var unit = parseCompilationUnit('main() { a?..foo(); }');
FunctionDeclaration funct = unit.declarations[0];
BlockFunctionBody body = funct.functionExpression.body;
ExpressionStatement statement = body.block.statements[0];
CascadeExpression cascade = statement.expression;
MethodInvocation invocation = cascade.cascadeSections[0];
expect(invocation.operator.lexeme, '?..');
expect(invocation.toSource(), '?..foo()');
}
void test_cascade_withNullCheck_propertyAccess() {
var unit = parseCompilationUnit('main() { a?..x27; }');
FunctionDeclaration funct = unit.declarations[0];
BlockFunctionBody body = funct.functionExpression.body;
ExpressionStatement statement = body.block.statements[0];
CascadeExpression cascade = statement.expression;
PropertyAccess propertyAccess = cascade.cascadeSections[0];
expect(propertyAccess.operator.lexeme, '?..');
expect(propertyAccess.toSource(), '?..x27');
}
void test_conditional() {
parseCompilationUnit('D? foo(X? x) { X ? 7 : y; }');
}
void test_conditional_complex() {
parseCompilationUnit('D? foo(X? x) { X ? x2 = x + bar(7) : y; }');
}
void test_conditional_error() {
parseCompilationUnit('D? foo(X? x) { X ? ? x2 = x + bar(7) : y; }',
errors: [
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 19, 1),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 40, 1),
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 40, 1),
]);
}
void test_conditional_simple() {
parseCompilationUnit('D? foo(X? x) { X ? x2 = x : y; }');
}
void test_enableNonNullable_false() {
parseCompilationUnit('main() { x is String? ? (x + y) : z; }',
errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 20, 1)],
featureSet: preNonNullable);
}
void test_for() {
parseCompilationUnit('main() { for(int x = 0; x < 7; ++x) { } }');
}
void test_for_conditional() {
parseCompilationUnit('main() { for(x ? y = 7 : y = 8; y < 10; ++y) { } }');
}
void test_for_nullable() {
parseCompilationUnit('main() { for(int? x = 0; x < 7; ++x) { } }');
}
void test_foreach() {
parseCompilationUnit('main() { for(int x in [7]) { } }');
}
void test_foreach_nullable() {
parseCompilationUnit('main() { for(int? x in [7, null]) { } }');
}
void test_functionTypedFormalParameter_nullable_disabled() {
parseCompilationUnit('void f(void p()?) {}',
errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 15, 1)],
featureSet: preNonNullable);
}
test_fuzz_38113() async {
// https://github.com/dart-lang/sdk/issues/38113
parseCompilationUnit(r'+t{{r?this}}', errors: [
expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 1, 1),
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 4),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
]);
}
void test_gft_nullable() {
parseCompilationUnit('main() { C? Function() x = 7; }');
}
void test_gft_nullable_1() {
parseCompilationUnit('main() { C Function()? x = 7; }');
}
void test_gft_nullable_2() {
parseCompilationUnit('main() { C? Function()? x = 7; }');
}
void test_gft_nullable_3() {
parseCompilationUnit('main() { C? Function()? Function()? x = 7; }');
}
void test_gft_nullable_prefixed() {
parseCompilationUnit('main() { C.a? Function()? x = 7; }');
}
void test_indexed() {
CompilationUnit unit = parseCompilationUnit('main() { a[7]; }');
FunctionDeclaration method = unit.declarations[0];
BlockFunctionBody body = method.functionExpression.body;
ExpressionStatement statement = body.block.statements[0];
IndexExpression expression = statement.expression;
expect(expression.leftBracket.lexeme, '[');
}
void test_indexed_nullAware() {
CompilationUnit unit = parseCompilationUnit('main() { a?[7]; }');
FunctionDeclaration method = unit.declarations[0];
BlockFunctionBody body = method.functionExpression.body;
ExpressionStatement statement = body.block.statements[0];
IndexExpression expression = statement.expression;
expect(expression.question, isNotNull);
expect(expression.leftBracket.lexeme, '[');
expect(expression.rightBracket.lexeme, ']');
expect(expression.leftBracket.endGroup, expression.rightBracket);
}
void test_indexed_nullAware_optOut() {
CompilationUnit unit = parseCompilationUnit('''
// @dart = 2.2
main() { a?[7]; }''',
errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 25, 1)]);
FunctionDeclaration method = unit.declarations[0];
BlockFunctionBody body = method.functionExpression.body;
ExpressionStatement statement = body.block.statements[0];
IndexExpressionImpl expression = statement.expression;
expect(expression.target.toSource(), 'a');
expect(expression.question, isNotNull);
expect(expression.leftBracket.lexeme, '[');
expect(expression.rightBracket.lexeme, ']');
expect(expression.leftBracket.endGroup, expression.rightBracket);
}
void test_indexExpression_nullable_disabled() {
parseCompilationUnit('main(a) { a?[0]; }',
errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 11, 1)],
featureSet: preNonNullable);
}
void test_is_nullable() {
CompilationUnit unit =
parseCompilationUnit('main() { x is String? ? (x + y) : z; }');
FunctionDeclaration function = unit.declarations[0];
BlockFunctionBody body = function.functionExpression.body;
ExpressionStatement statement = body.block.statements[0];
ConditionalExpression expression = statement.expression;
IsExpression condition = expression.condition;
expect((condition.type as NamedType).question, isNotNull);
Expression thenExpression = expression.thenExpression;
expect(thenExpression, isParenthesizedExpression);
Expression elseExpression = expression.elseExpression;
expect(elseExpression, isSimpleIdentifier);
}
void test_is_nullable_parenthesis() {
CompilationUnit unit =
parseCompilationUnit('main() { (x is String?) ? (x + y) : z; }');
FunctionDeclaration function = unit.declarations[0];
BlockFunctionBody body = function.functionExpression.body;
ExpressionStatement statement = body.block.statements[0];
ConditionalExpression expression = statement.expression;
ParenthesizedExpression condition = expression.condition;
IsExpression isExpression = condition.expression;
expect((isExpression.type as NamedType).question, isNotNull);
Expression thenExpression = expression.thenExpression;
expect(thenExpression, isParenthesizedExpression);
Expression elseExpression = expression.elseExpression;
expect(elseExpression, isSimpleIdentifier);
}
void test_is_nullable_parenthesis_optOut() {
parseCompilationUnit('''
// @dart = 2.2
main() { (x is String?) ? (x + y) : z; }
''', errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 36, 1)]);
}
void test_late_as_identifier() {
parseCompilationUnit('''
class C {
int late;
}
void f(C c) {
print(c.late);
}
main() {
f(new C());
}
''', featureSet: preNonNullable);
}
void test_late_as_identifier_optOut() {
parseCompilationUnit('''
// @dart = 2.2
class C {
int late;
}
void f(C c) {
print(c.late);
}
main() {
f(new C());
}
''');
}
void test_nullableTypeInInitializerList_01() {
// http://dartbug.com/40834
var unit = parseCompilationUnit(r'''
class Foo {
String? x;
int y;
Foo(Object? o) : x = o as String?, y = 0;
}
''');
ClassDeclaration classDeclaration = unit.declarations.first;
ConstructorDeclaration constructor = classDeclaration.getConstructor(null);
// Object? o
SimpleFormalParameter parameter = constructor.parameters.parameters.single;
expect(parameter.identifier.name, 'o');
TypeName type = parameter.type;
expect(type.question.lexeme, '?');
expect(type.name.name, 'Object');
expect(constructor.initializers.length, 2);
// o as String?
{
ConstructorFieldInitializer initializer = constructor.initializers[0];
expect(initializer.fieldName.name, 'x');
AsExpression expression = initializer.expression;
SimpleIdentifier identifier = expression.expression;
expect(identifier.name, 'o');
TypeName expressionType = expression.type;
expect(expressionType.question.lexeme, '?');
expect(expressionType.name.name, 'String');
}
// y = 0
{
ConstructorFieldInitializer initializer = constructor.initializers[1];
expect(initializer.fieldName.name, 'y');
IntegerLiteral expression = initializer.expression;
expect(expression.value, 0);
}
}
void test_nullableTypeInInitializerList_02() {
var unit = parseCompilationUnit(r'''
class Foo {
String? x;
int y;
Foo(Object? o) : y = o is String? ? o.length : null, x = null;
}
''');
ClassDeclaration classDeclaration = unit.declarations.first;
ConstructorDeclaration constructor = classDeclaration.getConstructor(null);
// Object? o
SimpleFormalParameter parameter = constructor.parameters.parameters.single;
expect(parameter.identifier.name, 'o');
TypeName type = parameter.type;
expect(type.question.lexeme, '?');
expect(type.name.name, 'Object');
expect(constructor.initializers.length, 2);
// y = o is String? ? o.length : null
{
ConstructorFieldInitializer initializer = constructor.initializers[0];
expect(initializer.fieldName.name, 'y');
ConditionalExpression expression = initializer.expression;
IsExpression condition = expression.condition;
SimpleIdentifier identifier = condition.expression;
expect(identifier.name, 'o');
TypeName expressionType = condition.type;
expect(expressionType.question.lexeme, '?');
expect(expressionType.name.name, 'String');
PrefixedIdentifier thenExpression = expression.thenExpression;
expect(thenExpression.identifier.name, 'length');
expect(thenExpression.prefix.name, 'o');
NullLiteral elseExpression = expression.elseExpression;
expect(elseExpression, isNotNull);
}
// x = null
{
ConstructorFieldInitializer initializer = constructor.initializers[1];
expect(initializer.fieldName.name, 'x');
NullLiteral expression = initializer.expression;
expect(expression, isNotNull);
}
}
void test_nullableTypeInInitializerList_03() {
// As test_nullableTypeInInitializerList_02 but without ? on String in is.
var unit = parseCompilationUnit(r'''
class Foo {
String? x;
int y;
Foo(Object? o) : y = o is String ? o.length : null, x = null;
}
''');
ClassDeclaration classDeclaration = unit.declarations.first;
ConstructorDeclaration constructor = classDeclaration.getConstructor(null);
// Object? o
SimpleFormalParameter parameter = constructor.parameters.parameters.single;
expect(parameter.identifier.name, 'o');
TypeName type = parameter.type;
expect(type.question.lexeme, '?');
expect(type.name.name, 'Object');
expect(constructor.initializers.length, 2);
// y = o is String ? o.length : null
{
ConstructorFieldInitializer initializer = constructor.initializers[0];
expect(initializer.fieldName.name, 'y');
ConditionalExpression expression = initializer.expression;
IsExpression condition = expression.condition;
SimpleIdentifier identifier = condition.expression;
expect(identifier.name, 'o');
TypeName expressionType = condition.type;
expect(expressionType.question, isNull);
expect(expressionType.name.name, 'String');
PrefixedIdentifier thenExpression = expression.thenExpression;
expect(thenExpression.identifier.name, 'length');
expect(thenExpression.prefix.name, 'o');
NullLiteral elseExpression = expression.elseExpression;
expect(elseExpression, isNotNull);
}
// x = null
{
ConstructorFieldInitializer initializer = constructor.initializers[1];
expect(initializer.fieldName.name, 'x');
NullLiteral expression = initializer.expression;
expect(expression, isNotNull);
}
}
void test_nullCheck() {
var unit = parseCompilationUnit('f(int? y) { var x = y!; }');
FunctionDeclaration function = unit.declarations[0];
BlockFunctionBody body = function.functionExpression.body;
VariableDeclarationStatement statement = body.block.statements[0];
PostfixExpression expression = statement.variables.variables[0].initializer;
SimpleIdentifier identifier = expression.operand;
expect(identifier.name, 'y');
expect(expression.operator.lexeme, '!');
}
void test_nullCheck_disabled() {
var unit = parseCompilationUnit('f(int? y) { var x = y!; }',
errors: [
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 5, 1),
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 21, 1),
],
featureSet: preNonNullable);
FunctionDeclaration function = unit.declarations[0];
BlockFunctionBody body = function.functionExpression.body;
VariableDeclarationStatement statement = body.block.statements[0];
SimpleIdentifier identifier = statement.variables.variables[0].initializer;
expect(identifier.name, 'y');
}
void test_nullCheckAfterGetterAccess() {
parseCompilationUnit('f() { var x = g.x!.y + 7; }');
}
void test_nullCheckAfterMethodCall() {
parseCompilationUnit('f() { var x = g.m()!.y + 7; }');
}
void test_nullCheckBeforeGetterAccess() {
parseCompilationUnit('f() { var x = g!.x + 7; }');
}
void test_nullCheckBeforeIndex() {
// https://github.com/dart-lang/sdk/issues/37708
var unit = parseCompilationUnit('f() { foo.bar!.baz[arg]; }');
var funct = unit.declarations[0] as FunctionDeclaration;
var body = funct.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var expression = statement.expression as IndexExpression;
expect(expression.index.toSource(), 'arg');
var propertyAccess = expression.target as PropertyAccess;
expect(propertyAccess.propertyName.toSource(), 'baz');
var target = propertyAccess.target as PostfixExpression;
expect(target.operand.toSource(), 'foo.bar');
expect(target.operator.lexeme, '!');
}
void test_nullCheckBeforeMethodCall() {
parseCompilationUnit('f() { var x = g!.m() + 7; }');
}
void test_nullCheckFunctionResult() {
parseCompilationUnit('f() { var x = g()! + 7; }');
}
void test_nullCheckIndexedValue() {
parseCompilationUnit('f(int? y) { var x = y[0]! + 7; }');
}
void test_nullCheckIndexedValue2() {
parseCompilationUnit('f(int? y) { var x = super.y[0]! + 7; }');
}
void test_nullCheckInExpression() {
parseCompilationUnit('f(int? y) { var x = y! + 7; }');
}
void test_nullCheckInExpression_disabled() {
parseCompilationUnit('f(int? y) { var x = y! + 7; }',
errors: [
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 5, 1),
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 21, 1),
],
featureSet: preNonNullable);
}
void test_nullCheckMethodResult() {
parseCompilationUnit('f() { var x = g.m()! + 7; }');
}
void test_nullCheckMethodResult2() {
parseCompilationUnit('f() { var x = g?.m()! + 7; }');
}
void test_nullCheckMethodResult3() {
parseCompilationUnit('f() { var x = super.m()! + 7; }');
}
void test_nullCheckOnConstConstructor() {
parseCompilationUnit('f() { var x = const Foo()!; }');
}
void test_nullCheckOnConstructor() {
parseCompilationUnit('f() { var x = new Foo()!; }');
}
void test_nullCheckOnIndex() {
// https://github.com/dart-lang/sdk/issues/37708
var unit = parseCompilationUnit('f() { obj![arg]; }');
var funct = unit.declarations[0] as FunctionDeclaration;
var body = funct.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var expression = statement.expression as IndexExpression;
var target = expression.target as PostfixExpression;
expect(target.operand.toSource(), 'obj');
expect(target.operator.lexeme, '!');
}
void test_nullCheckOnIndex2() {
// https://github.com/dart-lang/sdk/issues/37708
var unit = parseCompilationUnit('f() { obj![arg]![arg2]; }');
var funct = unit.declarations[0] as FunctionDeclaration;
var body = funct.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var expression = statement.expression as IndexExpression;
expect(expression.index.toSource(), 'arg2');
var target = expression.target as PostfixExpression;
expect(target.operator.lexeme, '!');
expression = target.operand as IndexExpression;
expect(expression.index.toSource(), 'arg');
target = expression.target as PostfixExpression;
expect(target.operator.lexeme, '!');
expect(target.operand.toSource(), 'obj');
}
void test_nullCheckOnIndex3() {
// https://github.com/dart-lang/sdk/issues/37708
var unit = parseCompilationUnit('f() { foo.bar![arg]; }');
var funct = unit.declarations[0] as FunctionDeclaration;
var body = funct.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var expression = statement.expression as IndexExpression;
expect(expression.index.toSource(), 'arg');
var target = expression.target as PostfixExpression;
expect(target.operand.toSource(), 'foo.bar');
expect(target.operator.lexeme, '!');
}
void test_nullCheckOnIndex4() {
// https://github.com/dart-lang/sdk/issues/37708
var unit = parseCompilationUnit('f() { foo!.bar![arg]; }');
var funct = unit.declarations[0] as FunctionDeclaration;
var body = funct.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var expression = statement.expression as IndexExpression;
var fooBarTarget = expression.target as PostfixExpression;
expect(fooBarTarget.toSource(), "foo!.bar!");
var propertyAccess = fooBarTarget.operand as PropertyAccess;
var targetFoo = propertyAccess.target as PostfixExpression;
expect(targetFoo.operand.toSource(), "foo");
expect(targetFoo.operator.lexeme, "!");
expect(propertyAccess.propertyName.toSource(), "bar");
expect(fooBarTarget.operator.lexeme, '!');
expect(expression.index.toSource(), 'arg');
}
void test_nullCheckOnIndex5() {
// https://github.com/dart-lang/sdk/issues/37708
var unit = parseCompilationUnit('f() { foo.bar![arg]![arg2]; }');
var funct = unit.declarations[0] as FunctionDeclaration;
var body = funct.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var expression = statement.expression as IndexExpression;
expect(expression.index.toSource(), 'arg2');
var target = expression.target as PostfixExpression;
expect(target.operator.lexeme, '!');
expression = target.operand as IndexExpression;
expect(expression.index.toSource(), 'arg');
target = expression.target as PostfixExpression;
expect(target.operator.lexeme, '!');
expect(target.operand.toSource(), 'foo.bar');
}
void test_nullCheckOnIndex6() {
// https://github.com/dart-lang/sdk/issues/37708
var unit = parseCompilationUnit('f() { foo!.bar![arg]![arg2]; }');
var funct = unit.declarations[0] as FunctionDeclaration;
var body = funct.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
// expression is "foo!.bar![arg]![arg2]"
var expression = statement.expression as IndexExpression;
expect(expression.index.toSource(), 'arg2');
// target is "foo!.bar![arg]!"
var target = expression.target as PostfixExpression;
expect(target.operator.lexeme, '!');
// expression is "foo!.bar![arg]"
expression = target.operand as IndexExpression;
expect(expression.index.toSource(), 'arg');
// target is "foo!.bar!"
target = expression.target as PostfixExpression;
expect(target.operator.lexeme, '!');
// propertyAccess is "foo!.bar"
PropertyAccess propertyAccess = target.operand as PropertyAccess;
expect(propertyAccess.propertyName.toSource(), "bar");
// target is "foo!"
target = propertyAccess.target as PostfixExpression;
expect(target.operator.lexeme, '!');
expect(target.operand.toSource(), "foo");
}
void test_nullCheckOnLiteral_disabled() {
parseCompilationUnit('f() { var x = 0!; }',
errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 15, 1)],
featureSet: preNonNullable);
}
void test_nullCheckOnLiteralDouble() {
// Issues like this should be caught during later analysis
parseCompilationUnit('f() { var x = 1.2!; }');
}
void test_nullCheckOnLiteralInt() {
// Issues like this should be caught during later analysis
parseCompilationUnit('f() { var x = 0!; }');
}
void test_nullCheckOnLiteralList() {
// Issues like this should be caught during later analysis
parseCompilationUnit('f() { var x = [1,2]!; }');
}
void test_nullCheckOnLiteralMap() {
// Issues like this should be caught during later analysis
parseCompilationUnit('f() { var x = {1:2}!; }');
}
void test_nullCheckOnLiteralSet() {
// Issues like this should be caught during later analysis
parseCompilationUnit('f() { var x = {1,2}!; }');
}
void test_nullCheckOnLiteralString() {
// Issues like this should be caught during later analysis
parseCompilationUnit('f() { var x = "seven"!; }');
}
void test_nullCheckOnNull() {
// Issues like this should be caught during later analysis
parseCompilationUnit('f() { var x = null!; }');
}
void test_nullCheckOnSend() {
// https://github.com/dart-lang/sdk/issues/37708
var unit = parseCompilationUnit('f() { obj!(arg); }');
var funct = unit.declarations[0] as FunctionDeclaration;
var body = funct.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var expression = statement.expression as FunctionExpressionInvocation;
var target = expression.function as PostfixExpression;
expect(target.operand.toSource(), 'obj');
expect(target.operator.lexeme, '!');
}
void test_nullCheckOnSend2() {
// https://github.com/dart-lang/sdk/issues/37708
var unit = parseCompilationUnit('f() { obj!(arg)!(arg2); }');
var funct = unit.declarations[0] as FunctionDeclaration;
var body = funct.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var expression = statement.expression as FunctionExpressionInvocation;
expect(expression.argumentList.toSource(), '(arg2)');
var target = expression.function as PostfixExpression;
expect(target.operator.lexeme, '!');
expression = target.operand as FunctionExpressionInvocation;
expect(expression.argumentList.toSource(), '(arg)');
target = expression.function as PostfixExpression;
expect(target.operator.lexeme, '!');
expect(target.operand.toSource(), 'obj');
}
void test_nullCheckOnSymbol() {
// Issues like this should be caught during later analysis
parseCompilationUnit('f() { var x = #seven!; }');
}
void test_nullCheckOnValue() {
parseCompilationUnit('f(Point p) { var x = p.y! + 7; }');
}
void test_nullCheckOnValue_disabled() {
parseCompilationUnit('f(Point p) { var x = p.y! + 7; }',
errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 24, 1)],
featureSet: preNonNullable);
}
void test_nullCheckParenthesizedExpression() {
parseCompilationUnit('f(int? y) { var x = (y)! + 7; }');
}
void test_nullCheckPropertyAccess() {
parseCompilationUnit('f() { var x = g.p! + 7; }');
}
void test_nullCheckPropertyAccess2() {
parseCompilationUnit('f() { var x = g?.p! + 7; }');
}
void test_nullCheckPropertyAccess3() {
parseCompilationUnit('f() { var x = super.p! + 7; }');
}
void test_postfix_null_assertion_and_unary_prefix_operator_precedence() {
// -x! is parsed as -(x!).
var unit = parseCompilationUnit('void main() { -x!; }');
var function = unit.declarations[0] as FunctionDeclaration;
var body = function.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var outerExpression = statement.expression as PrefixExpression;
expect(outerExpression.operator.type, TokenType.MINUS);
var innerExpression = outerExpression.operand as PostfixExpression;
expect(innerExpression.operator.type, TokenType.BANG);
}
void test_postfix_null_assertion_of_postfix_expression() {
// x++! is parsed as (x++)!.
var unit = parseCompilationUnit('void main() { x++!; }');
var function = unit.declarations[0] as FunctionDeclaration;
var body = function.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var outerExpression = statement.expression as PostfixExpression;
expect(outerExpression.operator.type, TokenType.BANG);
var innerExpression = outerExpression.operand as PostfixExpression;
expect(innerExpression.operator.type, TokenType.PLUS_PLUS);
}
void test_typeName_nullable_disabled() {
parseCompilationUnit('int? x;',
errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 3, 1)],
featureSet: preNonNullable);
}
}