Analyzer: Report on more invlid error handlers.

Bug: https://github.com/dart-lang/sdk/issues/35825
Change-Id: I43060e9b0b0a764f14be041c5cbdf1d884d92326
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/181740
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
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/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();