Skip to content

Commit 294a2cf

Browse files
srawlinscommit-bot@chromium.org
authored andcommitted
Analyzer: print constructor name when constructor returns invalid type
Fixes #27387 Change-Id: I8ce81bab4c4601c5157977d3f43f73903dae7f8b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151200 Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent d870463 commit 294a2cf

File tree

7 files changed

+78
-4
lines changed

7 files changed

+78
-4
lines changed

pkg/analyzer/lib/error/error.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,7 @@ const List<ErrorCode> errorCodeValues = [
706706
// ignore: deprecated_member_use_from_same_package
707707
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
708708
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE,
709+
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR,
709710
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION,
710711
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_METHOD,
711712
StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND,

pkg/analyzer/lib/src/error/codes.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7340,6 +7340,20 @@ class StaticTypeWarningCode extends AnalyzerErrorCode {
73407340
"context.",
73417341
hasPublishedDocs: true);
73427342

7343+
/**
7344+
* Parameters:
7345+
* 0: the return type as declared in the return statement
7346+
* 1: the expected return type as defined by the enclosing class
7347+
* 2: the name of the constructor
7348+
*/
7349+
static const StaticTypeWarningCode RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR =
7350+
StaticTypeWarningCodeWithUniqueName(
7351+
'RETURN_OF_INVALID_TYPE',
7352+
'StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR',
7353+
"A value of type '{0}' can't be returned from constructor '{2}' "
7354+
"because it has a return type of '{1}'.",
7355+
hasPublishedDocs: true);
7356+
73437357
/**
73447358
* Parameters:
73457359
* 0: the return type as declared in the return statement

pkg/analyzer/lib/src/error/return_type_verifier.dart

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,19 @@ class ReturnTypeVerifier {
141141

142142
void reportTypeError() {
143143
String displayName = enclosingExecutable.element.displayName;
144-
if (displayName.isEmpty) {
144+
if (enclosingExecutable.isConstructor) {
145+
var constructor = enclosingExecutable.element as ConstructorElement;
146+
var className = constructor.enclosingElement.displayName;
147+
var constructorBaseName = constructor.displayName;
148+
var constructorName = constructorBaseName.isEmpty
149+
? className
150+
: '$className.$constructorBaseName';
151+
_errorReporter.reportErrorForNode(
152+
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR,
153+
expression,
154+
[S, T, constructorName],
155+
);
156+
} else if (displayName.isEmpty) {
145157
_errorReporter.reportErrorForNode(
146158
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE,
147159
expression,
@@ -237,7 +249,19 @@ class ReturnTypeVerifier {
237249

238250
void reportTypeError() {
239251
String displayName = enclosingExecutable.element.displayName;
240-
if (displayName.isEmpty) {
252+
if (enclosingExecutable.isConstructor) {
253+
var constructor = enclosingExecutable.element as ConstructorElement;
254+
var className = constructor.enclosingElement.displayName;
255+
var constructorBaseName = constructor.displayName;
256+
var constructorName = constructorBaseName.isEmpty
257+
? className
258+
: '$className.$constructorBaseName';
259+
_errorReporter.reportErrorForNode(
260+
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR,
261+
expression,
262+
[S, T, constructorName],
263+
);
264+
} else if (displayName.isEmpty) {
241265
_errorReporter.reportErrorForNode(
242266
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE,
243267
expression,

pkg/analyzer/lib/src/generated/error_verifier.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ class EnclosingExecutableContext {
7171

7272
EnclosingExecutableContext.empty() : this(null);
7373

74+
bool get isConstructor => element is ConstructorElement;
75+
7476
bool get isMethod => element is MethodElement;
7577

7678
bool get isSynchronous => !isAsynchronous;

pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,39 @@ main() {
1717

1818
@reflectiveTest
1919
class ReturnOfInvalidTypeTest extends DriverResolutionTest {
20+
test_closure() async {
21+
await assertErrorsInCode('''
22+
typedef Td = int Function();
23+
Td f() {
24+
return () => "hello";
25+
}
26+
''', [
27+
error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE, 53, 7),
28+
]);
29+
}
30+
31+
test_factoryConstructor_named() async {
32+
await assertErrorsInCode('''
33+
class C {
34+
factory C.named() => 7;
35+
}
36+
''', [
37+
error(
38+
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR, 33, 1),
39+
]);
40+
}
41+
42+
test_factoryConstructor_unnamed() async {
43+
await assertErrorsInCode('''
44+
class C {
45+
factory C() => 7;
46+
}
47+
''', [
48+
error(
49+
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR, 27, 1),
50+
]);
51+
}
52+
2053
test_function_async_block__to_Future_void() async {
2154
await assertNoErrorsInCode(r'''
2255
Future<void> f1() async {}

tests/language/factory/return_type_checked_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import "package:expect/expect.dart";
77
class A {
88
factory A() => 42;
99
// ^^
10-
// [analyzer] STATIC_TYPE_WARNING.RETURN_OF_INVALID_TYPE_FROM_CLOSURE
10+
// [analyzer] STATIC_TYPE_WARNING.RETURN_OF_INVALID_TYPE
1111
// [cfe] A value of type 'int' can't be assigned to a variable of type 'A'.
1212
}
1313

tests/language_2/factory/return_type_checked_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import "package:expect/expect.dart";
77
class A {
88
factory A() => 42;
99
// ^^
10-
// [analyzer] STATIC_TYPE_WARNING.RETURN_OF_INVALID_TYPE_FROM_CLOSURE
10+
// [analyzer] STATIC_TYPE_WARNING.RETURN_OF_INVALID_TYPE
1111
// [cfe] A value of type 'int' can't be assigned to a variable of type 'A'.
1212
}
1313

0 commit comments

Comments
 (0)