Abstract field support: do not allow abstract fields to be late or static.

Although these error conditions are not reported by the parser, the
language grammar does not permit them, so from a customer perspective
they are parser errors.  Accordingly, they have been assigned
ParserErrorCodes and reported by the AstBuilder, as we do for other
similar errors.

Change-Id: I79d0ad1dcad518981b8b649c117df326279008f7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/157800
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Paul Berry 2020-08-10 19:27:13 +00:00 committed by commit-bot@chromium.org
parent 8405d7c8e3
commit 87f0d5d9dc
8 changed files with 74 additions and 5 deletions

View file

@ -89,6 +89,7 @@ const Code<Null> codeAbstractLateField = messageAbstractLateField;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageAbstractLateField = const MessageCode(
"AbstractLateField",
index: 108,
message: r"""Abstract fields cannot be late.""",
tip: r"""Try removing the 'abstract' or 'late' keyword.""");
@ -134,6 +135,7 @@ const Code<Null> codeAbstractStaticField = messageAbstractStaticField;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageAbstractStaticField = const MessageCode(
"AbstractStaticField",
index: 107,
message: r"""Static fields can't be declared 'abstract'.""",
tip: r"""Try removing the 'abstract' or 'static' keyword.""");

View file

@ -570,6 +570,8 @@ const List<ErrorCode> errorCodeValues = [
ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE,
ParserErrorCode.ABSTRACT_CLASS_MEMBER,
ParserErrorCode.ABSTRACT_ENUM,
ParserErrorCode.ABSTRACT_LATE_FIELD,
ParserErrorCode.ABSTRACT_STATIC_FIELD,
ParserErrorCode.ABSTRACT_STATIC_METHOD,
ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION,
ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE,

View file

@ -29,6 +29,10 @@ class ParserErrorCode extends ErrorCode {
'ABSTRACT_ENUM', "Enums can't be declared to be 'abstract'.",
correction: "Try removing the keyword 'abstract'.");
static const ParserErrorCode ABSTRACT_LATE_FIELD = _ABSTRACT_LATE_FIELD;
static const ParserErrorCode ABSTRACT_STATIC_FIELD = _ABSTRACT_STATIC_FIELD;
static const ParserErrorCode ABSTRACT_STATIC_METHOD = ParserErrorCode(
'ABSTRACT_STATIC_METHOD',
"Static methods can't be declared to be 'abstract'.",

View file

@ -114,6 +114,8 @@ final fastaAnalyzerErrorCodes = <ErrorCode>[
_SETTER_CONSTRUCTOR,
_MEMBER_WITH_CLASS_NAME,
_EXTERNAL_CONSTRUCTOR_WITH_INITIALIZER,
_ABSTRACT_STATIC_FIELD,
_ABSTRACT_LATE_FIELD,
];
const ParserErrorCode _ABSTRACT_CLASS_MEMBER = ParserErrorCode(
@ -122,6 +124,14 @@ const ParserErrorCode _ABSTRACT_CLASS_MEMBER = ParserErrorCode(
correction:
"Try removing the 'abstract' keyword. You can add the 'abstract' keyword before the class declaration.");
const ParserErrorCode _ABSTRACT_LATE_FIELD = ParserErrorCode(
'ABSTRACT_LATE_FIELD', r"Abstract fields cannot be late.",
correction: "Try removing the 'abstract' or 'late' keyword.");
const ParserErrorCode _ABSTRACT_STATIC_FIELD = ParserErrorCode(
'ABSTRACT_STATIC_FIELD', r"Static fields can't be declared 'abstract'.",
correction: "Try removing the 'abstract' or 'static' keyword.");
const ParserErrorCode _ANNOTATION_WITH_TYPE_ARGUMENTS = ParserErrorCode(
'ANNOTATION_WITH_TYPE_ARGUMENTS',
r"An annotation (metadata) can't use type arguments.");

View file

@ -8,6 +8,8 @@ import 'package:_fe_analyzer_shared/src/messages/codes.dart'
Message,
MessageCode,
messageAbstractClassMember,
messageAbstractLateField,
messageAbstractStaticField,
messageConstConstructorWithBody,
messageConstructorWithTypeParameters,
messageDirectiveAfterDeclaration,
@ -849,9 +851,20 @@ class AstBuilder extends StackListener {
assert(optional(';', semicolon));
debugEvent("Fields");
if (!enableNonNullable && abstractToken != null) {
handleRecoverableError(
messageAbstractClassMember, abstractToken, abstractToken);
if (abstractToken != null) {
if (!enableNonNullable) {
handleRecoverableError(
messageAbstractClassMember, abstractToken, abstractToken);
} else {
if (staticToken != null) {
handleRecoverableError(
messageAbstractStaticField, abstractToken, abstractToken);
}
if (lateToken != null) {
handleRecoverableError(
messageAbstractLateField, abstractToken, abstractToken);
}
}
}
if (externalToken != null) {
handleRecoverableError(

View file

@ -182,6 +182,42 @@ class ClassMemberParserTest_Fasta extends FastaParserTestCase
expect(field.abstractKeyword, isNotNull);
}
void test_parseField_abstract_late() {
createParser('abstract late int? i;', featureSet: nonNullable);
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertErrors(errors: [
expectedError(ParserErrorCode.ABSTRACT_LATE_FIELD, 0, 8),
]);
expect(member, isFieldDeclaration);
FieldDeclaration field = member;
expect(field.abstractKeyword, isNotNull);
}
void test_parseField_abstract_late_final() {
createParser('abstract late final int? i;', featureSet: nonNullable);
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertErrors(errors: [
expectedError(ParserErrorCode.ABSTRACT_LATE_FIELD, 0, 8),
]);
expect(member, isFieldDeclaration);
FieldDeclaration field = member;
expect(field.abstractKeyword, isNotNull);
}
void test_parseField_abstract_static() {
createParser('abstract static int? i;', featureSet: nonNullable);
ClassMember member = parser.parseClassMember('C');
expect(member, isNotNull);
assertErrors(errors: [
expectedError(ParserErrorCode.ABSTRACT_STATIC_FIELD, 0, 8),
]);
expect(member, isFieldDeclaration);
FieldDeclaration field = member;
expect(field.abstractKeyword, isNotNull);
}
void test_parseField_const_late() {
createParser('const late T f = 0;', featureSet: nonNullable);
ClassMember member = parser.parseClassMember('C');

View file

@ -11,10 +11,8 @@ AbstractFieldInitializer/analyzerCode: Fail
AbstractExtensionField/analyzerCode: Fail
AbstractExtensionField/example: Fail
AbstractExternalField/analyzerCode: Fail
AbstractLateField/analyzerCode: Fail
AbstractNotSync/example: Fail
AbstractRedirectedClassInstantiation/example: Fail
AbstractStaticField/analyzerCode: Fail
AccessError/analyzerCode: Fail
AccessError/example: Fail
AmbiguousExtensionMethod/analyzerCode: Fail

View file

@ -563,7 +563,9 @@ AbstractExternalField:
- "abstract class C {external abstract var f;}"
AbstractStaticField:
index: 107
template: "Static fields can't be declared 'abstract'."
analyzerCode: ParserErrorCode.ABSTRACT_STATIC_FIELD
tip: "Try removing the 'abstract' or 'static' keyword."
configuration: nnbd-strong
script:
@ -593,7 +595,9 @@ AbstractFieldConstructorInitializer:
- "abstract class C {abstract var f; C() : this.f = 0;}"
AbstractLateField:
index: 108
template: "Abstract fields cannot be late."
analyzerCode: ParserErrorCode.ABSTRACT_LATE_FIELD
tip: "Try removing the 'abstract' or 'late' keyword."
configuration: nnbd-strong
script: