| Index: pkg/analyzer/test/src/task/strong/inferred_type_test.dart
|
| diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
|
| index b6311e66cd94e09b53a367c60c830995c9a54bc3..3f7c0095c434af70f1b3d0360fda6bdff266c361 100644
|
| --- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
|
| +++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
|
| @@ -20,6 +20,11 @@ void main() {
|
|
|
| abstract class InferredTypeMixin {
|
| /**
|
| + * If `true` then types of local elements may be checked.
|
| + */
|
| + bool get mayCheckTypesOfLocals;
|
| +
|
| + /**
|
| * Add a new file with the given [name] and [content].
|
| */
|
| void addFile(String content, {String name: '/main.dart'});
|
| @@ -30,7 +35,49 @@ abstract class InferredTypeMixin {
|
| */
|
| CompilationUnitElement checkFile(String content);
|
|
|
| + void test_blockBodiedLambdas_async_allReturnsAreFutures() {
|
| + if (!mayCheckTypesOfLocals) {
|
| + return;
|
| + }
|
| + var mainUnit = checkFile(r'''
|
| +import 'dart:async';
|
| +import 'dart:math' show Random;
|
| +main() {
|
| + var f = /*info:INFERRED_TYPE_CLOSURE*/() async {
|
| + if (new Random().nextBool()) {
|
| + return new Future<int>.value(1);
|
| + } else {
|
| + return new Future<double>.value(2.0);
|
| + }
|
| + };
|
| + Future<num> g = f();
|
| + Future<int> h = /*info:ASSIGNMENT_CAST*/f();
|
| +}
|
| +''');
|
| + var f = mainUnit.functions[0].localVariables[0];
|
| + expect(f.type.toString(), '() → Future<num>');
|
| + }
|
| +
|
| + void test_blockBodiedLambdas_async_allReturnsAreFutures_topLevel() {
|
| + var mainUnit = checkFile(r'''
|
| +import 'dart:async';
|
| +import 'dart:math' show Random;
|
| +var f = /*info:INFERRED_TYPE_CLOSURE*/() async {
|
| + if (new Random().nextBool()) {
|
| + return new Future<int>.value(1);
|
| + } else {
|
| + return new Future<double>.value(2.0);
|
| + }
|
| +};
|
| +''');
|
| + var f = mainUnit.topLevelVariables[0];
|
| + expect(f.type.toString(), '() → Future<num>');
|
| + }
|
| +
|
| void test_blockBodiedLambdas_async_allReturnsAreValues() {
|
| + if (!mayCheckTypesOfLocals) {
|
| + return;
|
| + }
|
| var mainUnit = checkFile(r'''
|
| import 'dart:async';
|
| import 'dart:math' show Random;
|
| @@ -50,7 +97,26 @@ main() {
|
| expect(f.type.toString(), '() → Future<num>');
|
| }
|
|
|
| - void test_blockBodiedLambdas_async_alReturnsAreFutures() {
|
| + void test_blockBodiedLambdas_async_allReturnsAreValues_topLevel() {
|
| + var mainUnit = checkFile(r'''
|
| +import 'dart:async';
|
| +import 'dart:math' show Random;
|
| +var f = /*info:INFERRED_TYPE_CLOSURE*/() async {
|
| + if (new Random().nextBool()) {
|
| + return 1;
|
| + } else {
|
| + return 2.0;
|
| + }
|
| +};
|
| +''');
|
| + var f = mainUnit.topLevelVariables[0];
|
| + expect(f.type.toString(), '() → Future<num>');
|
| + }
|
| +
|
| + void test_blockBodiedLambdas_async_mixOfValuesAndFutures() {
|
| + if (!mayCheckTypesOfLocals) {
|
| + return;
|
| + }
|
| var mainUnit = checkFile(r'''
|
| import 'dart:async';
|
| import 'dart:math' show Random;
|
| @@ -59,7 +125,7 @@ main() {
|
| if (new Random().nextBool()) {
|
| return new Future<int>.value(1);
|
| } else {
|
| - return new Future<double>.value(2.0);
|
| + return 2.0;
|
| }
|
| };
|
| Future<num> g = f();
|
| @@ -70,43 +136,55 @@ main() {
|
| expect(f.type.toString(), '() → Future<num>');
|
| }
|
|
|
| - void test_blockBodiedLambdas_async_mixOfValuesAndFutures() {
|
| + void test_blockBodiedLambdas_async_mixOfValuesAndFutures_topLevel() {
|
| var mainUnit = checkFile(r'''
|
| - import 'dart:async';
|
| - import 'dart:math' show Random;
|
| - main() {
|
| - var f = /*info:INFERRED_TYPE_CLOSURE*/() async {
|
| - if (new Random().nextBool()) {
|
| - return new Future<int>.value(1);
|
| - } else {
|
| - return 2.0;
|
| - }
|
| - };
|
| - Future<num> g = f();
|
| - Future<int> h = /*info:ASSIGNMENT_CAST*/f();
|
| +import 'dart:async';
|
| +import 'dart:math' show Random;
|
| +var f = /*info:INFERRED_TYPE_CLOSURE*/() async {
|
| + if (new Random().nextBool()) {
|
| + return new Future<int>.value(1);
|
| + } else {
|
| + return 2.0;
|
| }
|
| +};
|
| ''');
|
| - var f = mainUnit.functions[0].localVariables[0];
|
| + var f = mainUnit.topLevelVariables[0];
|
| expect(f.type.toString(), '() → Future<num>');
|
| }
|
|
|
| void test_blockBodiedLambdas_asyncStar() {
|
| + if (!mayCheckTypesOfLocals) {
|
| + return;
|
| + }
|
| var mainUnit = checkFile(r'''
|
| - import 'dart:async';
|
| - main() {
|
| - var f = /*info:INFERRED_TYPE_CLOSURE*/() async* {
|
| - yield 1;
|
| - Stream<double> s;
|
| - yield* s;
|
| - };
|
| - Stream<num> g = f();
|
| - Stream<int> h = /*info:ASSIGNMENT_CAST*/f();
|
| - }
|
| +import 'dart:async';
|
| +main() {
|
| + var f = /*info:INFERRED_TYPE_CLOSURE*/() async* {
|
| + yield 1;
|
| + Stream<double> s;
|
| + yield* s;
|
| + };
|
| + Stream<num> g = f();
|
| + Stream<int> h = /*info:ASSIGNMENT_CAST*/f();
|
| +}
|
| ''');
|
| var f = mainUnit.functions[0].localVariables[0];
|
| expect(f.type.toString(), '() → Stream<num>');
|
| }
|
|
|
| + void test_blockBodiedLambdas_asyncStar_topLevel() {
|
| + var mainUnit = checkFile(r'''
|
| + import 'dart:async';
|
| +var f = /*info:INFERRED_TYPE_CLOSURE*/() async* {
|
| + yield 1;
|
| + Stream<double> s;
|
| + yield* s;
|
| +};
|
| +''');
|
| + var f = mainUnit.topLevelVariables[0];
|
| + expect(f.type.toString(), '() → Stream<num>');
|
| + }
|
| +
|
| void test_blockBodiedLambdas_basic() {
|
| checkFile(r'''
|
| test1() {
|
| @@ -126,6 +204,9 @@ Iterable<int> z = y;
|
| }
|
|
|
| void test_blockBodiedLambdas_doesNotInferBottom_async() {
|
| + if (!mayCheckTypesOfLocals) {
|
| + return;
|
| + }
|
| var mainUnit = checkFile(r'''
|
| import 'dart:async';
|
| main() async {
|
| @@ -135,12 +216,23 @@ main() async {
|
| String s = /*info:DYNAMIC_CAST*/await f();
|
| }
|
| ''');
|
| -
|
| var f = mainUnit.functions[0].localVariables[0];
|
| expect(f.type.toString(), '() → Future<dynamic>');
|
| }
|
|
|
| + void test_blockBodiedLambdas_doesNotInferBottom_async_topLevel() {
|
| + var mainUnit = checkFile(r'''
|
| +import 'dart:async';
|
| +var f = () async { return null; };
|
| +''');
|
| + var f = mainUnit.topLevelVariables[0];
|
| + expect(f.type.toString(), '() → Future<dynamic>');
|
| + }
|
| +
|
| void test_blockBodiedLambdas_doesNotInferBottom_asyncStar() {
|
| + if (!mayCheckTypesOfLocals) {
|
| + return;
|
| + }
|
| var mainUnit = checkFile(r'''
|
| import 'dart:async';
|
| main() async {
|
| @@ -150,12 +242,23 @@ main() async {
|
| String s = /*info:DYNAMIC_CAST*/await f().first;
|
| }
|
| ''');
|
| -
|
| var f = mainUnit.functions[0].localVariables[0];
|
| expect(f.type.toString(), '() → Stream<dynamic>');
|
| }
|
|
|
| + void test_blockBodiedLambdas_doesNotInferBottom_asyncStar_topLevel() {
|
| + var mainUnit = checkFile(r'''
|
| +import 'dart:async';
|
| +var f = () async* { yield null; };
|
| +''');
|
| + var f = mainUnit.topLevelVariables[0];
|
| + expect(f.type.toString(), '() → Stream<dynamic>');
|
| + }
|
| +
|
| void test_blockBodiedLambdas_doesNotInferBottom_sync() {
|
| + if (!mayCheckTypesOfLocals) {
|
| + return;
|
| + }
|
| var mainUnit = checkFile(r'''
|
| var h = null;
|
| void foo(int f(Object _)) {}
|
| @@ -175,7 +278,18 @@ main() {
|
| expect(f.type.toString(), '(Object) → dynamic');
|
| }
|
|
|
| + void test_blockBodiedLambdas_doesNotInferBottom_sync_topLevel() {
|
| + var mainUnit = checkFile(r'''
|
| +var f = (Object x) { return null; };
|
| +''');
|
| + var f = mainUnit.topLevelVariables[0];
|
| + expect(f.type.toString(), '(Object) → dynamic');
|
| + }
|
| +
|
| void test_blockBodiedLambdas_doesNotInferBottom_syncStar() {
|
| + if (!mayCheckTypesOfLocals) {
|
| + return;
|
| + }
|
| var mainUnit = checkFile(r'''
|
| main() {
|
| var f = () sync* { yield null; };
|
| @@ -184,12 +298,22 @@ main() {
|
| String s = /*info:DYNAMIC_CAST*/f().first;
|
| }
|
| ''');
|
| -
|
| var f = mainUnit.functions[0].localVariables[0];
|
| expect(f.type.toString(), '() → Iterable<dynamic>');
|
| }
|
|
|
| + void test_blockBodiedLambdas_doesNotInferBottom_syncStar_topLevel() {
|
| + var mainUnit = checkFile(r'''
|
| +var f = () sync* { yield null; };
|
| +''');
|
| + var f = mainUnit.topLevelVariables[0];
|
| + expect(f.type.toString(), '() → Iterable<dynamic>');
|
| + }
|
| +
|
| void test_blockBodiedLambdas_downwardsIncompatibleWithUpwardsInference() {
|
| + if (!mayCheckTypesOfLocals) {
|
| + return;
|
| + }
|
| var mainUnit = checkFile(r'''
|
| main() {
|
| String f() => null;
|
| @@ -201,6 +325,16 @@ main() {
|
| expect(f.type.toString(), '() → String');
|
| }
|
|
|
| + void
|
| + test_blockBodiedLambdas_downwardsIncompatibleWithUpwardsInference_topLevel() {
|
| + var mainUnit = checkFile(r'''
|
| +String f() => null;
|
| +var g = f;
|
| +''');
|
| + var f = mainUnit.topLevelVariables[0];
|
| + expect(f.type.toString(), '() → String');
|
| + }
|
| +
|
| void test_blockBodiedLambdas_LUB() {
|
| checkFile(r'''
|
| import 'dart:math' show Random;
|
| @@ -236,6 +370,9 @@ Iterable<int> z = /*info:ASSIGNMENT_CAST*/y;
|
| }
|
|
|
| void test_blockBodiedLambdas_nestedLambdas() {
|
| + if (!mayCheckTypesOfLocals) {
|
| + return;
|
| + }
|
| // Original feature request: https://github.com/dart-lang/sdk/issues/25487
|
| var mainUnit = checkFile(r'''
|
| main() {
|
| @@ -248,7 +385,21 @@ main() {
|
| expect(f.type.toString(), '() → (int) → num');
|
| }
|
|
|
| + void test_blockBodiedLambdas_nestedLambdas_topLevel() {
|
| + // Original feature request: https://github.com/dart-lang/sdk/issues/25487
|
| + var mainUnit = checkFile(r'''
|
| +var f = /*info:INFERRED_TYPE_CLOSURE*/() {
|
| + return /*info:INFERRED_TYPE_CLOSURE*/(int x) { return 2.0 * x; };
|
| +};
|
| +''');
|
| + var f = mainUnit.topLevelVariables[0];
|
| + expect(f.type.toString(), '() → (int) → num');
|
| + }
|
| +
|
| void test_blockBodiedLambdas_noReturn() {
|
| + if (!mayCheckTypesOfLocals) {
|
| + return;
|
| + }
|
| var mainUnit = checkFile(r'''
|
| test1() {
|
| List<int> o;
|
| @@ -260,7 +411,19 @@ test1() {
|
| expect(f.type.toString(), 'Iterable<dynamic>');
|
| }
|
|
|
| + void test_blockBodiedLambdas_noReturn_topLevel() {
|
| + var mainUnit = checkFile(r'''
|
| +final List<int> o = <int>[];
|
| +var y = o.map((x) { });
|
| +''');
|
| + var f = mainUnit.topLevelVariables[1];
|
| + expect(f.type.toString(), 'Iterable<dynamic>');
|
| + }
|
| +
|
| void test_blockBodiedLambdas_syncStar() {
|
| + if (!mayCheckTypesOfLocals) {
|
| + return;
|
| + }
|
| var mainUnit = checkFile(r'''
|
| main() {
|
| var f = /*info:INFERRED_TYPE_CLOSURE*/() sync* {
|
| @@ -275,6 +438,17 @@ main() {
|
| expect(f.type.toString(), '() → Iterable<num>');
|
| }
|
|
|
| + void test_blockBodiedLambdas_syncStar_topLevel() {
|
| + var mainUnit = checkFile(r'''
|
| +var f = /*info:INFERRED_TYPE_CLOSURE*/() sync* {
|
| + yield 1;
|
| + yield* /*info:INFERRED_TYPE_LITERAL*/[3, 4.0];
|
| +};
|
| +''');
|
| + var f = mainUnit.topLevelVariables[0];
|
| + expect(f.type.toString(), '() → Iterable<num>');
|
| + }
|
| +
|
| void test_canInferAlsoFromStaticAndInstanceFieldsFlagOn() {
|
| addFile(
|
| '''
|
| @@ -2528,6 +2702,9 @@ test2() {
|
| }
|
|
|
| void test_listLiteralsShouldNotInferBottom() {
|
| + if (!mayCheckTypesOfLocals) {
|
| + return;
|
| + }
|
| var unit = checkFile(r'''
|
| test1() {
|
| var x = [null];
|
| @@ -2538,6 +2715,14 @@ test1() {
|
| expect(x.type.toString(), 'List<dynamic>');
|
| }
|
|
|
| + void test_listLiteralsShouldNotInferBottom_topLevel() {
|
| + var unit = checkFile(r'''
|
| +var x = [null];
|
| +''');
|
| + var x = unit.topLevelVariables[0];
|
| + expect(x.type.toString(), 'List<dynamic>');
|
| + }
|
| +
|
| void test_mapLiterals() {
|
| checkFile(r'''
|
| test1() {
|
| @@ -2587,6 +2772,9 @@ test2() {
|
| }
|
|
|
| void test_mapLiteralsShouldNotInferBottom() {
|
| + if (!mayCheckTypesOfLocals) {
|
| + return;
|
| + }
|
| var unit = checkFile(r'''
|
| test1() {
|
| var x = { null: null };
|
| @@ -2597,6 +2785,14 @@ test1() {
|
| expect(x.type.toString(), 'Map<dynamic, dynamic>');
|
| }
|
|
|
| + void test_mapLiteralsShouldNotInferBottom_topLevel() {
|
| + var unit = checkFile(r'''
|
| +var x = { null: null };
|
| +''');
|
| + var x = unit.topLevelVariables[0];
|
| + expect(x.type.toString(), 'Map<dynamic, dynamic>');
|
| + }
|
| +
|
| void test_noErrorWhenDeclaredTypeIsNumAndAssignedNull() {
|
| checkFile('''
|
| test1() {
|
| @@ -2705,7 +2901,7 @@ void main() {
|
| ''');
|
| }
|
|
|
| - void test_staticRefersToNonstaticField_inOtherLibraryCycle() {
|
| + void test_staticRefersToNonStaticField_inOtherLibraryCycle() {
|
| addFile(
|
| '''
|
| import 'b.dart';
|
| @@ -2759,6 +2955,9 @@ test() {
|
|
|
| @reflectiveTest
|
| class InferredTypeTest extends InferredTypeMixin {
|
| + @override
|
| + bool get mayCheckTypesOfLocals => true;
|
| +
|
| /// Adds a file to check. The file should contain:
|
| ///
|
| /// * all expected failures are listed in the source code using comments
|
|
|