| // 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 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 '../util/feature_sets.dart'; |
| import 'parser_test_base.dart'; |
| import 'test_support.dart'; |
| |
| main() { |
| defineReflectiveSuite(() { |
| defineReflectiveTests(NNBDParserTest); |
| }); |
| } |
| |
| @reflectiveTest |
| class NNBDParserTest extends FastaParserTestCase { |
| @override |
| CompilationUnitImpl 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; |
| var identifier = functionExpression.operand as SimpleIdentifier; |
| expect(identifier.name, 'f1'); |
| expect(functionExpression.operator.lexeme, '!'); |
| |
| expect(expression.typeArguments, null); |
| |
| expect(expression.argumentList.arguments.length, 1); |
| var argument = expression.argumentList.arguments.single as IntegerLiteral; |
| 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; |
| var identifier = functionExpression.operand as SimpleIdentifier; |
| expect(identifier.name, 'f2'); |
| expect(functionExpression.operator.lexeme, '!'); |
| |
| expect(expression.typeArguments!.arguments.length, 1); |
| var typeArgument = expression.typeArguments!.arguments.single as NamedType; |
| expect(typeArgument.name.name, "int"); |
| |
| expect(expression.argumentList.arguments.length, 1); |
| var argument = expression.argumentList.arguments.single as IntegerLiteral; |
| expect(argument.value, 42); |
| } |
| |
| void test_bangQuestionIndex() { |
| // http://dartbug.com/41177 |
| CompilationUnit unit = parseCompilationUnit('f(dynamic a) { a!?[0]; }'); |
| 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 index = expression.index as IntegerLiteral; |
| expect(index.value, 0); |
| |
| var question = expression.question!; |
| expect(question, isNotNull); |
| expect(question.lexeme, "?"); |
| |
| var target = expression.target as PostfixExpression; |
| var identifier = target.operand as SimpleIdentifier; |
| expect(identifier.name, 'a'); |
| expect(target.operator.lexeme, '!'); |
| } |
| |
| void test_binary_expression_statement() { |
| final unit = parseCompilationUnit('D? foo(X? x) { X ?? x2; }'); |
| 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 BinaryExpression; |
| var lhs = expression.leftOperand as SimpleIdentifier; |
| expect(lhs.name, 'X'); |
| expect(expression.operator.lexeme, '??'); |
| var rhs = expression.rightOperand as SimpleIdentifier; |
| expect(rhs.name, 'x2'); |
| } |
| |
| void test_cascade_withNullCheck_indexExpression() { |
| var unit = parseCompilationUnit('main() { a?..[27]; }'); |
| var funct = unit.declarations[0] as FunctionDeclaration; |
| var body = funct.functionExpression.body as BlockFunctionBody; |
| var statement = body.block.statements[0] as ExpressionStatement; |
| var cascade = statement.expression as CascadeExpression; |
| var indexExpression = cascade.cascadeSections[0] as IndexExpression; |
| 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(); }'); |
| var funct = unit.declarations[0] as FunctionDeclaration; |
| var body = funct.functionExpression.body as BlockFunctionBody; |
| var statement = body.block.statements[0] as ExpressionStatement; |
| var cascade = statement.expression as CascadeExpression; |
| var invocation = cascade.cascadeSections[0] as MethodInvocation; |
| expect(invocation.operator!.lexeme, '?..'); |
| expect(invocation.toSource(), '?..foo()'); |
| } |
| |
| void test_cascade_withNullCheck_propertyAccess() { |
| var unit = parseCompilationUnit('main() { a?..x27; }'); |
| var funct = unit.declarations[0] as FunctionDeclaration; |
| var body = funct.functionExpression.body as BlockFunctionBody; |
| var statement = body.block.statements[0] as ExpressionStatement; |
| var cascade = statement.expression as CascadeExpression; |
| var propertyAccess = cascade.cascadeSections[0] as PropertyAccess; |
| 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: FeatureSets.language_2_9); |
| } |
| |
| 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: FeatureSets.language_2_9); |
| } |
| |
| 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.EXPECTED_TOKEN, 6, 4), |
| expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1), |
| expectedError(ParserErrorCode.MISSING_IDENTIFIER, 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]; }'); |
| var method = unit.declarations[0] as FunctionDeclaration; |
| var body = method.functionExpression.body as BlockFunctionBody; |
| var statement = body.block.statements[0] as ExpressionStatement; |
| var expression = statement.expression as IndexExpression; |
| expect(expression.leftBracket.lexeme, '['); |
| } |
| |
| void test_indexed_nullAware() { |
| CompilationUnit unit = parseCompilationUnit('main() { a?[7]; }'); |
| var method = unit.declarations[0] as FunctionDeclaration; |
| var body = method.functionExpression.body as BlockFunctionBody; |
| var statement = body.block.statements[0] as ExpressionStatement; |
| var expression = statement.expression as IndexExpression; |
| 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)]); |
| var method = unit.declarations[0] as FunctionDeclaration; |
| var body = method.functionExpression.body as BlockFunctionBody; |
| var statement = body.block.statements[0] as ExpressionStatement; |
| var expression = statement.expression as IndexExpressionImpl; |
| 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: FeatureSets.language_2_9); |
| } |
| |
| void test_is_nullable() { |
| CompilationUnit unit = |
| parseCompilationUnit('main() { x is String? ? (x + y) : z; }'); |
| var function = unit.declarations[0] as FunctionDeclaration; |
| var body = function.functionExpression.body as BlockFunctionBody; |
| var statement = body.block.statements[0] as ExpressionStatement; |
| var expression = statement.expression as ConditionalExpression; |
| |
| var condition = expression.condition as IsExpression; |
| 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; }'); |
| var function = unit.declarations[0] as FunctionDeclaration; |
| var body = function.functionExpression.body as BlockFunctionBody; |
| var statement = body.block.statements[0] as ExpressionStatement; |
| var expression = statement.expression as ConditionalExpression; |
| |
| var condition = expression.condition as ParenthesizedExpression; |
| var isExpression = condition.expression as IsExpression; |
| 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: FeatureSets.language_2_9); |
| } |
| |
| 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; |
| } |
| '''); |
| var classDeclaration = unit.declarations.first as ClassDeclaration; |
| var constructor = |
| classDeclaration.getConstructor(null) as ConstructorDeclaration; |
| |
| // Object? o |
| var parameter = |
| constructor.parameters.parameters.single as SimpleFormalParameter; |
| expect(parameter.identifier!.name, 'o'); |
| var type = parameter.type as NamedType; |
| expect(type.question!.lexeme, '?'); |
| expect(type.name.name, 'Object'); |
| |
| expect(constructor.initializers.length, 2); |
| |
| // o as String? |
| { |
| var initializer = |
| constructor.initializers[0] as ConstructorFieldInitializer; |
| expect(initializer.fieldName.name, 'x'); |
| var expression = initializer.expression as AsExpression; |
| var identifier = expression.expression as SimpleIdentifier; |
| expect(identifier.name, 'o'); |
| var expressionType = expression.type as NamedType; |
| expect(expressionType.question!.lexeme, '?'); |
| expect(expressionType.name.name, 'String'); |
| } |
| |
| // y = 0 |
| { |
| var initializer = |
| constructor.initializers[1] as ConstructorFieldInitializer; |
| expect(initializer.fieldName.name, 'y'); |
| var expression = initializer.expression as IntegerLiteral; |
| 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; |
| } |
| '''); |
| var classDeclaration = unit.declarations.first as ClassDeclaration; |
| var constructor = |
| classDeclaration.getConstructor(null) as ConstructorDeclaration; |
| |
| // Object? o |
| var parameter = |
| constructor.parameters.parameters.single as SimpleFormalParameter; |
| expect(parameter.identifier!.name, 'o'); |
| var type = parameter.type as NamedType; |
| expect(type.question!.lexeme, '?'); |
| expect(type.name.name, 'Object'); |
| |
| expect(constructor.initializers.length, 2); |
| |
| // y = o is String? ? o.length : null |
| { |
| var initializer = |
| constructor.initializers[0] as ConstructorFieldInitializer; |
| expect(initializer.fieldName.name, 'y'); |
| var expression = initializer.expression as ConditionalExpression; |
| var condition = expression.condition as IsExpression; |
| var identifier = condition.expression as SimpleIdentifier; |
| expect(identifier.name, 'o'); |
| var expressionType = condition.type as NamedType; |
| expect(expressionType.question!.lexeme, '?'); |
| expect(expressionType.name.name, 'String'); |
| var thenExpression = expression.thenExpression as PrefixedIdentifier; |
| expect(thenExpression.identifier.name, 'length'); |
| expect(thenExpression.prefix.name, 'o'); |
| var elseExpression = expression.elseExpression as NullLiteral; |
| expect(elseExpression, isNotNull); |
| } |
| |
| // x = null |
| { |
| var initializer = |
| constructor.initializers[1] as ConstructorFieldInitializer; |
| expect(initializer.fieldName.name, 'x'); |
| var expression = initializer.expression as NullLiteral; |
| 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; |
| } |
| '''); |
| var classDeclaration = unit.declarations.first as ClassDeclaration; |
| var constructor = |
| classDeclaration.getConstructor(null) as ConstructorDeclaration; |
| |
| // Object? o |
| var parameter = |
| constructor.parameters.parameters.single as SimpleFormalParameter; |
| expect(parameter.identifier!.name, 'o'); |
| var type = parameter.type as NamedType; |
| expect(type.question!.lexeme, '?'); |
| expect(type.name.name, 'Object'); |
| |
| expect(constructor.initializers.length, 2); |
| |
| // y = o is String ? o.length : null |
| { |
| var initializer = |
| constructor.initializers[0] as ConstructorFieldInitializer; |
| expect(initializer.fieldName.name, 'y'); |
| var expression = initializer.expression as ConditionalExpression; |
| var condition = expression.condition as IsExpression; |
| var identifier = condition.expression as SimpleIdentifier; |
| expect(identifier.name, 'o'); |
| var expressionType = condition.type as NamedType; |
| expect(expressionType.question, isNull); |
| expect(expressionType.name.name, 'String'); |
| var thenExpression = expression.thenExpression as PrefixedIdentifier; |
| expect(thenExpression.identifier.name, 'length'); |
| expect(thenExpression.prefix.name, 'o'); |
| var elseExpression = expression.elseExpression as NullLiteral; |
| expect(elseExpression, isNotNull); |
| } |
| |
| // x = null |
| { |
| var initializer = |
| constructor.initializers[1] as ConstructorFieldInitializer; |
| expect(initializer.fieldName.name, 'x'); |
| var expression = initializer.expression as NullLiteral; |
| expect(expression, isNotNull); |
| } |
| } |
| |
| void test_nullCheck() { |
| var unit = parseCompilationUnit('f(int? y) { var x = y!; }'); |
| var function = unit.declarations[0] as FunctionDeclaration; |
| var body = function.functionExpression.body as BlockFunctionBody; |
| var statement = body.block.statements[0] as VariableDeclarationStatement; |
| var expression = |
| statement.variables.variables[0].initializer as PostfixExpression; |
| var identifier = expression.operand as SimpleIdentifier; |
| 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: FeatureSets.language_2_9); |
| var function = unit.declarations[0] as FunctionDeclaration; |
| var body = function.functionExpression.body as BlockFunctionBody; |
| var statement = body.block.statements[0] as VariableDeclarationStatement; |
| var identifier = |
| statement.variables.variables[0].initializer as SimpleIdentifier; |
| 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: FeatureSets.language_2_9); |
| } |
| |
| 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: FeatureSets.language_2_9); |
| } |
| |
| 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: FeatureSets.language_2_9); |
| } |
| |
| 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: FeatureSets.language_2_9); |
| } |
| } |