Issue 54485. Report error when external constructor has a field formal parameter.

Bug: https://github.com/dart-lang/sdk/issues/54485
Change-Id: Id2cec10b1c8bdb7bba5d608f28a3b55b8f4146ad
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/344180
Reviewed-by: Kallen Tu <kallentu@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2024-01-03 19:59:53 +00:00 committed by Commit Queue
parent af8d70367d
commit 8898abbc7e
8 changed files with 96 additions and 2 deletions

View file

@ -4628,7 +4628,7 @@ const Code<Null> codeExternalConstructorWithFieldInitializers =
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageExternalConstructorWithFieldInitializers =
const MessageCode("ExternalConstructorWithFieldInitializers",
analyzerCodes: <String>["EXTERNAL_CONSTRUCTOR_WITH_FIELD_INITIALIZERS"],
index: 178,
problemMessage: r"""An external constructor can't initialize fields.""",
correctionMessage:
r"""Try removing the field initializers, or removing the keyword 'external'.""");

View file

@ -2800,6 +2800,10 @@ ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY:
status: needsFix
notes: |-
Remove the `external` keyword.
ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_FIELD_INITIALIZERS:
status: needsFix
notes: |-
Remove the `external` keyword or remove the initializers.
ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_INITIALIZER:
status: needsFix
notes: |-

View file

@ -199,6 +199,7 @@ final fastaAnalyzerErrorCodes = <ErrorCode?>[
ParserErrorCode.EXTRANEOUS_MODIFIER_IN_PRIMARY_CONSTRUCTOR,
ParserErrorCode.ABSTRACT_FINAL_BASE_CLASS,
ParserErrorCode.ABSTRACT_FINAL_INTERFACE_CLASS,
ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_FIELD_INITIALIZERS,
];
class ParserErrorCode extends ErrorCode {
@ -817,6 +818,15 @@ class ParserErrorCode extends ErrorCode {
"'external'.",
);
static const ParserErrorCode EXTERNAL_CONSTRUCTOR_WITH_FIELD_INITIALIZERS =
ParserErrorCode(
'EXTERNAL_CONSTRUCTOR_WITH_FIELD_INITIALIZERS',
"An external constructor can't initialize fields.",
correctionMessage:
"Try removing the field initializers, or removing the keyword "
"'external'.",
);
static const ParserErrorCode EXTERNAL_CONSTRUCTOR_WITH_INITIALIZER =
ParserErrorCode(
'EXTERNAL_CONSTRUCTOR_WITH_INITIALIZER',

View file

@ -735,6 +735,7 @@ const List<ErrorCode> errorCodeValues = [
ParserErrorCode.EXTENSION_TYPE_WITH,
ParserErrorCode.EXTERNAL_CLASS,
ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY,
ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_FIELD_INITIALIZERS,
ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_INITIALIZER,
ParserErrorCode.EXTERNAL_ENUM,
ParserErrorCode.EXTERNAL_FACTORY_REDIRECTION,

View file

@ -5660,6 +5660,18 @@ class AstBuilder extends StackListener {
handleRecoverableError(
messageConstConstructorWithBody, bodyToken, bodyToken);
}
if (modifiers?.externalKeyword != null) {
for (final formalParameter in parameters.parameters) {
if (formalParameter is FieldFormalParameterImpl) {
errorReporter.errorReporter?.reportErrorForToken(
ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_FIELD_INITIALIZERS,
formalParameter.thisKeyword,
);
}
}
}
var constructor = ConstructorDeclarationImpl(
comment: comment,
metadata: metadata,

View file

@ -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/dart/error/syntactic_errors.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../diagnostics/parser_diagnostics.dart';
@ -43,6 +44,69 @@ ClassDeclaration
body: EmptyFunctionBody
semicolon: ;
rightBracket: }
''');
}
test_constructor_external_fieldFormalParameter() {
final parseResult = parseStringWithErrors(r'''
class A {
final int f;
external A(this.f);
}
''');
parseResult.assertErrors([
error(
ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_FIELD_INITIALIZERS, 38, 4),
]);
final node = parseResult.findNode.singleConstructorDeclaration;
assertParsedNodeText(node, r'''
ConstructorDeclaration
externalKeyword: external
returnType: SimpleIdentifier
token: A
parameters: FormalParameterList
leftParenthesis: (
parameter: FieldFormalParameter
thisKeyword: this
period: .
name: f
rightParenthesis: )
body: EmptyFunctionBody
semicolon: ;
''');
}
test_constructor_external_fieldInitializer() {
final parseResult = parseStringWithErrors(r'''
class A {
final int f;
external A() : f = 0;
}
''');
parseResult.assertErrors([
error(ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_INITIALIZER, 40, 1),
]);
final node = parseResult.findNode.singleConstructorDeclaration;
assertParsedNodeText(node, r'''
ConstructorDeclaration
externalKeyword: external
returnType: SimpleIdentifier
token: A
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
separator: :
initializers
ConstructorFieldInitializer
fieldName: SimpleIdentifier
token: f
equals: =
expression: IntegerLiteral
literal: 0
body: EmptyFunctionBody
semicolon: ;
''');
}
}

View file

@ -1270,9 +1270,10 @@ ExternalConstructorWithBody:
- "class C { external C() {} }"
ExternalConstructorWithFieldInitializers:
index: 178
problemMessage: "An external constructor can't initialize fields."
correctionMessage: "Try removing the field initializers, or removing the keyword 'external'."
analyzerCode: EXTERNAL_CONSTRUCTOR_WITH_FIELD_INITIALIZERS
analyzerCode: ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_FIELD_INITIALIZERS
ExternalFactoryWithBody:
index: 86

View file

@ -56,6 +56,8 @@ class Foo {
// ^
// [cfe] An external or native method can't have a body.
external Foo.n24(this.x);
// ^^^^
// [analyzer] SYNTACTIC_ERROR.EXTERNAL_CONSTRUCTOR_WITH_FIELD_INITIALIZERS
// ^
// [cfe] An external constructor can't initialize fields.
external factory Foo.n25(val) = Bar;