diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart index 95ce3fd3aa2e..04edcc1e19f1 100644 --- a/pkg/analyzer/lib/error/error.dart +++ b/pkg/analyzer/lib/error/error.dart @@ -482,7 +482,7 @@ const List errorCodeValues = [ 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 70494074bd43..3621e3bdbf9e 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 @@ class HintCode extends AnalyzerErrorCode { * 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 b3136ff5745f..9b54f4e49058 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/element/type_system.dart'; 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 @@ class BestPracticesVerifier extends RecursiveAstVisitor { final MustCallSuperVerifier _mustCallSuperVerifier; - final CatchErrorVerifier _catchErrorVerifier; + final ErrorHandlerVerifier _errorHandlerVerifier; /// The [WorkspacePackage] in which [_currentLibrary] is declared. final WorkspacePackage? _workspacePackage; @@ -109,8 +109,8 @@ class BestPracticesVerifier extends RecursiveAstVisitor { _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 @@ class BestPracticesVerifier extends RecursiveAstVisitor { 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 00d227dd38c9..000000000000 --- 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 { - 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 000000000000..070647419745 --- /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.catchError] must return `FutureOr`, and any return statements in a +/// function literal must return a value of type `FutureOr`. +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() + .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.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() + .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 { + 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 74bcc945c127..e588646c681a 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 @@ abstract class Future { Future catchError(Function onError, {bool test(Object error)}); - Future then(FutureOr onValue(T value)); + Future then(FutureOr onValue(T value), {Function? onError}); Future whenComplete(action()); @@ -90,6 +90,8 @@ abstract class Stream { StreamSubscription listen(void onData(T event)?, {Function? onError, void onDone()?, bool? cancelOnError}); + + Stream handleError(Function onError, {bool test(dynamic error)}); } abstract class StreamIterator {} 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 ceb07067c792..000000000000 --- 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 future, Future Function(dynamic a) callback) { - future.catchError(callback); -} -'''); - } - - void test_firstParameterIsNamed() async { - await assertErrorsInCode(''' -void f(Future future, Future 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 future, Future Function([Object a]) callback) { - future.catchError(callback); -} -'''); - } - - void test_functionExpression_firstParameterIsDynamic() async { - await assertNoErrorsInCode(''' -void f(Future future) { - future.catchError((dynamic a) {}); -} -'''); - } - - void test_functionExpression_firstParameterIsImplicit() async { - await assertNoErrorsInCode(''' -void f(Future future) { - future.catchError((a) {}); -} -'''); - } - - void test_functionExpression_firstParameterIsNamed() async { - await assertErrorsInCode(''' -void f(Future 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 future) { - future.catchError(([Object a = 1]) {}); -} -'''); - } - - void test_functionExpression_firstParameterIsVar() async { - await assertNoErrorsInCode(''' -void f(Future future) { - future.catchError((var a) {}); -} -'''); - } - - void test_functionExpression_noParameters() async { - await assertErrorsInCode(''' -void f(Future 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 future) { - future.catchError((Object a, dynamic b) {}); -} -'''); - } - - void test_functionExpression_secondParameterIsImplicit() async { - await assertNoErrorsInCode(''' -void f(Future future) { - future.catchError((Object a, b) {}); -} -'''); - } - - void test_functionExpression_secondParameterIsNamed() async { - await assertErrorsInCode(''' -void f(Future 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 future) { - future.catchError((Object a, [StackTrace st]) {}); -} -'''); - } - - void test_functionExpression_secondParameterIsVar() async { - await assertNoErrorsInCode(''' -void f(Future future) { - future.catchError((Object a, var b) {}); -} -'''); - } - - void test_functionExpression_tooManyParameters() async { - await assertErrorsInCode(''' -void f(Future 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 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 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 future, Future 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 future, Future Function(Object, StackTrace) callback) { - future.catchError(callback); -} -'''); - } - - void test_secondParameterIsDynamic() async { - await assertNoErrorsInCode(''' -void f(Future future, Future Function(Object a, dynamic b) callback) { - future.catchError(callback); -} -'''); - } - - void test_secondParameterIsNamed() async { - await assertErrorsInCode(''' -void f(Future future, Future 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 future, Future 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 future, Future 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 future, Future 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 future) { - future.catchError((Object? a) {}); -} -'''); - } - - @override - void test_functionExpression_secondParameterIsNamed() async { - await assertErrorsInCode(''' -void f(Future 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 future) { - future.catchError((Object a, StackTrace? b) {}); -} -'''); - } - - @override - void test_functionExpression_secondParameterIsOptional() async { - await assertNoErrorsInCode(''' -void f(Future 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 000000000000..eaeddb5ea27c --- /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 future) { + future.catchError((Object? a) {}); +} +'''); + } + + @override + void test_functionExpression_secondParameterIsNamed() async { + await assertErrorsInCode(''' +void f(Future 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 future) { + future.catchError((Object a, StackTrace? b) {}); +} +'''); + } +} + +mixin ArgumentTypeNotAssignableToErrorHandler_FutureCatchErrorTestCases + on PubPackageResolutionTest { + void test_firstParameterIsDynamic() async { + await assertNoErrorsInCode(''' +void f(Future future, Future Function(dynamic a) callback) { + future.catchError(callback); +} +'''); + } + + void test_firstParameterIsNamed() async { + await assertErrorsInCode(''' +void f(Future future, Future 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 future, Future Function([Object a]) callback) { + future.catchError(callback); +} +'''); + } + + void test_functionExpression_firstParameterIsDynamic() async { + await assertNoErrorsInCode(''' +void f(Future future) { + future.catchError((dynamic a) {}); +} +'''); + } + + void test_functionExpression_firstParameterIsImplicit() async { + await assertNoErrorsInCode(''' +void f(Future future) { + future.catchError((a) {}); +} +'''); + } + + void test_functionExpression_firstParameterIsNamed() async { + await assertErrorsInCode(''' +void f(Future 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 future) { + future.catchError(([Object a = 1]) {}); +} +'''); + } + + void test_functionExpression_firstParameterIsVar() async { + await assertNoErrorsInCode(''' +void f(Future future) { + future.catchError((var a) {}); +} +'''); + } + + void test_functionExpression_noParameters() async { + await assertErrorsInCode(''' +void f(Future future) { + future.catchError(() {}); +} +''', [ + error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 50, 5), + ]); + } + + void test_functionExpression_secondParameterIsDynamic() async { + await assertNoErrorsInCode(''' +void f(Future future) { + future.catchError((Object a, dynamic b) {}); +} +'''); + } + + void test_functionExpression_secondParameterIsImplicit() async { + await assertNoErrorsInCode(''' +void f(Future future) { + future.catchError((Object a, b) {}); +} +'''); + } + + void test_functionExpression_secondParameterIsNamed() async { + await assertErrorsInCode(''' +void f(Future 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 future) { + future.catchError((Object a, var b) {}); +} +'''); + } + + void test_functionExpression_tooManyParameters() async { + await assertErrorsInCode(''' +void f(Future 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 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 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 future, Future 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 future, Future Function(Object, StackTrace) callback) { + future.catchError(callback); +} +'''); + } + + void test_secondParameterIsDynamic() async { + await assertNoErrorsInCode(''' +void f(Future future, Future Function(Object a, dynamic b) callback) { + future.catchError(callback); +} +'''); + } + + void test_secondParameterIsNamed() async { + await assertErrorsInCode(''' +void f(Future future, Future 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 future, Future 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 future, Future 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 future, Future 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 future) { + future.then((_) {}, onError: (Object? a) {}); +} +'''); + } + + @override + void test_functionExpression_secondParameterIsNamed() async { + await assertErrorsInCode(''' +void f(Future 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 future) { + future.then((_) {}, onError: (Object a, StackTrace? b) {}); +} +'''); + } +} + +mixin ArgumentTypeNotAssignableToErrorHandler_FutureThenTestCases + on PubPackageResolutionTest { + void test_firstParameterIsDynamic() async { + await assertNoErrorsInCode(''' +void f(Future future, void Function(dynamic a) callback) { + future.then((_) {}, onError: callback); +} +'''); + } + + void test_firstParameterIsNamed() async { + await assertErrorsInCode(''' +void f(Future future, Future 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 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 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 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 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 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 stream) { + stream.handleError((Object? a) {}); +} +'''); + } + + @override + void test_functionExpression_secondParameterIsNamed() async { + await assertErrorsInCode(''' +void f(Stream 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 stream) { + stream.handleError((Object a, StackTrace? b) {}); +} +'''); + } +} + +mixin ArgumentTypeNotAssignableToErrorHandler_StreamHandleErrorTestCases + on PubPackageResolutionTest { + void test_firstParameterIsDynamic() async { + await assertNoErrorsInCode(''' +void f(Stream stream, void Function(dynamic a) callback) { + stream.handleError(callback); +} +'''); + } + + void test_firstParameterIsNamed() async { + await assertErrorsInCode(''' +void f(Stream stream, Future 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 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 stream) { + stream.handleError(() {}); +} +''', [ + error(HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER, 51, 5), + ]); + } + + void test_functionExpression_secondParameterIsNamed() async { + await assertErrorsInCode(''' +void f(Stream 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 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 stream) { + stream.listen((_) {}, onError: (Object? a) {}); +} +'''); + } + + @override + void test_functionExpression_secondParameterIsNamed() async { + await assertErrorsInCode(''' +void f(Stream 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 stream) { + stream.listen((_) {}, onError: (Object a, StackTrace? b) {}); +} +'''); + } +} + +mixin ArgumentTypeNotAssignableToErrorHandler_StreamListenTestCases + on PubPackageResolutionTest { + void test_firstParameterIsDynamic() async { + await assertNoErrorsInCode(''' +void f(Stream stream, void Function(dynamic a) callback) { + stream.listen((_) {}, onError: callback); +} +'''); + } + + void test_firstParameterIsNamed() async { + await assertErrorsInCode(''' +void f(Stream stream, Future 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 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 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 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 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 subscription) { + subscription.onError((Object? a) {}); +} +'''); + } + + @override + void test_functionExpression_secondParameterIsNamed() async { + await assertErrorsInCode(''' +import 'dart:async'; +void f(StreamSubscription 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 subscription) { + subscription.onError((Object a, StackTrace? b) {}); +} +'''); + } +} + +mixin ArgumentTypeNotAssignableToErrorHandler_StreamSubscriptionOnErrorTestCases + on PubPackageResolutionTest { + void test_firstParameterIsDynamic() async { + await assertNoErrorsInCode(''' +import 'dart:async'; +void f( + StreamSubscription subscription, void Function(dynamic a) callback) { + subscription.onError(callback); +} +'''); + } + + void test_firstParameterIsNamed() async { + await assertErrorsInCode(''' +import 'dart:async'; +void f( + StreamSubscription subscription, + Future 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 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 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 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 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 8b1a3b156f91..11cd8e8737a3 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_import_test.dart' as ambiguous_import; 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 @@ main() { 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();