mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 09:31:58 +00:00
Analyzer: print constructor name when constructor returns invalid type
Fixes https://github.com/dart-lang/sdk/issues/27387 Change-Id: I8ce81bab4c4601c5157977d3f43f73903dae7f8b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151200 Commit-Queue: Samuel Rawlins <srawlins@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
d87046342f
commit
294a2cffd1
|
@ -706,6 +706,7 @@ const List<ErrorCode> errorCodeValues = [
|
|||
// ignore: deprecated_member_use_from_same_package
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE,
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR,
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION,
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_METHOD,
|
||||
StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND,
|
||||
|
|
|
@ -7340,6 +7340,20 @@ class StaticTypeWarningCode extends AnalyzerErrorCode {
|
|||
"context.",
|
||||
hasPublishedDocs: true);
|
||||
|
||||
/**
|
||||
* Parameters:
|
||||
* 0: the return type as declared in the return statement
|
||||
* 1: the expected return type as defined by the enclosing class
|
||||
* 2: the name of the constructor
|
||||
*/
|
||||
static const StaticTypeWarningCode RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR =
|
||||
StaticTypeWarningCodeWithUniqueName(
|
||||
'RETURN_OF_INVALID_TYPE',
|
||||
'StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR',
|
||||
"A value of type '{0}' can't be returned from constructor '{2}' "
|
||||
"because it has a return type of '{1}'.",
|
||||
hasPublishedDocs: true);
|
||||
|
||||
/**
|
||||
* Parameters:
|
||||
* 0: the return type as declared in the return statement
|
||||
|
|
|
@ -141,7 +141,19 @@ class ReturnTypeVerifier {
|
|||
|
||||
void reportTypeError() {
|
||||
String displayName = enclosingExecutable.element.displayName;
|
||||
if (displayName.isEmpty) {
|
||||
if (enclosingExecutable.isConstructor) {
|
||||
var constructor = enclosingExecutable.element as ConstructorElement;
|
||||
var className = constructor.enclosingElement.displayName;
|
||||
var constructorBaseName = constructor.displayName;
|
||||
var constructorName = constructorBaseName.isEmpty
|
||||
? className
|
||||
: '$className.$constructorBaseName';
|
||||
_errorReporter.reportErrorForNode(
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR,
|
||||
expression,
|
||||
[S, T, constructorName],
|
||||
);
|
||||
} else if (displayName.isEmpty) {
|
||||
_errorReporter.reportErrorForNode(
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE,
|
||||
expression,
|
||||
|
@ -237,7 +249,19 @@ class ReturnTypeVerifier {
|
|||
|
||||
void reportTypeError() {
|
||||
String displayName = enclosingExecutable.element.displayName;
|
||||
if (displayName.isEmpty) {
|
||||
if (enclosingExecutable.isConstructor) {
|
||||
var constructor = enclosingExecutable.element as ConstructorElement;
|
||||
var className = constructor.enclosingElement.displayName;
|
||||
var constructorBaseName = constructor.displayName;
|
||||
var constructorName = constructorBaseName.isEmpty
|
||||
? className
|
||||
: '$className.$constructorBaseName';
|
||||
_errorReporter.reportErrorForNode(
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR,
|
||||
expression,
|
||||
[S, T, constructorName],
|
||||
);
|
||||
} else if (displayName.isEmpty) {
|
||||
_errorReporter.reportErrorForNode(
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE,
|
||||
expression,
|
||||
|
|
|
@ -71,6 +71,8 @@ class EnclosingExecutableContext {
|
|||
|
||||
EnclosingExecutableContext.empty() : this(null);
|
||||
|
||||
bool get isConstructor => element is ConstructorElement;
|
||||
|
||||
bool get isMethod => element is MethodElement;
|
||||
|
||||
bool get isSynchronous => !isAsynchronous;
|
||||
|
|
|
@ -17,6 +17,39 @@ main() {
|
|||
|
||||
@reflectiveTest
|
||||
class ReturnOfInvalidTypeTest extends DriverResolutionTest {
|
||||
test_closure() async {
|
||||
await assertErrorsInCode('''
|
||||
typedef Td = int Function();
|
||||
Td f() {
|
||||
return () => "hello";
|
||||
}
|
||||
''', [
|
||||
error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE, 53, 7),
|
||||
]);
|
||||
}
|
||||
|
||||
test_factoryConstructor_named() async {
|
||||
await assertErrorsInCode('''
|
||||
class C {
|
||||
factory C.named() => 7;
|
||||
}
|
||||
''', [
|
||||
error(
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR, 33, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_factoryConstructor_unnamed() async {
|
||||
await assertErrorsInCode('''
|
||||
class C {
|
||||
factory C() => 7;
|
||||
}
|
||||
''', [
|
||||
error(
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR, 27, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_function_async_block__to_Future_void() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
Future<void> f1() async {}
|
||||
|
|
|
@ -7,7 +7,7 @@ import "package:expect/expect.dart";
|
|||
class A {
|
||||
factory A() => 42;
|
||||
// ^^
|
||||
// [analyzer] STATIC_TYPE_WARNING.RETURN_OF_INVALID_TYPE_FROM_CLOSURE
|
||||
// [analyzer] STATIC_TYPE_WARNING.RETURN_OF_INVALID_TYPE
|
||||
// [cfe] A value of type 'int' can't be assigned to a variable of type 'A'.
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import "package:expect/expect.dart";
|
|||
class A {
|
||||
factory A() => 42;
|
||||
// ^^
|
||||
// [analyzer] STATIC_TYPE_WARNING.RETURN_OF_INVALID_TYPE_FROM_CLOSURE
|
||||
// [analyzer] STATIC_TYPE_WARNING.RETURN_OF_INVALID_TYPE
|
||||
// [cfe] A value of type 'int' can't be assigned to a variable of type 'A'.
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue