| Index: pkg/analyzer/test/src/task/strong/non_null_checker_test.dart
|
| diff --git a/pkg/analyzer/test/src/task/strong/non_null_checker_test.dart b/pkg/analyzer/test/src/task/strong/non_null_checker_test.dart
|
| index e5fa7c662a856384501a5d0512af768d75f9e3b5..b61deaacc0f77b5b2e986514e006dcc68d6d8b28 100644
|
| --- a/pkg/analyzer/test/src/task/strong/non_null_checker_test.dart
|
| +++ b/pkg/analyzer/test/src/task/strong/non_null_checker_test.dart
|
| @@ -9,12 +9,17 @@
|
|
|
| library analyzer.test.src.task.non_null_primitives.checker_test;
|
|
|
| -import '../../../reflective_tests.dart';
|
| +import 'package:test_reflective_loader/test_reflective_loader.dart';
|
| +
|
| import '../strong/strong_test_helper.dart';
|
|
|
| void main() {
|
| initStrongModeTests();
|
| - runReflectiveTests(NonNullCheckerTest);
|
| + defineReflectiveTests(NonNullCheckerTest);
|
| +}
|
| +
|
| +String _withError(String file, String error) {
|
| + return ("" + file).replaceFirst("boom", error);
|
| }
|
|
|
| @reflectiveTest
|
| @@ -22,6 +27,64 @@ class NonNullCheckerTest {
|
| // Tests simple usage of ints as iterators for a loop. Not directly related to
|
| // non-nullability, but if it is implemented this should be more efficient,
|
| // since languages.length will not be null-checked on every iteration.
|
| + final String defaultNnbdExample = '''
|
| +class Point {
|
| + final int x, y;
|
| + Point(this.x, this.y);
|
| + Point operator +(Point other) => new Point(x + other.x, y + other.y);
|
| + String toString() => "x: \$x, y: \$y";
|
| +}
|
| +
|
| +void main() {
|
| + Point p1 = new Point(0, 0);
|
| + Point p2 = new Point(10, 10);
|
| + print("p1 + p2 = \${p1 + p2}");
|
| +}
|
| +''';
|
| +
|
| + final String defaultNnbdExampleMod1 = '''
|
| +class Point {
|
| + final int x, y;
|
| + Point(this.x, this.y);
|
| + Point operator +(Point other) => new Point(x + other.x, y + other.y);
|
| + String toString() => "x: \$x, y: \$y";
|
| +}
|
| +
|
| +void main() {
|
| + Point p1 = new Point(0, 0);
|
| + Point p2 = new Point(10, /*boom*/null); // Change here.
|
| + print("p1 + p2 = \${p1 + p2}");
|
| +}
|
| +''';
|
| +
|
| + final String defaultNnbdExampleMod2 = '''
|
| +class Point {
|
| + final int x, y;
|
| + Point(this.x, this.y);
|
| + Point operator +(Point other) => new Point(x + other.x, y + other.y);
|
| + String toString() => "x: \$x, y: \$y";
|
| +}
|
| +
|
| +void main() {
|
| + bool f = false; // Necessary, because dead code is otherwise detected.
|
| + Point p1 = new Point(0, 0);
|
| + Point p2 = new Point(10, /*boom*/f ? 10 : null); // Change here.
|
| + print("p1 + p2 = \${p1 + p2}");
|
| +}
|
| +''';
|
| +
|
| + void test_assign_null_to_nonnullable() {
|
| + addFile('''
|
| +int x = 0;
|
| +
|
| +main() {
|
| + x = 1;
|
| + x = /*error:INVALID_ASSIGNMENT*/null;
|
| +}
|
| +''');
|
| + check(nonnullableTypes: <String>['dart:core,int']);
|
| + }
|
| +
|
| void test_forLoop() {
|
| checkFile('''
|
| class MyList {
|
| @@ -43,11 +106,6 @@ main() {
|
| ''');
|
| }
|
|
|
| - void test_nullableTypes() {
|
| - // By default x can be set to null.
|
| - checkFile('int x = null;');
|
| - }
|
| -
|
| void test_initialize_nonnullable_with_null() {
|
| addFile('int x = /*error:INVALID_ASSIGNMENT*/null;');
|
| check(nonnullableTypes: <String>['dart:core,int']);
|
| @@ -58,130 +116,73 @@ main() {
|
| check(nonnullableTypes: <String>['dart:core,int']);
|
| }
|
|
|
| - void test_assign_null_to_nonnullable() {
|
| - addFile('''
|
| -int x = 0;
|
| -
|
| -main() {
|
| - x = 1;
|
| - x = /*error:INVALID_ASSIGNMENT*/null;
|
| -}
|
| -''');
|
| + void test_nonnullable_fields() {
|
| + addFile(defaultNnbdExample);
|
| + // `null` can be passed as an argument to `Point` in default mode.
|
| + addFile(_withError(defaultNnbdExampleMod1, "error:INVALID_ASSIGNMENT"));
|
| + // A nullable expression can be passed as an argument to `Point` in default
|
| + // mode.
|
| + addFile(_withError(defaultNnbdExampleMod2, "error:INVALID_ASSIGNMENT"));
|
| check(nonnullableTypes: <String>['dart:core,int']);
|
| }
|
|
|
| - void test_uninitialized_nonnullable_local_variable() {
|
| - // Ideally, we will do flow analysis and throw an error only if a variable
|
| - // is used before it has been initialized.
|
| - addFile('main() { int /*error:NON_NULLABLE_FIELD_NOT_INITIALIZED*/x; }');
|
| - check(nonnullableTypes: <String>['dart:core,int']);
|
| + void test_nullable_fields() {
|
| + addFile(defaultNnbdExample);
|
| + // `null` can be passed as an argument to `Point` in default mode.
|
| + addFile(defaultNnbdExampleMod1);
|
| + // A nullable expression can be passed as an argument to `Point` in default
|
| + // mode.
|
| + addFile(defaultNnbdExampleMod2);
|
| + check();
|
| }
|
|
|
| - void test_uninitialized_nonnullable_top_level_variable_declaration() {
|
| - // If `int`s are non-nullable, then this code should throw an error.
|
| - addFile('int /*error:NON_NULLABLE_FIELD_NOT_INITIALIZED*/x;');
|
| - check(nonnullableTypes: <String>['dart:core,int']);
|
| + // Default example from NNBD document.
|
| + void test_nullableTypes() {
|
| + // By default x can be set to null.
|
| + checkFile('int x = null;');
|
| }
|
|
|
| - void test_uninitialized_nonnullable_field_declaration() {
|
| + void test_prefer_final_to_non_nullable_error() {
|
| + addFile('main() { final int /*error:FINAL_NOT_INITIALIZED*/x; }');
|
| + addFile('final int /*error:FINAL_NOT_INITIALIZED*/x;');
|
| addFile('''
|
| void foo() {}
|
|
|
| class A {
|
| - // Ideally, we should allow x to be init in the constructor, but that requires
|
| - // too much complication in the checker, so for now we throw a static error at
|
| - // the declaration site.
|
| - int /*error:NON_NULLABLE_FIELD_NOT_INITIALIZED*/x;
|
| + final int x;
|
|
|
| - A();
|
| + /*warning:FINAL_NOT_INITIALIZED_CONSTRUCTOR_1*/A();
|
| }
|
| ''');
|
| check(nonnullableTypes: <String>['dart:core,int']);
|
| }
|
|
|
| - void test_prefer_final_to_non_nullable_error() {
|
| - addFile('main() { final int /*error:FINAL_NOT_INITIALIZED*/x; }');
|
| - addFile('final int /*error:FINAL_NOT_INITIALIZED*/x;');
|
| + void test_uninitialized_nonnullable_field_declaration() {
|
| addFile('''
|
| void foo() {}
|
|
|
| class A {
|
| - final int x;
|
| + // Ideally, we should allow x to be init in the constructor, but that requires
|
| + // too much complication in the checker, so for now we throw a static error at
|
| + // the declaration site.
|
| + int /*error:NON_NULLABLE_FIELD_NOT_INITIALIZED*/x;
|
|
|
| - /*warning:FINAL_NOT_INITIALIZED_CONSTRUCTOR_1*/A();
|
| + A();
|
| }
|
| ''');
|
| check(nonnullableTypes: <String>['dart:core,int']);
|
| }
|
|
|
| - // Default example from NNBD document.
|
| - final String defaultNnbdExample = '''
|
| -class Point {
|
| - final int x, y;
|
| - Point(this.x, this.y);
|
| - Point operator +(Point other) => new Point(x + other.x, y + other.y);
|
| - String toString() => "x: \$x, y: \$y";
|
| -}
|
| -
|
| -void main() {
|
| - Point p1 = new Point(0, 0);
|
| - Point p2 = new Point(10, 10);
|
| - print("p1 + p2 = \${p1 + p2}");
|
| -}
|
| -''';
|
| -
|
| - final String defaultNnbdExampleMod1 = '''
|
| -class Point {
|
| - final int x, y;
|
| - Point(this.x, this.y);
|
| - Point operator +(Point other) => new Point(x + other.x, y + other.y);
|
| - String toString() => "x: \$x, y: \$y";
|
| -}
|
| -
|
| -void main() {
|
| - Point p1 = new Point(0, 0);
|
| - Point p2 = new Point(10, /*boom*/null); // Change here.
|
| - print("p1 + p2 = \${p1 + p2}");
|
| -}
|
| -''';
|
| -
|
| - final String defaultNnbdExampleMod2 = '''
|
| -class Point {
|
| - final int x, y;
|
| - Point(this.x, this.y);
|
| - Point operator +(Point other) => new Point(x + other.x, y + other.y);
|
| - String toString() => "x: \$x, y: \$y";
|
| -}
|
| -
|
| -void main() {
|
| - bool f = false; // Necessary, because dead code is otherwise detected.
|
| - Point p1 = new Point(0, 0);
|
| - Point p2 = new Point(10, /*boom*/f ? 10 : null); // Change here.
|
| - print("p1 + p2 = \${p1 + p2}");
|
| -}
|
| -''';
|
| -
|
| - void test_nullable_fields() {
|
| - addFile(defaultNnbdExample);
|
| - // `null` can be passed as an argument to `Point` in default mode.
|
| - addFile(defaultNnbdExampleMod1);
|
| - // A nullable expression can be passed as an argument to `Point` in default
|
| - // mode.
|
| - addFile(defaultNnbdExampleMod2);
|
| - check();
|
| + void test_uninitialized_nonnullable_local_variable() {
|
| + // Ideally, we will do flow analysis and throw an error only if a variable
|
| + // is used before it has been initialized.
|
| + addFile('main() { int /*error:NON_NULLABLE_FIELD_NOT_INITIALIZED*/x; }');
|
| + check(nonnullableTypes: <String>['dart:core,int']);
|
| }
|
|
|
| - void test_nonnullable_fields() {
|
| - addFile(defaultNnbdExample);
|
| - // `null` can be passed as an argument to `Point` in default mode.
|
| - addFile(_withError(defaultNnbdExampleMod1, "error:INVALID_ASSIGNMENT"));
|
| - // A nullable expression can be passed as an argument to `Point` in default
|
| - // mode.
|
| - addFile(_withError(defaultNnbdExampleMod2, "error:INVALID_ASSIGNMENT"));
|
| + void test_uninitialized_nonnullable_top_level_variable_declaration() {
|
| + // If `int`s are non-nullable, then this code should throw an error.
|
| + addFile('int /*error:NON_NULLABLE_FIELD_NOT_INITIALIZED*/x;');
|
| check(nonnullableTypes: <String>['dart:core,int']);
|
| }
|
| }
|
| -
|
| -String _withError(String file, String error) {
|
| - return ("" + file).replaceFirst("boom", error);
|
| -}
|
|
|