Augment. Don't report an error in the parser when a factory constructor has no body.

Change-Id: Ia6df688d4c13bb1ef8b73a0bf810857a1f0fe5b2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/502300
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov
2026-05-13 11:15:09 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 782c4555b4
commit 2c5f7e1ab0
6 changed files with 120 additions and 6 deletions
@@ -6189,7 +6189,7 @@ class Parser {
token = parseFunctionBody(
token,
/* ofFunctionExpression = */ false,
/* allowAbstract = */ false,
/* allowAbstract = */ _isAugmentationsFeatureEnabled,
);
}
switch (kind) {
@@ -1335,6 +1335,7 @@ class C {
]);
}
@FailingTest() // TODO(scheglov): implement augmentation
void test_factoryWithoutBody() {
var parseResult = parseStringWithErrors(r'''
class C {
@@ -1344,6 +1345,16 @@ class C {
parseResult.assertErrors([error(diag.missingFunctionBody, 23, 1)]);
}
void test_factoryWithoutBody_language305() {
var parseResult = parseStringWithErrors(r'''
// @dart = 3.5
class C {
factory C();
}
''');
parseResult.assertErrors([error(diag.missingFunctionBody, 38, 1)]);
}
void test_fieldInitializerOutsideConstructor() {
var parseResult = parseStringWithErrors(r'''
class C {
@@ -879,6 +879,53 @@ ConstructorDeclaration
''');
}
test_constructor_typeName_factory_unnamed_noBody() {
var parseResult = parseStringWithErrors(r'''
class A {
factory A();
}
''');
parseResult.assertExpectedDiagnostics();
var node = parseResult.findNode.singleConstructorDeclaration;
assertParsedNodeText(node, r'''
ConstructorDeclaration
factoryKeyword: factory
typeName: SimpleIdentifier
token: A
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: EmptyFunctionBody
semicolon: ;
''');
}
test_constructor_typeName_factory_unnamed_noBody_language305() {
var parseResult = parseStringWithErrors(r'''
// @dart = 3.5
class A {
factory A();
// ^
// [diag.missingFunctionBody] A function body must be provided.
}
''');
parseResult.assertExpectedDiagnostics();
var node = parseResult.findNode.singleConstructorDeclaration;
assertParsedNodeText(node, r'''
ConstructorDeclaration
factoryKeyword: factory
typeName: SimpleIdentifier
token: A
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: EmptyFunctionBody
semicolon: ;
''');
}
test_constructor_typeName_factory_unnamed_withoutPrimaryConstructors() {
var parseResult = parseStringWithErrors(r'''
// @dart = 3.10
@@ -55,7 +55,6 @@ class A {
);
}
@FailingTest() // TODO(scheglov): implement augmentation
test_secondary_factory_introductory_noBody() async {
await assertNoErrorsInCode(r'''
class A {
@@ -2,6 +2,7 @@
// 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/diagnostic/diagnostic.dart' as diag;
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../dart/resolution/context_collection_resolution.dart';
@@ -109,6 +110,7 @@ class C {
''');
}
@SkippedTest() // TODO(scheglov): implement augmentation
test_class_secondaryConstructor_constFactory_emptyBody() async {
await resolveTestCodeWithDiagnostics(r'''
class C {
@@ -121,6 +123,18 @@ class C {
''');
}
test_class_secondaryConstructor_constFactory_emptyBody_language305() async {
await assertErrorsInCode(
r'''
// @dart = 3.5
class C {
const factory C();
}
''',
[error(diag.constFactory, 27, 5), error(diag.missingFunctionBody, 44, 1)],
);
}
test_class_secondaryConstructor_constFactory_expressionBody() async {
await resolveTestCodeWithDiagnostics(r'''
class C {
@@ -470,6 +484,7 @@ enum E {
''');
}
@SkippedTest() // TODO(scheglov): implement augmentation
test_enum_secondaryConstructor_constFactory_emptyBody() async {
await resolveTestCodeWithDiagnostics(r'''
enum E {
@@ -484,6 +499,20 @@ enum E {
''');
}
test_enum_secondaryConstructor_constFactory_emptyBody_language305() async {
await assertErrorsInCode(
r'''
// @dart = 3.5
enum E {
v;
const E();
const factory E.named();
}
''',
[error(diag.constFactory, 44, 5), error(diag.missingFunctionBody, 67, 1)],
);
}
test_enum_secondaryConstructor_constFactory_expressionBody() async {
await resolveTestCodeWithDiagnostics(r'''
enum E {
@@ -804,6 +833,7 @@ extension type const E(int it) {
''');
}
@SkippedTest() // TODO(scheglov): implement augmentation
test_extensionType_secondaryConstructor_constFactory_emptyBody() async {
await resolveTestCodeWithDiagnostics(r'''
extension type const E(int it) {
@@ -816,6 +846,18 @@ extension type const E(int it) {
''');
}
test_extensionType_secondaryConstructor_constFactory_emptyBody_language305() async {
await assertErrorsInCode(
r'''
// @dart = 3.5
extension type const E(int it) {
const factory E.named();
}
''',
[error(diag.constFactory, 50, 5), error(diag.missingFunctionBody, 73, 1)],
);
}
test_extensionType_secondaryConstructor_constFactory_expressionBody() async {
await resolveTestCodeWithDiagnostics(r'''
extension type const E(int it) {
@@ -2,6 +2,7 @@
// 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/diagnostic/diagnostic.dart' as diag;
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../dart/resolution/context_collection_resolution.dart';
@@ -26,20 +27,34 @@ class A {
}
test_class_fieldFormalParameter_functionTyped() async {
// TODO(srawlins): Only report one error. Theoretically change Fasta to
// report "Field initializer in factory constructor" as a parse error.
await resolveTestCodeWithDiagnostics(r'''
class A {
int Function()? x;
factory A(int this.x());
// ^^^^^^^^^^^^
// [diag.fieldInitializerFactoryConstructor] Initializing formal parameters can't be used in factory constructors.
// ^
// [diag.missingFunctionBody] A function body must be provided.
}
''');
}
test_class_fieldFormalParameter_functionTyped_language305() async {
await assertErrorsInCode(
r'''
// @dart = 3.5
class A {
int Function()? x;
factory A(int this.x());
}
''',
[
// TODO(srawlins): Only report one error. Theoretically change Fasta to
// report "Field initializer in factory constructor" as a parse error.
error(diag.fieldInitializerFactoryConstructor, 58, 12),
error(diag.missingFunctionBody, 71, 1),
],
);
}
test_enum_fieldFormalParameter() async {
await resolveTestCodeWithDiagnostics(r'''
enum E {