Skip to content

Commit 7f6b0d8

Browse files
scheglovcommit-bot@chromium.org
authored andcommitted
Issue 42337. Report BODY_MIGHT_COMPLETE_NORMALLY for factory constructors.
Bug: #42337 Change-Id: I9209d7bf519ec61026ffe22bb05145e776e8517d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151344 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent 18b753c commit 7f6b0d8

File tree

3 files changed

+77
-17
lines changed

3 files changed

+77
-17
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
273273

274274
@override
275275
void visitConstructorDeclaration(ConstructorDeclaration node) {
276-
if (node.declaredElement.isFactory) {
276+
if (!_isNonNullableByDefault && node.declaredElement.isFactory) {
277277
if (node.body is BlockFunctionBody) {
278278
// Check the block for a return statement, if not, create the hint.
279279
if (!ExitDetector.exits(node.body)) {

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

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -414,10 +414,17 @@ class ResolverVisitor extends ScopedVisitor {
414414
}
415415

416416
if (typeSystem.isPotentiallyNonNullable(returnType)) {
417-
errorReporter.reportErrorForNode(
418-
CompileTimeErrorCode.BODY_MIGHT_COMPLETE_NORMALLY,
419-
errorNode,
420-
);
417+
if (errorNode is ConstructorDeclaration) {
418+
errorReporter.reportErrorForName(
419+
CompileTimeErrorCode.BODY_MIGHT_COMPLETE_NORMALLY,
420+
errorNode,
421+
);
422+
} else {
423+
errorReporter.reportErrorForNode(
424+
CompileTimeErrorCode.BODY_MIGHT_COMPLETE_NORMALLY,
425+
errorNode,
426+
);
427+
}
421428
}
422429
}
423430
}
@@ -807,24 +814,41 @@ class ResolverVisitor extends ScopedVisitor {
807814
@override
808815
void visitConstructorDeclaration(ConstructorDeclaration node) {
809816
ExecutableElement outerFunction = _enclosingFunction;
810-
try {
811-
_flowAnalysis?.topLevelDeclaration_enter(
812-
node, node.parameters, node.body);
813-
_flowAnalysis?.executableDeclaration_enter(node, node.parameters, false);
817+
_enclosingFunction = node.declaredElement;
818+
819+
if (_flowAnalysis != null) {
820+
_flowAnalysis.topLevelDeclaration_enter(node, node.parameters, node.body);
821+
_flowAnalysis.executableDeclaration_enter(node, node.parameters, false);
822+
} else {
814823
_promoteManager.enterFunctionBody(node.body);
815-
_enclosingFunction = node.declaredElement;
816-
FunctionType type = _enclosingFunction.type;
817-
InferenceContext.setType(node.body, type.returnType);
818-
super.visitConstructorDeclaration(node);
819-
} finally {
820-
_flowAnalysis?.executableDeclaration_exit(node.body, false);
821-
_flowAnalysis?.topLevelDeclaration_exit();
824+
}
825+
826+
var returnType = _enclosingFunction.type.returnType;
827+
InferenceContext.setType(node.body, returnType);
828+
829+
super.visitConstructorDeclaration(node);
830+
831+
if (_flowAnalysis != null) {
832+
var bodyContext = BodyInferenceContext.of(node.body);
833+
if (node.factoryKeyword != null) {
834+
checkForBodyMayCompleteNormally(
835+
returnType: bodyContext?.contextType,
836+
body: node.body,
837+
errorNode: node,
838+
);
839+
}
840+
_flowAnalysis.executableDeclaration_exit(node.body, false);
841+
_flowAnalysis.topLevelDeclaration_exit();
842+
nullSafetyDeadCodeVerifier?.flowEnd(node);
843+
} else {
822844
_promoteManager.exitFunctionBody();
823-
_enclosingFunction = outerFunction;
824845
}
846+
825847
ConstructorElementImpl constructor = node.declaredElement;
826848
constructor.constantInitializers =
827849
_createCloner().cloneNodeList(node.initializers);
850+
851+
_enclosingFunction = outerFunction;
828852
}
829853

830854
@override

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,26 @@ class BodyMayCompleteNormallyTest extends DriverResolutionTest {
2222
..contextFeatures = FeatureSet.forTesting(
2323
sdkVersion: '2.7.0', additionalFeatures: [Feature.non_nullable]);
2424

25+
test_factoryConstructor_named_blockBody() async {
26+
await assertErrorsInCode(r'''
27+
class A {
28+
factory A.named() {}
29+
}
30+
''', [
31+
error(CompileTimeErrorCode.BODY_MIGHT_COMPLETE_NORMALLY, 20, 7),
32+
]);
33+
}
34+
35+
test_factoryConstructor_unnamed_blockBody() async {
36+
await assertErrorsInCode(r'''
37+
class A {
38+
factory A() {}
39+
}
40+
''', [
41+
error(CompileTimeErrorCode.BODY_MIGHT_COMPLETE_NORMALLY, 20, 1),
42+
]);
43+
}
44+
2545
test_function_future_int_blockBody_async() async {
2646
await assertErrorsInCode(r'''
2747
Future<int> foo() async {}
@@ -219,6 +239,22 @@ main() {
219239
''');
220240
}
221241

242+
test_generativeConstructor_blockBody() async {
243+
await assertNoErrorsInCode(r'''
244+
class A {
245+
A() {}
246+
}
247+
''');
248+
}
249+
250+
test_generativeConstructor_emptyBody() async {
251+
await assertNoErrorsInCode(r'''
252+
class A {
253+
A();
254+
}
255+
''');
256+
}
257+
222258
test_method_future_int_blockBody_async() async {
223259
await assertErrorsInCode(r'''
224260
class A {

0 commit comments

Comments
 (0)