Version 2.13.0-46.0.dev
Merge commit 'f0ec362a1c082bf9c29e805f1bf7981d38eff8a9' into 'dev'
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 95ce3fd..04edcc1 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -482,7 +482,7 @@
FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_EXTENDS,
FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_IMPLEMENTS,
FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_WITH,
- HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR,
+ HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER,
HintCode.ASSIGNMENT_OF_DO_NOT_STORE,
HintCode.CAN_BE_NULL_AFTER_NULL_AWARE,
HintCode.DEAD_CODE,
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
index 030cecb..69ebea3 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
@@ -16,6 +16,7 @@
EnableString.control_flow_collections:
ExperimentalFeatures.control_flow_collections,
EnableString.extension_methods: ExperimentalFeatures.extension_methods,
+ EnableString.extension_types: ExperimentalFeatures.extension_types,
EnableString.generic_metadata: ExperimentalFeatures.generic_metadata,
EnableString.non_nullable: ExperimentalFeatures.non_nullable,
EnableString.nonfunction_type_aliases:
@@ -39,6 +40,9 @@
/// String to enable the experiment "extension-methods"
static const String extension_methods = 'extension-methods';
+ /// String to enable the experiment "extension-types"
+ static const String extension_types = 'extension-types';
+
/// String to enable the experiment "generic-metadata"
static const String generic_metadata = 'generic-metadata';
@@ -95,8 +99,18 @@
releaseVersion: Version.parse('2.6.0'),
);
- static final generic_metadata = ExperimentalFeature(
+ static final extension_types = ExperimentalFeature(
index: 3,
+ enableString: EnableString.extension_types,
+ isEnabledByDefault: IsEnabledByDefault.extension_types,
+ isExpired: IsExpired.extension_types,
+ documentation: 'Extension Types',
+ experimentalReleaseVersion: null,
+ releaseVersion: Version.parse('2.13.0'),
+ );
+
+ static final generic_metadata = ExperimentalFeature(
+ index: 4,
enableString: EnableString.generic_metadata,
isEnabledByDefault: IsEnabledByDefault.generic_metadata,
isExpired: IsExpired.generic_metadata,
@@ -107,7 +121,7 @@
);
static final non_nullable = ExperimentalFeature(
- index: 4,
+ index: 5,
enableString: EnableString.non_nullable,
isEnabledByDefault: IsEnabledByDefault.non_nullable,
isExpired: IsExpired.non_nullable,
@@ -117,7 +131,7 @@
);
static final nonfunction_type_aliases = ExperimentalFeature(
- index: 5,
+ index: 6,
enableString: EnableString.nonfunction_type_aliases,
isEnabledByDefault: IsEnabledByDefault.nonfunction_type_aliases,
isExpired: IsExpired.nonfunction_type_aliases,
@@ -127,7 +141,7 @@
);
static final set_literals = ExperimentalFeature(
- index: 6,
+ index: 7,
enableString: EnableString.set_literals,
isEnabledByDefault: IsEnabledByDefault.set_literals,
isExpired: IsExpired.set_literals,
@@ -137,7 +151,7 @@
);
static final spread_collections = ExperimentalFeature(
- index: 7,
+ index: 8,
enableString: EnableString.spread_collections,
isEnabledByDefault: IsEnabledByDefault.spread_collections,
isExpired: IsExpired.spread_collections,
@@ -147,7 +161,7 @@
);
static final triple_shift = ExperimentalFeature(
- index: 8,
+ index: 9,
enableString: EnableString.triple_shift,
isEnabledByDefault: IsEnabledByDefault.triple_shift,
isExpired: IsExpired.triple_shift,
@@ -157,7 +171,7 @@
);
static final value_class = ExperimentalFeature(
- index: 9,
+ index: 10,
enableString: EnableString.value_class,
isEnabledByDefault: IsEnabledByDefault.value_class,
isExpired: IsExpired.value_class,
@@ -167,7 +181,7 @@
);
static final variance = ExperimentalFeature(
- index: 10,
+ index: 11,
enableString: EnableString.variance,
isEnabledByDefault: IsEnabledByDefault.variance,
isExpired: IsExpired.variance,
@@ -189,6 +203,9 @@
/// Default state of the experiment "extension-methods"
static const bool extension_methods = true;
+ /// Default state of the experiment "extension-types"
+ static const bool extension_types = true;
+
/// Default state of the experiment "generic-metadata"
static const bool generic_metadata = false;
@@ -227,6 +244,9 @@
/// Expiration status of the experiment "extension-methods"
static const bool extension_methods = false;
+ /// Expiration status of the experiment "extension-types"
+ static const bool extension_types = false;
+
/// Expiration status of the experiment "generic-metadata"
static const bool generic_metadata = false;
@@ -265,6 +285,9 @@
bool get extension_methods =>
isEnabled(ExperimentalFeatures.extension_methods);
+ /// Current state for the flag "extension-types"
+ bool get extension_types => isEnabled(ExperimentalFeatures.extension_types);
+
/// Current state for the flag "generic-metadata"
bool get generic_metadata => isEnabled(ExperimentalFeatures.generic_metadata);
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 7049407..3621e3b 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -19,9 +19,9 @@
* 0: the name of the actual argument type
* 1: the name of the expected function return type
*/
- static const HintCode ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR =
+ static const HintCode ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER =
HintCode(
- 'ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR',
+ 'ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER',
"The argument type '{0}' can't be assigned to the parameter type "
"'{1} Function(Object)' or '{1} Function(Object, StackTrace)'.");
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index b3136ff..9b54f4e 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -23,9 +23,9 @@
import 'package:analyzer/src/dart/resolver/body_inference_context.dart';
import 'package:analyzer/src/dart/resolver/exit_detector.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
-import 'package:analyzer/src/error/catch_error_verifier.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/error/deprecated_member_use_verifier.dart';
+import 'package:analyzer/src/error/error_handler_verifier.dart';
import 'package:analyzer/src/error/must_call_super_verifier.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -70,7 +70,7 @@
final MustCallSuperVerifier _mustCallSuperVerifier;
- final CatchErrorVerifier _catchErrorVerifier;
+ final ErrorHandlerVerifier _errorHandlerVerifier;
/// The [WorkspacePackage] in which [_currentLibrary] is declared.
final WorkspacePackage? _workspacePackage;
@@ -109,8 +109,8 @@
_deprecatedVerifier =
DeprecatedMemberUseVerifier(workspacePackage, _errorReporter),
_mustCallSuperVerifier = MustCallSuperVerifier(_errorReporter),
- _catchErrorVerifier =
- CatchErrorVerifier(_errorReporter, typeProvider, typeSystem),
+ _errorHandlerVerifier =
+ ErrorHandlerVerifier(_errorReporter, typeProvider, typeSystem),
_workspacePackage = workspacePackage {
_deprecatedVerifier.pushInDeprecatedValue(_currentLibrary.hasDeprecated);
_inDoNotStoreMember = _currentLibrary.hasDoNotStore;
@@ -596,7 +596,7 @@
void visitMethodInvocation(MethodInvocation node) {
_deprecatedVerifier.methodInvocation(node);
_checkForNullAwareHints(node, node.operator);
- _catchErrorVerifier.verifyMethodInvocation(node);
+ _errorHandlerVerifier.verifyMethodInvocation(node);
super.visitMethodInvocation(node);
}
diff --git a/pkg/analyzer/lib/src/error/catch_error_verifier.dart b/pkg/analyzer/lib/src/error/catch_error_verifier.dart
deleted file mode 100644
index 00d227d..0000000
--- a/pkg/analyzer/lib/src/error/catch_error_verifier.dart
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright (c) 2021, 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/ast/ast.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/ast/extensions.dart';
-import 'package:analyzer/src/dart/element/type_provider.dart';
-import 'package:analyzer/src/dart/element/type_system.dart';
-import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/error/return_type_verifier.dart';
-import 'package:analyzer/src/generated/error_verifier.dart';
-
-/// Reports on invalid functions passed to [Future.catchError].
-class CatchErrorVerifier {
- final ErrorReporter _errorReporter;
-
- final TypeProviderImpl _typeProvider;
-
- final TypeSystemImpl _typeSystem;
-
- final ReturnTypeVerifier _returnTypeVerifier;
-
- CatchErrorVerifier(this._errorReporter, this._typeProvider, this._typeSystem)
- : _returnTypeVerifier = ReturnTypeVerifier(
- typeProvider: _typeProvider,
- typeSystem: _typeSystem,
- errorReporter: _errorReporter,
- );
-
- void verifyMethodInvocation(MethodInvocation node) {
- var target = node.realTarget;
- if (target == null) {
- return;
- }
- var methodName = node.methodName;
- if (!(methodName.name == 'catchError' &&
- target.typeOrThrow.isDartAsyncFuture)) {
- return;
- }
- if (node.argumentList.arguments.isEmpty) {
- return;
- }
- var callback = node.argumentList.arguments.first;
- if (callback is NamedExpression) {
- // This implies that no positional arguments are passed.
- return;
- }
- var targetType = target.staticType as InterfaceType;
- var targetFutureType = targetType.typeArguments.first;
- var expectedReturnType = _typeProvider.futureOrType(targetFutureType);
- if (callback is FunctionExpression) {
- // TODO(migration): should be FunctionType, not nullable
- var callbackType = callback.staticType as FunctionType;
- _checkOnErrorFunctionType(callback, callbackType, expectedReturnType);
- var catchErrorOnErrorExecutable = EnclosingExecutableContext(
- callback.declaredElement,
- isAsynchronous: true,
- catchErrorOnErrorReturnType: expectedReturnType);
- var returnStatementVerifier =
- _ReturnStatementVerifier(_returnTypeVerifier);
- _returnTypeVerifier.enclosingExecutable = catchErrorOnErrorExecutable;
- callback.body.accept(returnStatementVerifier);
- } else {
- var callbackType = callback.staticType;
- if (callbackType is FunctionType) {
- _checkReturnType(expectedReturnType, callbackType.returnType, callback);
- _checkOnErrorFunctionType(callback, callbackType, expectedReturnType);
- } else {
- // If [callback] is not even a Function, then ErrorVerifier will have
- // reported this.
- }
- }
- }
-
- void _checkOnErrorFunctionType(Expression expression,
- FunctionType expressionType, DartType expectedFunctionReturnType) {
- void report() {
- _errorReporter.reportErrorForNode(
- HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR,
- expression,
- [expressionType, expectedFunctionReturnType],
- );
- }
-
- var parameters = expressionType.parameters;
- if (parameters.isEmpty) {
- return report();
- }
- var firstParameter = parameters.first;
- if (firstParameter.isNamed) {
- return report();
- } else {
- if (!_typeSystem.isSubtypeOf(
- _typeProvider.objectType, firstParameter.type)) {
- return report();
- }
- }
- if (parameters.length == 2) {
- var secondParameter = parameters[1];
- if (secondParameter.isNamed) {
- return report();
- } else {
- if (!_typeSystem.isSubtypeOf(
- _typeProvider.stackTraceType, secondParameter.type)) {
- return report();
- }
- }
- } else if (parameters.length > 2) {
- return report();
- }
- }
-
- void _checkReturnType(
- DartType expectedType, DartType functionReturnType, Expression callback) {
- if (!_typeSystem.isAssignableTo(functionReturnType, expectedType)) {
- _errorReporter.reportErrorForNode(
- HintCode.RETURN_TYPE_INVALID_FOR_CATCH_ERROR,
- callback,
- [functionReturnType, expectedType],
- );
- }
- }
-}
-
-/// Visits a function body, looking for return statements.
-class _ReturnStatementVerifier extends RecursiveAstVisitor<void> {
- final ReturnTypeVerifier _returnTypeVerifier;
-
- _ReturnStatementVerifier(this._returnTypeVerifier);
-
- @override
- void visitExpressionFunctionBody(ExpressionFunctionBody node) {
- _returnTypeVerifier.verifyExpressionFunctionBody(node);
- super.visitExpressionFunctionBody(node);
- }
-
- @override
- void visitFunctionExpression(FunctionExpression node) {
- // Do not visit within [node]. We have no interest in return statements
- // within.
- }
- @override
- void visitReturnStatement(ReturnStatement node) {
- _returnTypeVerifier.verifyReturnStatement(node);
- super.visitReturnStatement(node);
- }
-}
diff --git a/pkg/analyzer/lib/src/error/error_handler_verifier.dart b/pkg/analyzer/lib/src/error/error_handler_verifier.dart
new file mode 100644
index 0000000..0706474
--- /dev/null
+++ b/pkg/analyzer/lib/src/error/error_handler_verifier.dart
@@ -0,0 +1,281 @@
+// Copyright (c) 2021, 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/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/element/type_provider.dart';
+import 'package:analyzer/src/dart/element/type_system.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/error/return_type_verifier.dart';
+import 'package:analyzer/src/generated/error_verifier.dart';
+import 'package:collection/collection.dart';
+
+/// Reports on invalid functions passed as error handlers.
+///
+/// Functions must either accept exactly one positional parameter, or exactly
+/// two positional parameters. The one parameter (or the first parameter) must
+/// have a type of `dynamic`, `Object`, or `Object?`. If a second parameter is
+/// accepted, it must have a type of `StackTrace`.
+///
+/// A function is checked if it is passed as:
+/// * as the first argument to [Future.catchError],
+/// * as the 'onError' named argument to [Future.then],
+/// * as the first argument to [Stream.handleError],
+/// * as the 'onError' named argument to [Future.onError],
+/// * as the first argument to [StreamSubscription.onError],
+///
+/// Additionally, a function passed as the first argument to
+/// [Future<T>.catchError] must return `FutureOr<T>`, and any return statements in a
+/// function literal must return a value of type `FutureOr<T>`.
+class ErrorHandlerVerifier {
+ final ErrorReporter _errorReporter;
+
+ final TypeProviderImpl _typeProvider;
+
+ final TypeSystemImpl _typeSystem;
+
+ final ReturnTypeVerifier _returnTypeVerifier;
+
+ ErrorHandlerVerifier(
+ this._errorReporter, this._typeProvider, this._typeSystem)
+ : _returnTypeVerifier = ReturnTypeVerifier(
+ typeProvider: _typeProvider,
+ typeSystem: _typeSystem,
+ errorReporter: _errorReporter,
+ );
+
+ void verifyMethodInvocation(MethodInvocation node) {
+ var target = node.realTarget;
+ if (target == null) {
+ return;
+ }
+
+ if (node.argumentList.arguments.isEmpty) {
+ return;
+ }
+
+ var targetType = target.staticType;
+ if (targetType == null) {
+ return;
+ }
+ var methodName = node.methodName.name;
+ if (methodName == 'catchError' && targetType.isDartAsyncFuture) {
+ var callback = node.argumentList.arguments.first;
+ if (callback is NamedExpression) {
+ // This implies that no positional arguments are passed.
+ return;
+ }
+ _checkFutureCatchErrorOnError(target, callback);
+ return;
+ }
+
+ if (methodName == 'then' && targetType.isDartAsyncFuture) {
+ var callback = node.argumentList.arguments
+ .whereType<NamedExpression>()
+ .firstWhereOrNull(
+ (argument) => argument.name.label.name == 'onError');
+ if (callback == null) {
+ return;
+ }
+ var callbackType = callback.staticType;
+ if (callbackType == null) {
+ return;
+ }
+ if (callbackType is FunctionType) {
+ // TODO(srawlins): Also check return type of the 'onError' named
+ // argument to [Future<T>.then].
+ _checkErrorHandlerFunctionType(
+ callback, callbackType, _typeProvider.voidType,
+ checkFirstParameterType: callback.expression is FunctionExpression);
+ return;
+ }
+ // [callbackType] might be dart:core's Function, or something not
+ // assignable to Function, in which case an error is reported elsewhere.
+ }
+
+ if (methodName == 'handleError' &&
+ _isDartCoreAsyncType(targetType, 'Stream')) {
+ var callback = node.argumentList.arguments.first;
+ if (callback is NamedExpression) {
+ // This implies that no positional arguments are passed.
+ return;
+ }
+ var callbackType = callback.staticType;
+ if (callbackType == null) {
+ return;
+ }
+ if (callbackType is FunctionType) {
+ _checkErrorHandlerFunctionType(
+ callback, callbackType, _typeProvider.voidType,
+ checkFirstParameterType: callback is FunctionExpression);
+ return;
+ }
+ // [callbackType] might be dart:core's Function, or something not
+ // assignable to Function, in which case an error is reported elsewhere.
+ }
+
+ if (methodName == 'listen' && _isDartCoreAsyncType(targetType, 'Stream')) {
+ var callback = node.argumentList.arguments
+ .whereType<NamedExpression>()
+ .firstWhereOrNull(
+ (argument) => argument.name.label.name == 'onError');
+ if (callback == null) {
+ return;
+ }
+ var callbackType = callback.staticType;
+ if (callbackType == null) {
+ return;
+ }
+ if (callbackType is FunctionType) {
+ _checkErrorHandlerFunctionType(
+ callback, callbackType, _typeProvider.voidType,
+ checkFirstParameterType: callback.expression is FunctionExpression);
+ return;
+ }
+ // [callbackType] might be dart:core's Function, or something not
+ // assignable to Function, in which case an error is reported elsewhere.
+ }
+
+ if (methodName == 'onError' &&
+ _isDartCoreAsyncType(targetType, 'StreamSubscription')) {
+ var callback = node.argumentList.arguments.first;
+ if (callback is NamedExpression) {
+ // This implies that no positional arguments are passed.
+ return;
+ }
+ var callbackType = callback.staticType;
+ if (callbackType == null) {
+ return;
+ }
+ if (callbackType is FunctionType) {
+ _checkErrorHandlerFunctionType(
+ callback, callbackType, _typeProvider.voidType,
+ checkFirstParameterType: callback is FunctionExpression);
+ return;
+ }
+ // [callbackType] might be dart:core's Function, or something not
+ // assignable to Function, in which case an error is reported elsewhere.
+ }
+ }
+
+ /// Checks that [expression], a function with static type [expressionType], is
+ /// a valid error handler.
+ ///
+ /// Only checks the first parameter type if [checkFirstParameterType] is true.
+ /// Certain error handlers are allowed to specify a different type for their
+ /// first parameter.
+ void _checkErrorHandlerFunctionType(Expression expression,
+ FunctionType expressionType, DartType expectedFunctionReturnType,
+ {bool checkFirstParameterType = true}) {
+ void report() {
+ _errorReporter.reportErrorForNode(
+ HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER,
+ expression,
+ [expressionType, expectedFunctionReturnType],
+ );
+ }
+
+ var parameters = expressionType.parameters;
+ if (parameters.isEmpty) {
+ return report();
+ }
+ var firstParameter = parameters.first;
+ if (firstParameter.isNamed) {
+ return report();
+ } else if (checkFirstParameterType) {
+ if (!_typeSystem.isSubtypeOf(
+ _typeProvider.objectType, firstParameter.type)) {
+ return report();
+ }
+ }
+ if (parameters.length == 2) {
+ var secondParameter = parameters[1];
+ if (secondParameter.isNamed) {
+ return report();
+ } else {
+ if (!_typeSystem.isSubtypeOf(
+ _typeProvider.stackTraceType, secondParameter.type)) {
+ return report();
+ }
+ }
+ } else if (parameters.length > 2) {
+ return report();
+ }
+ }
+
+ /// Check the 'onError' argument given to [Future.catchError].
+ void _checkFutureCatchErrorOnError(Expression target, Expression callback) {
+ var targetType = target.staticType as InterfaceType;
+ var targetFutureType = targetType.typeArguments.first;
+ var expectedReturnType = _typeProvider.futureOrType(targetFutureType);
+ if (callback is FunctionExpression) {
+ // TODO(migration): should be FunctionType, not nullable
+ var callbackType = callback.staticType as FunctionType;
+ _checkErrorHandlerFunctionType(
+ callback, callbackType, expectedReturnType);
+ var catchErrorOnErrorExecutable = EnclosingExecutableContext(
+ callback.declaredElement,
+ isAsynchronous: true,
+ catchErrorOnErrorReturnType: expectedReturnType);
+ var returnStatementVerifier =
+ _ReturnStatementVerifier(_returnTypeVerifier);
+ _returnTypeVerifier.enclosingExecutable = catchErrorOnErrorExecutable;
+ callback.body.accept(returnStatementVerifier);
+ } else {
+ var callbackType = callback.staticType;
+ if (callbackType is FunctionType) {
+ _checkReturnType(expectedReturnType, callbackType.returnType, callback);
+ _checkErrorHandlerFunctionType(
+ callback, callbackType, expectedReturnType);
+ } else {
+ // If [callback] is not even a Function, then ErrorVerifier will have
+ // reported this.
+ }
+ }
+ }
+
+ void _checkReturnType(
+ DartType expectedType, DartType functionReturnType, Expression callback) {
+ if (!_typeSystem.isAssignableTo(functionReturnType, expectedType)) {
+ _errorReporter.reportErrorForNode(
+ HintCode.RETURN_TYPE_INVALID_FOR_CATCH_ERROR,
+ callback,
+ [functionReturnType, expectedType],
+ );
+ }
+ }
+
+ /// Returns whether [element] represents the []
+ bool _isDartCoreAsyncType(DartType type, String typeName) =>
+ type is InterfaceType &&
+ type.element.name == typeName &&
+ type.element.library.isDartAsync;
+}
+
+/// Visits a function body, looking for return statements.
+class _ReturnStatementVerifier extends RecursiveAstVisitor<void> {
+ final ReturnTypeVerifier _returnTypeVerifier;
+
+ _ReturnStatementVerifier(this._returnTypeVerifier);
+
+ @override
+ void visitExpressionFunctionBody(ExpressionFunctionBody node) {
+ _returnTypeVerifier.verifyExpressionFunctionBody(node);
+ super.visitExpressionFunctionBody(node);
+ }
+
+ @override
+ void visitFunctionExpression(FunctionExpression node) {
+ // Do not visit within [node]. We have no interest in return statements
+ // within.
+ }
+
+ @override
+ void visitReturnStatement(ReturnStatement node) {
+ _returnTypeVerifier.verifyReturnStatement(node);
+ super.visitReturnStatement(node);
+ }
+}
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 74bcc94..e588646 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -44,7 +44,7 @@
Future<T> catchError(Function onError, {bool test(Object error)});
- Future<R> then<R>(FutureOr<R> onValue(T value));
+ Future<R> then<R>(FutureOr<R> onValue(T value), {Function? onError});
Future<T> whenComplete(action());
@@ -90,6 +90,8 @@
StreamSubscription<T> listen(void onData(T event)?,
{Function? onError, void onDone()?, bool? cancelOnError});
+
+ Stream<T> handleError(Function onError, {bool test(dynamic error)});
}
abstract class StreamIterator<T> {}
diff --git a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_catch_error_on_error_test.dart b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_catch_error_on_error_test.dart
deleted file mode 100644
index ceb0706..0000000
--- a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_catch_error_on_error_test.dart
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright (c) 2021, 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/src/error/codes.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../dart/resolution/context_collection_resolution.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(ArgumentTypeNotAssignableCatchErrorOnErrorTest);
- defineReflectiveTests(
- ArgumentTypeNotAssignableCatchErrorOnErrorWithNullSafetyTest);
- });
-}
-
-@reflectiveTest
-class ArgumentTypeNotAssignableCatchErrorOnErrorTest
- extends PubPackageResolutionTest with WithoutNullSafetyMixin {
- void test_firstParameterIsDynamic() async {
- await assertNoErrorsInCode('''
-void f(Future<int> future, Future<int> Function(dynamic a) callback) {
- future.catchError(callback);
-}
-''');
- }
-
- void test_firstParameterIsNamed() async {
- await assertErrorsInCode('''
-void f(Future<int> future, Future<int> Function({Object a}) callback) {
- future.catchError(callback);
-}
-''', [
- error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR, 92, 8),
- ]);
- }
-
- void test_firstParameterIsOptional() async {
- await assertNoErrorsInCode('''
-void f(Future<int> future, Future<int> Function([Object a]) callback) {
- future.catchError(callback);
-}
-''');
- }
-
- void test_functionExpression_firstParameterIsDynamic() async {
- await assertNoErrorsInCode('''
-void f(Future<void> future) {
- future.catchError((dynamic a) {});
-}
-''');
- }
-
- void test_functionExpression_firstParameterIsImplicit() async {
- await assertNoErrorsInCode('''
-void f(Future<void> future) {
- future.catchError((a) {});
-}
-''');
- }
-
- void test_functionExpression_firstParameterIsNamed() async {
- await assertErrorsInCode('''
-void f(Future<void> future) {
- future.catchError(({Object a = 1}) {});
-}
-''', [
- error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR, 50, 19),
- ]);
- }
-
- void test_functionExpression_firstParameterIsOptional() async {
- await assertNoErrorsInCode('''
-void f(Future<void> future) {
- future.catchError(([Object a = 1]) {});
-}
-''');
- }
-
- void test_functionExpression_firstParameterIsVar() async {
- await assertNoErrorsInCode('''
-void f(Future<void> future) {
- future.catchError((var a) {});
-}
-''');
- }
-
- void test_functionExpression_noParameters() async {
- await assertErrorsInCode('''
-void f(Future<void> future) {
- future.catchError(() {});
-}
-''', [
- error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR, 50, 5),
- ]);
- }
-
- void test_functionExpression_secondParameterIsDynamic() async {
- await assertNoErrorsInCode('''
-void f(Future<void> future) {
- future.catchError((Object a, dynamic b) {});
-}
-''');
- }
-
- void test_functionExpression_secondParameterIsImplicit() async {
- await assertNoErrorsInCode('''
-void f(Future<void> future) {
- future.catchError((Object a, b) {});
-}
-''');
- }
-
- void test_functionExpression_secondParameterIsNamed() async {
- await assertErrorsInCode('''
-void f(Future<void> future) {
- future.catchError((Object a, {StackTrace b}) {});
-}
-''', [
- error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR, 50, 29),
- ]);
- }
-
- void test_functionExpression_secondParameterIsOptional() async {
- await assertNoErrorsInCode('''
-void f(Future<void> future) {
- future.catchError((Object a, [StackTrace st]) {});
-}
-''');
- }
-
- void test_functionExpression_secondParameterIsVar() async {
- await assertNoErrorsInCode('''
-void f(Future<void> future) {
- future.catchError((Object a, var b) {});
-}
-''');
- }
-
- void test_functionExpression_tooManyParameters() async {
- await assertErrorsInCode('''
-void f(Future<void> future) {
- future.catchError((a, b, c) {});
-}
-''', [
- error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR, 50, 12),
- ]);
- }
-
- void test_functionExpression_wrongFirstParameterType() async {
- await assertErrorsInCode('''
-void f(Future<void> future) {
- future.catchError((String a) {});
-}
-''', [
- error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR, 50, 13),
- ]);
- }
-
- void test_functionExpression_wrongSecondParameterType() async {
- await assertErrorsInCode('''
-void f(Future<void> future) {
- future.catchError((Object a, String b) {});
-}
-''', [
- error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR, 50, 23),
- ]);
- }
-
- void test_noParameters() async {
- await assertErrorsInCode('''
-void f(Future<int> future, Future<int> Function() callback) {
- future.catchError(callback);
-}
-''', [
- error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR, 82, 8),
- ]);
- }
-
- void test_okType() async {
- await assertNoErrorsInCode('''
-void f(Future<int> future, Future<int> Function(Object, StackTrace) callback) {
- future.catchError(callback);
-}
-''');
- }
-
- void test_secondParameterIsDynamic() async {
- await assertNoErrorsInCode('''
-void f(Future<int> future, Future<int> Function(Object a, dynamic b) callback) {
- future.catchError(callback);
-}
-''');
- }
-
- void test_secondParameterIsNamed() async {
- await assertErrorsInCode('''
-void f(Future<int> future, Future<int> Function(Object a, {StackTrace b}) callback) {
- future.catchError(callback);
-}
-''', [
- error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR, 106, 8),
- ]);
- }
-
- void test_tooManyParameters() async {
- await assertErrorsInCode('''
-void f(Future<int> future, Future<int> Function(int, int, int) callback) {
- future.catchError(callback);
-}
-''', [
- error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR, 95, 8),
- ]);
- }
-
- void test_wrongSecondParameterType() async {
- await assertErrorsInCode('''
-void f(Future<int> future, Future<int> Function(Object, String) callback) {
- future.catchError(callback);
-}
-''', [
- error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR, 96, 8),
- ]);
- }
-
- voidtest_wrongFirstParameterType() async {
- await assertErrorsInCode('''
-void f(Future<int> future, Future<int> Function(String) callback) {
- future.catchError(callback);
-}
-''', [
- error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR, 88, 8),
- ]);
- }
-}
-
-@reflectiveTest
-class ArgumentTypeNotAssignableCatchErrorOnErrorWithNullSafetyTest
- extends ArgumentTypeNotAssignableCatchErrorOnErrorTest
- with WithNullSafetyMixin {
- void test_functionExpression_firstParameterIsNullableObject() async {
- await assertNoErrorsInCode('''
-void f(Future<void> future) {
- future.catchError((Object? a) {});
-}
-''');
- }
-
- @override
- void test_functionExpression_secondParameterIsNamed() async {
- await assertErrorsInCode('''
-void f(Future<void> future) {
- future.catchError((Object a, {required StackTrace b}) {});
-}
-''', [
- error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_CATCH_ERROR_ON_ERROR, 50, 38),
- ]);
- }
-
- void test_functionExpression_secondParameterIsNullableStackTrace() async {
- await assertNoErrorsInCode('''
-void f(Future<void> future) {
- future.catchError((Object a, StackTrace? b) {});
-}
-''');
- }
-
- @override
- void test_functionExpression_secondParameterIsOptional() async {
- await assertNoErrorsInCode('''
-void f(Future<void> future) {
- future.catchError((Object a, [StackTrace? st]) {});
-}
-''');
- }
-}
diff --git a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_to_error_handler_test.dart b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_to_error_handler_test.dart
new file mode 100644
index 0000000..eaeddb5
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_to_error_handler_test.dart
@@ -0,0 +1,704 @@
+// Copyright (c) 2021, 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/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(
+ ArgumentTypeNotAssignableToErrorHandler_FutureCatchErrorTest);
+ defineReflectiveTests(
+ ArgumentTypeNotAssignableToErrorHandler_FutureCatchErrorWithoutNullSafetyTest);
+ defineReflectiveTests(
+ ArgumentTypeNotAssignableToErrorHandler_FutureThenTest);
+ defineReflectiveTests(
+ ArgumentTypeNotAssignableToErrorHandler_FutureThenWithoutNullSafetyTest);
+ defineReflectiveTests(
+ ArgumentTypeNotAssignableToErrorHandler_StreamHandleErrorTest);
+ defineReflectiveTests(
+ ArgumentTypeNotAssignableToErrorHandler_StreamHandleErrorWithoutNullSafetyTest);
+ defineReflectiveTests(
+ ArgumentTypeNotAssignableToErrorHandler_StreamListenTest);
+ defineReflectiveTests(
+ ArgumentTypeNotAssignableToErrorHandler_StreamListenWithoutNullSafetyTest);
+ defineReflectiveTests(
+ ArgumentTypeNotAssignableToErrorHandler_StreamSubscriptionOnErrorTest);
+ defineReflectiveTests(
+ ArgumentTypeNotAssignableToErrorHandler_StreamSubscriptionOnErrorWithoutNullSafetyTest);
+ });
+}
+
+@reflectiveTest
+class ArgumentTypeNotAssignableToErrorHandler_FutureCatchErrorTest
+ extends PubPackageResolutionTest
+ with ArgumentTypeNotAssignableToErrorHandler_FutureCatchErrorTestCases {
+ void test_functionExpression_firstParameterIsNullableObject() async {
+ await assertNoErrorsInCode('''
+void f(Future<void> future) {
+ future.catchError((Object? a) {});
+}
+''');
+ }
+
+ @override
+ void test_functionExpression_secondParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Future<void> future) {
+ future.catchError((Object a, {required StackTrace b}) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 50, 38),
+ ]);
+ }
+
+ void test_functionExpression_secondParameterIsNullableStackTrace() async {
+ await assertNoErrorsInCode('''
+void f(Future<void> future) {
+ future.catchError((Object a, StackTrace? b) {});
+}
+''');
+ }
+}
+
+mixin ArgumentTypeNotAssignableToErrorHandler_FutureCatchErrorTestCases
+ on PubPackageResolutionTest {
+ void test_firstParameterIsDynamic() async {
+ await assertNoErrorsInCode('''
+void f(Future<int> future, Future<int> Function(dynamic a) callback) {
+ future.catchError(callback);
+}
+''');
+ }
+
+ void test_firstParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Future<int> future, Future<int> Function({Object a}) callback) {
+ future.catchError(callback);
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 92, 8),
+ ]);
+ }
+
+ void test_firstParameterIsOptional() async {
+ await assertNoErrorsInCode('''
+void f(Future<int> future, Future<int> Function([Object a]) callback) {
+ future.catchError(callback);
+}
+''');
+ }
+
+ void test_functionExpression_firstParameterIsDynamic() async {
+ await assertNoErrorsInCode('''
+void f(Future<void> future) {
+ future.catchError((dynamic a) {});
+}
+''');
+ }
+
+ void test_functionExpression_firstParameterIsImplicit() async {
+ await assertNoErrorsInCode('''
+void f(Future<void> future) {
+ future.catchError((a) {});
+}
+''');
+ }
+
+ void test_functionExpression_firstParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Future<void> future) {
+ future.catchError(({Object a = 1}) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 50, 19),
+ ]);
+ }
+
+ void test_functionExpression_firstParameterIsOptional() async {
+ await assertNoErrorsInCode('''
+void f(Future<void> future) {
+ future.catchError(([Object a = 1]) {});
+}
+''');
+ }
+
+ void test_functionExpression_firstParameterIsVar() async {
+ await assertNoErrorsInCode('''
+void f(Future<void> future) {
+ future.catchError((var a) {});
+}
+''');
+ }
+
+ void test_functionExpression_noParameters() async {
+ await assertErrorsInCode('''
+void f(Future<void> future) {
+ future.catchError(() {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 50, 5),
+ ]);
+ }
+
+ void test_functionExpression_secondParameterIsDynamic() async {
+ await assertNoErrorsInCode('''
+void f(Future<void> future) {
+ future.catchError((Object a, dynamic b) {});
+}
+''');
+ }
+
+ void test_functionExpression_secondParameterIsImplicit() async {
+ await assertNoErrorsInCode('''
+void f(Future<void> future) {
+ future.catchError((Object a, b) {});
+}
+''');
+ }
+
+ void test_functionExpression_secondParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Future<void> future) {
+ future.catchError((Object a, {StackTrace b}) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 50, 29),
+ ]);
+ }
+
+ void test_functionExpression_secondParameterIsVar() async {
+ await assertNoErrorsInCode('''
+void f(Future<void> future) {
+ future.catchError((Object a, var b) {});
+}
+''');
+ }
+
+ void test_functionExpression_tooManyParameters() async {
+ await assertErrorsInCode('''
+void f(Future<void> future) {
+ future.catchError((a, b, c) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 50, 12),
+ ]);
+ }
+
+ void test_functionExpression_wrongFirstParameterType() async {
+ await assertErrorsInCode('''
+void f(Future<void> future) {
+ future.catchError((String a) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 50, 13),
+ ]);
+ }
+
+ void test_functionExpression_wrongSecondParameterType() async {
+ await assertErrorsInCode('''
+void f(Future<void> future) {
+ future.catchError((Object a, String b) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 50, 23),
+ ]);
+ }
+
+ void test_noParameters() async {
+ await assertErrorsInCode('''
+void f(Future<int> future, Future<int> Function() callback) {
+ future.catchError(callback);
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 82, 8),
+ ]);
+ }
+
+ void test_okType() async {
+ await assertNoErrorsInCode('''
+void f(Future<int> future, Future<int> Function(Object, StackTrace) callback) {
+ future.catchError(callback);
+}
+''');
+ }
+
+ void test_secondParameterIsDynamic() async {
+ await assertNoErrorsInCode('''
+void f(Future<int> future, Future<int> Function(Object a, dynamic b) callback) {
+ future.catchError(callback);
+}
+''');
+ }
+
+ void test_secondParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Future<int> future, Future<int> Function(Object a, {StackTrace b}) callback) {
+ future.catchError(callback);
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 106, 8),
+ ]);
+ }
+
+ void test_tooManyParameters() async {
+ await assertErrorsInCode('''
+void f(Future<int> future, Future<int> Function(int, int, int) callback) {
+ future.catchError(callback);
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 95, 8),
+ ]);
+ }
+
+ void test_wrongFirstParameterType() async {
+ await assertErrorsInCode('''
+void f(Future<int> future, Future<int> Function(String) callback) {
+ future.catchError(callback);
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 88, 8),
+ ]);
+ }
+
+ void test_wrongSecondParameterType() async {
+ await assertErrorsInCode('''
+void f(Future<int> future, Future<int> Function(Object, String) callback) {
+ future.catchError(callback);
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 96, 8),
+ ]);
+ }
+}
+
+@reflectiveTest
+class ArgumentTypeNotAssignableToErrorHandler_FutureCatchErrorWithoutNullSafetyTest
+ extends PubPackageResolutionTest
+ with
+ ArgumentTypeNotAssignableToErrorHandler_FutureCatchErrorTestCases,
+ WithoutNullSafetyMixin {}
+
+@reflectiveTest
+class ArgumentTypeNotAssignableToErrorHandler_FutureThenTest
+ extends PubPackageResolutionTest
+ with ArgumentTypeNotAssignableToErrorHandler_FutureThenTestCases {
+ void test_functionExpression_firstParameterIsNullableObject() async {
+ await assertNoErrorsInCode('''
+void f(Future<void> future) {
+ future.then((_) {}, onError: (Object? a) {});
+}
+''');
+ }
+
+ @override
+ void test_functionExpression_secondParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Future<void> future) {
+ future.then((_) {}, onError: (Object a, {StackTrace? b}) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 52, 39),
+ ]);
+ }
+
+ void test_functionExpression_secondParameterIsNullableStackTrace() async {
+ await assertNoErrorsInCode('''
+void f(Future<void> future) {
+ future.then((_) {}, onError: (Object a, StackTrace? b) {});
+}
+''');
+ }
+}
+
+mixin ArgumentTypeNotAssignableToErrorHandler_FutureThenTestCases
+ on PubPackageResolutionTest {
+ void test_firstParameterIsDynamic() async {
+ await assertNoErrorsInCode('''
+void f(Future<void> future, void Function(dynamic a) callback) {
+ future.then((_) {}, onError: callback);
+}
+''');
+ }
+
+ void test_firstParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Future<void> future, Future<int> Function({Object a}) callback) {
+ future.then((_) {}, onError: callback);
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 95, 17),
+ ]);
+ }
+
+ void test_functionExpression_firstParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Future<void> future) {
+ future.then((_) {}, onError: ({Object a = 1}) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 52, 28),
+ ]);
+ }
+
+ void test_functionExpression_noParameters() async {
+ await assertErrorsInCode('''
+void f(Future<void> future) {
+ future.then((_) {}, onError: () {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 52, 14),
+ ]);
+ }
+
+ void test_functionExpression_secondParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Future<void> future) {
+ future.then((_) {}, onError: (Object a, {StackTrace b}) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 52, 38),
+ ]);
+ }
+
+ void test_functionExpression_wrongFirstParameterType() async {
+ await assertErrorsInCode('''
+void f(Future<void> future) {
+ future.then((_) {}, onError: (String a) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 52, 22),
+ ]);
+ }
+
+ void test_functionType() async {
+ await assertNoErrorsInCode('''
+void f(Future<void> future, Function callback) {
+ future.then((_) {}, onError: callback);
+}
+''');
+ }
+}
+
+@reflectiveTest
+class ArgumentTypeNotAssignableToErrorHandler_FutureThenWithoutNullSafetyTest
+ extends PubPackageResolutionTest
+ with
+ ArgumentTypeNotAssignableToErrorHandler_FutureThenTestCases,
+ WithoutNullSafetyMixin {}
+
+@reflectiveTest
+class ArgumentTypeNotAssignableToErrorHandler_StreamHandleErrorTest
+ extends PubPackageResolutionTest
+ with ArgumentTypeNotAssignableToErrorHandler_StreamHandleErrorTestCases {
+ void test_functionExpression_firstParameterIsNullableObject() async {
+ await assertNoErrorsInCode('''
+void f(Stream<void> stream) {
+ stream.handleError((Object? a) {});
+}
+''');
+ }
+
+ @override
+ void test_functionExpression_secondParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Stream<void> stream) {
+ stream.handleError((Object a, {StackTrace? b}) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 51, 30),
+ ]);
+ }
+
+ void test_functionExpression_secondParameterIsNullableStackTrace() async {
+ await assertNoErrorsInCode('''
+void f(Stream<void> stream) {
+ stream.handleError((Object a, StackTrace? b) {});
+}
+''');
+ }
+}
+
+mixin ArgumentTypeNotAssignableToErrorHandler_StreamHandleErrorTestCases
+ on PubPackageResolutionTest {
+ void test_firstParameterIsDynamic() async {
+ await assertNoErrorsInCode('''
+void f(Stream<void> stream, void Function(dynamic a) callback) {
+ stream.handleError(callback);
+}
+''');
+ }
+
+ void test_firstParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Stream<void> stream, Future<int> Function({Object a}) callback) {
+ stream.handleError(callback);
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 94, 8),
+ ]);
+ }
+
+ void test_functionExpression_firstParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Stream<void> stream) {
+ stream.handleError(({Object a = 1}) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 51, 19),
+ ]);
+ }
+
+ void test_functionExpression_noParameters() async {
+ await assertErrorsInCode('''
+void f(Stream<void> stream) {
+ stream.handleError(() {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 51, 5),
+ ]);
+ }
+
+ void test_functionExpression_secondParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Stream<void> stream) {
+ stream.handleError((Object a, {StackTrace b}) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 51, 29),
+ ]);
+ }
+
+ void test_functionExpression_wrongFirstParameterType() async {
+ await assertErrorsInCode('''
+void f(Stream<void> stream) {
+ stream.handleError((String a) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 51, 13),
+ ]);
+ }
+}
+
+@reflectiveTest
+class ArgumentTypeNotAssignableToErrorHandler_StreamHandleErrorWithoutNullSafetyTest
+ extends PubPackageResolutionTest
+ with
+ ArgumentTypeNotAssignableToErrorHandler_StreamHandleErrorTestCases,
+ WithoutNullSafetyMixin {}
+
+@reflectiveTest
+class ArgumentTypeNotAssignableToErrorHandler_StreamListenTest
+ extends PubPackageResolutionTest
+ with ArgumentTypeNotAssignableToErrorHandler_StreamListenTestCases {
+ void test_functionExpression_firstParameterIsNullableObject() async {
+ await assertNoErrorsInCode('''
+void f(Stream<void> stream) {
+ stream.listen((_) {}, onError: (Object? a) {});
+}
+''');
+ }
+
+ @override
+ void test_functionExpression_secondParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Stream<void> stream) {
+ stream.listen((_) {}, onError: (Object a, {StackTrace? b}) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 54, 39),
+ ]);
+ }
+
+ void test_functionExpression_secondParameterIsNullableStackTrace() async {
+ await assertNoErrorsInCode('''
+void f(Stream<void> stream) {
+ stream.listen((_) {}, onError: (Object a, StackTrace? b) {});
+}
+''');
+ }
+}
+
+mixin ArgumentTypeNotAssignableToErrorHandler_StreamListenTestCases
+ on PubPackageResolutionTest {
+ void test_firstParameterIsDynamic() async {
+ await assertNoErrorsInCode('''
+void f(Stream<void> stream, void Function(dynamic a) callback) {
+ stream.listen((_) {}, onError: callback);
+}
+''');
+ }
+
+ void test_firstParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Stream<void> stream, Future<int> Function({Object a}) callback) {
+ stream.listen((_) {}, onError: callback);
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 97, 17),
+ ]);
+ }
+
+ void test_functionExpression_firstParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Stream<void> stream) {
+ stream.listen((_) {}, onError: ({Object a = 1}) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 54, 28),
+ ]);
+ }
+
+ void test_functionExpression_noParameters() async {
+ await assertErrorsInCode('''
+void f(Stream<void> stream) {
+ stream.listen((_) {}, onError: () {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 54, 14),
+ ]);
+ }
+
+ void test_functionExpression_secondParameterIsNamed() async {
+ await assertErrorsInCode('''
+void f(Stream<void> stream) {
+ stream.listen((_) {}, onError: (Object a, {StackTrace b}) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 54, 38),
+ ]);
+ }
+
+ void test_functionExpression_wrongFirstParameterType() async {
+ await assertErrorsInCode('''
+void f(Stream<void> stream) {
+ stream.listen((_) {}, onError: (String a) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 54, 22),
+ ]);
+ }
+}
+
+@reflectiveTest
+class ArgumentTypeNotAssignableToErrorHandler_StreamListenWithoutNullSafetyTest
+ extends PubPackageResolutionTest
+ with
+ ArgumentTypeNotAssignableToErrorHandler_StreamListenTestCases,
+ WithoutNullSafetyMixin {}
+
+@reflectiveTest
+class ArgumentTypeNotAssignableToErrorHandler_StreamSubscriptionOnErrorTest
+ extends PubPackageResolutionTest
+ with
+ ArgumentTypeNotAssignableToErrorHandler_StreamSubscriptionOnErrorTestCases {
+ void test_functionExpression_firstParameterIsNullableObject() async {
+ await assertNoErrorsInCode('''
+import 'dart:async';
+void f(StreamSubscription<void> subscription) {
+ subscription.onError((Object? a) {});
+}
+''');
+ }
+
+ @override
+ void test_functionExpression_secondParameterIsNamed() async {
+ await assertErrorsInCode('''
+import 'dart:async';
+void f(StreamSubscription<void> subscription) {
+ subscription.onError((Object a, {StackTrace? b}) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 92, 30),
+ ]);
+ }
+
+ void test_functionExpression_secondParameterIsNullableStackTrace() async {
+ await assertNoErrorsInCode('''
+import 'dart:async';
+void f(StreamSubscription<void> subscription) {
+ subscription.onError((Object a, StackTrace? b) {});
+}
+''');
+ }
+}
+
+mixin ArgumentTypeNotAssignableToErrorHandler_StreamSubscriptionOnErrorTestCases
+ on PubPackageResolutionTest {
+ void test_firstParameterIsDynamic() async {
+ await assertNoErrorsInCode('''
+import 'dart:async';
+void f(
+ StreamSubscription<void> subscription, void Function(dynamic a) callback) {
+ subscription.onError(callback);
+}
+''');
+ }
+
+ void test_firstParameterIsNamed() async {
+ await assertErrorsInCode('''
+import 'dart:async';
+void f(
+ StreamSubscription<void> subscription,
+ Future<int> Function({Object a}) callback) {
+ subscription.onError(callback);
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 144, 8),
+ ]);
+ }
+
+ void test_functionExpression_firstParameterIsNamed() async {
+ await assertErrorsInCode('''
+import 'dart:async';
+void f(StreamSubscription<void> subscription) {
+ subscription.onError(({Object a = 1}) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 92, 19),
+ ]);
+ }
+
+ void test_functionExpression_noParameters() async {
+ await assertErrorsInCode('''
+import 'dart:async';
+void f(StreamSubscription<void> subscription) {
+ subscription.onError(() {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 92, 5),
+ ]);
+ }
+
+ void test_functionExpression_secondParameterIsNamed() async {
+ await assertErrorsInCode('''
+import 'dart:async';
+void f(StreamSubscription<void> subscription) {
+ subscription.onError((Object a, {StackTrace b}) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 92, 29),
+ ]);
+ }
+
+ void test_functionExpression_wrongFirstParameterType() async {
+ await assertErrorsInCode('''
+import 'dart:async';
+void f(StreamSubscription<void> subscription) {
+ subscription.onError((String a) {});
+}
+''', [
+ error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 92, 13),
+ ]);
+ }
+}
+
+@reflectiveTest
+class ArgumentTypeNotAssignableToErrorHandler_StreamSubscriptionOnErrorWithoutNullSafetyTest
+ extends PubPackageResolutionTest
+ with
+ ArgumentTypeNotAssignableToErrorHandler_StreamSubscriptionOnErrorTestCases,
+ WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 8b1a3b1..11cd8e8 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -17,9 +17,9 @@
import 'ambiguous_set_or_map_literal_test.dart' as ambiguous_set_or_map_literal;
import 'annotation_on_pointer_field_test.dart' as annotation_on_pointer_field;
import 'annotation_syntax_test.dart' as annotation_syntax;
-import 'argument_type_not_assignable_catch_error_on_error_test.dart'
- as argument_type_not_assignable_catch_error_on_error;
import 'argument_type_not_assignable_test.dart' as argument_type_not_assignable;
+import 'argument_type_not_assignable_to_error_handler_test.dart'
+ as argument_type_not_assignable_to_error_handler;
import 'assert_in_redirecting_constructor_test.dart'
as assert_in_redirecting_constructor;
import 'assignment_of_do_not_store_test.dart' as assignment_of_do_not_store;
@@ -683,7 +683,7 @@
annotation_on_pointer_field.main();
annotation_syntax.main();
argument_type_not_assignable.main();
- argument_type_not_assignable_catch_error_on_error.main();
+ argument_type_not_assignable_to_error_handler.main();
assert_in_redirecting_constructor.main();
assignment_of_do_not_store.main();
assignment_to_const.main();
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 1bbce68..db471a1 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -3316,16 +3316,13 @@
//
// In the body of an `async`, `await` is generated simply as `yield`.
var gen = emitGeneratorFn((_) => []);
- // Return type of an async body is `Future<flatten(T)>`, where T is the
- // declared return type, unless T is Object. In that case the Object refers
- // to a return type of `Future<Object?>`.
- // TODO(nshahan) Use the Future type value when available on a FunctionNode.
- var declaredReturnType = function
- .computeThisFunctionType(_currentLibrary.nonNullable)
- .returnType;
- var returnType = _coreTypes.isObject(declaredReturnType)
- ? _coreTypes.objectNullableRawType
- : _types.flatten(declaredReturnType);
+ var returnType = _currentLibrary.isNonNullableByDefault
+ ? function.futureValueType
+ // Otherwise flatten the return type because futureValueType(T) is not
+ // defined for legacy libraries.
+ : _types.flatten(function
+ .computeThisFunctionType(_currentLibrary.nonNullable)
+ .returnType);
return js.call('#.async(#, #)',
[emitLibraryName(_coreTypes.asyncLibrary), _emitType(returnType), gen]);
}
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
index 1915787..699e59c 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
@@ -16,6 +16,7 @@
constantUpdate2018,
controlFlowCollections,
extensionMethods,
+ extensionTypes,
genericMetadata,
nonNullable,
nonfunctionTypeAliases,
@@ -31,6 +32,7 @@
const Version enableConstantUpdate2018Version = const Version(2, 0);
const Version enableControlFlowCollectionsVersion = const Version(2, 0);
const Version enableExtensionMethodsVersion = const Version(2, 6);
+const Version enableExtensionTypesVersion = const Version(2, 13);
const Version enableGenericMetadataVersion = const Version(2, 13);
const Version enableNonNullableVersion = const Version(2, 12);
const Version enableNonfunctionTypeAliasesVersion = const Version(2, 13);
@@ -50,6 +52,8 @@
return ExperimentalFlag.controlFlowCollections;
case "extension-methods":
return ExperimentalFlag.extensionMethods;
+ case "extension-types":
+ return ExperimentalFlag.extensionTypes;
case "generic-metadata":
return ExperimentalFlag.genericMetadata;
case "non-nullable":
@@ -75,6 +79,7 @@
ExperimentalFlag.constantUpdate2018: true,
ExperimentalFlag.controlFlowCollections: true,
ExperimentalFlag.extensionMethods: true,
+ ExperimentalFlag.extensionTypes: true,
ExperimentalFlag.genericMetadata: false,
ExperimentalFlag.nonNullable: true,
ExperimentalFlag.nonfunctionTypeAliases: false,
@@ -90,6 +95,7 @@
ExperimentalFlag.constantUpdate2018: true,
ExperimentalFlag.controlFlowCollections: true,
ExperimentalFlag.extensionMethods: false,
+ ExperimentalFlag.extensionTypes: false,
ExperimentalFlag.genericMetadata: false,
ExperimentalFlag.nonNullable: false,
ExperimentalFlag.nonfunctionTypeAliases: false,
@@ -105,6 +111,7 @@
ExperimentalFlag.constantUpdate2018: const Version(2, 0),
ExperimentalFlag.controlFlowCollections: const Version(2, 0),
ExperimentalFlag.extensionMethods: const Version(2, 6),
+ ExperimentalFlag.extensionTypes: const Version(2, 13),
ExperimentalFlag.genericMetadata: const Version(2, 13),
ExperimentalFlag.nonNullable: const Version(2, 12),
ExperimentalFlag.nonfunctionTypeAliases: const Version(2, 13),
@@ -120,6 +127,7 @@
ExperimentalFlag.constantUpdate2018: const Version(2, 0),
ExperimentalFlag.controlFlowCollections: const Version(2, 0),
ExperimentalFlag.extensionMethods: const Version(2, 6),
+ ExperimentalFlag.extensionTypes: const Version(2, 13),
ExperimentalFlag.genericMetadata: const Version(2, 13),
ExperimentalFlag.nonNullable: const Version(2, 10),
ExperimentalFlag.nonfunctionTypeAliases: const Version(2, 13),
diff --git a/runtime/vm/experimental_features.cc b/runtime/vm/experimental_features.cc
index fd0fe59..12b02ef 100644
--- a/runtime/vm/experimental_features.cc
+++ b/runtime/vm/experimental_features.cc
@@ -18,12 +18,7 @@
bool GetExperimentalFeatureDefault(ExperimentalFeature feature) {
constexpr bool kFeatureValues[] = {
- true,
- true,
- true,
- true,
- true,
- true,
+ true, true, true, true, true, true, true,
};
ASSERT(static_cast<size_t>(feature) < ARRAY_SIZE(kFeatureValues));
return kFeatureValues[static_cast<int>(feature)];
@@ -31,12 +26,10 @@
const char* GetExperimentalFeatureName(ExperimentalFeature feature) {
constexpr const char* kFeatureNames[] = {
- "non-nullable",
- "extension-methods",
- "constant-update-2018",
- "control-flow-collections",
- "set-literals",
- "spread-collections",
+ "extension-types", "non-nullable",
+ "extension-methods", "constant-update-2018",
+ "control-flow-collections", "set-literals",
+ "spread-collections",
};
ASSERT(static_cast<size_t>(feature) < ARRAY_SIZE(kFeatureNames));
return kFeatureNames[static_cast<int>(feature)];
diff --git a/runtime/vm/experimental_features.h b/runtime/vm/experimental_features.h
index 8efd29e..6418be6 100644
--- a/runtime/vm/experimental_features.h
+++ b/runtime/vm/experimental_features.h
@@ -14,6 +14,7 @@
namespace dart {
enum class ExperimentalFeature {
+ extension_types,
non_nullable,
extension_methods,
constant_update_2018,
diff --git a/tools/VERSION b/tools/VERSION
index d35a7a6..88d050c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 13
PATCH 0
-PRERELEASE 45
+PRERELEASE 46
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/experimental_features.yaml b/tools/experimental_features.yaml
index bd85a2b..e97a0a3 100644
--- a/tools/experimental_features.yaml
+++ b/tools/experimental_features.yaml
@@ -124,6 +124,10 @@
# on the command line, and will eventually be removed.
#
+ extension-types:
+ help: "Extension Types"
+ enabledIn: '2.13.0'
+
non-nullable:
help: "Non Nullable by default"
experimentalReleaseVersion: '2.10.0'