Augment. Report modifierOutOfOrder for 'abstract static' field.

Change-Id: I6e25f204708ed6031e4004464205b5b173253e81
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/508373
Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Konstantin Shcheglov
2026-06-02 11:55:23 -07:00
parent 45c27304eb
commit 2cc79a0fec
4 changed files with 77 additions and 33 deletions
@@ -605,14 +605,16 @@ class ModifierContext {
if (covariantToken == null && staticToken == null && !_afterFactory) {
staticToken = next;
if (constToken != null) {
if (abstractToken != null && parser.isAugmentationsFeatureEnabled) {
reportModifierOutOfOrder(next, abstractToken!.lexeme);
} else if (constToken != null) {
reportModifierOutOfOrder(next, constToken!.lexeme);
} else if (finalToken != null) {
reportModifierOutOfOrder(next, finalToken!.lexeme);
} else if (varToken != null) {
reportModifierOutOfOrder(next, varToken!.lexeme);
} else if (lateToken != null) {
reportModifierOutOfOrder(next, lateToken!.lexeme);
} else if (varToken != null) {
reportModifierOutOfOrder(next, varToken!.lexeme);
}
return next;
}
@@ -348,7 +348,7 @@ class Parser {
bool get allowedToShortcutParseExpression => true;
/// `true` if the 'augmentations' feature is enabled.
final bool _isAugmentationsFeatureEnabled;
final bool isAugmentationsFeatureEnabled;
Parser(
this.listener, {
@@ -363,8 +363,9 @@ class Parser {
.isExperimentEnabled(ExperimentalFlag.primaryConstructors),
_isAnonymousMethodsFeatureEnabled = experimentalFeatures
.isExperimentEnabled(ExperimentalFlag.anonymousMethods),
_isAugmentationsFeatureEnabled = experimentalFeatures
.isExperimentEnabled(ExperimentalFlag.augmentations);
isAugmentationsFeatureEnabled = experimentalFeatures.isExperimentEnabled(
ExperimentalFlag.augmentations,
);
/// Executes [callback]; however if `this` is the `TestParser` (from
/// `pkg/front_end/test/parser_test_parser.dart`) then no output is printed
@@ -4349,7 +4350,7 @@ class Parser {
if (getOrSet != null) {
reportRecoverableErrorWithToken(getOrSet, diag.extraneousModifier);
}
if (!_isAugmentationsFeatureEnabled && abstractToken != null) {
if (!isAugmentationsFeatureEnabled && abstractToken != null) {
reportRecoverableErrorWithToken(abstractToken, diag.extraneousModifier);
}
return parseFields(
@@ -4585,7 +4586,7 @@ class Parser {
token = parseFunctionBody(
token,
/* ofFunctionExpression = */ false,
isExternal || _isAugmentationsFeatureEnabled,
isExternal || isAugmentationsFeatureEnabled,
);
asyncState = savedAsyncModifier;
listener.endTopLevelMethod(beforeStart.next!, getOrSet, token);
@@ -5252,7 +5253,7 @@ class Parser {
next = token.next!;
}
if (isModifier(next)) {
if (next.isA(Keyword.STATIC)) {
if (next.isA(Keyword.STATIC) && abstractToken == null) {
staticToken = token = next;
next = token.next!;
} else if (next.isA(Keyword.COVARIANT)) {
@@ -6009,7 +6010,7 @@ class Parser {
/* ofFunctionExpression = */ false,
/* allowAbstract = */ (staticToken == null ||
externalToken != null ||
_isAugmentationsFeatureEnabled) &&
isAugmentationsFeatureEnabled) &&
inPlainSync,
);
}
@@ -6211,7 +6212,7 @@ class Parser {
token = parseFunctionBody(
token,
/* ofFunctionExpression = */ false,
/* allowAbstract = */ _isAugmentationsFeatureEnabled,
/* allowAbstract = */ isAugmentationsFeatureEnabled,
);
}
switch (kind) {
@@ -3010,28 +3010,6 @@ FieldDeclaration
''');
}
void test_parseField_abstract_static() {
var parseResult = parseTestCodeWithDiagnostics(r'''
class C {
abstract static int? i;
}
''');
var node = parseResult.findNode.singleClassMember;
assertParsedNodeText(node, r'''
FieldDeclaration
staticKeyword: static
abstractKeyword: abstract
fields: VariableDeclarationList
type: NamedType
name: int
question: ?
variables
VariableDeclaration
name: i
semicolon: ;
''');
}
void test_parseField_const_late() {
var parseResult = parseTestCodeWithDiagnostics(r'''
class C {
@@ -1325,6 +1325,69 @@ ClassDeclaration
''', withOffsets: true);
}
test_field_abstract_static() {
var parseResult = parseTestCodeWithDiagnostics(r'''
class A {
abstract static int? foo;
// ^^^^^^
// [diag.modifierOutOfOrder] The modifier 'static' should be before the modifier 'abstract'.
}
''');
assertParsedNodeText(parseResult.findNode.singleClassDeclaration, r'''
ClassDeclaration
classKeyword: class
namePart: NameWithTypeParameters
typeName: A
body: BlockClassBody
leftBracket: {
members
FieldDeclaration
staticKeyword: static
abstractKeyword: abstract
fields: VariableDeclarationList
type: NamedType
name: int
question: ?
variables
VariableDeclaration
name: foo
semicolon: ;
rightBracket: }
''');
}
test_field_abstract_static_language305() {
var parseResult = parseTestCodeWithDiagnostics(r'''
// @dart = 3.5
class A {
abstract static int? foo;
//^^^^^^^^
// [diag.abstractStaticField] Static fields can't be declared 'abstract'.
}
''');
assertParsedNodeText(parseResult.findNode.singleClassDeclaration, r'''
ClassDeclaration
classKeyword: class
namePart: NameWithTypeParameters
typeName: A
body: BlockClassBody
leftBracket: {
members
FieldDeclaration
staticKeyword: static
abstractKeyword: abstract
fields: VariableDeclarationList
type: NamedType
name: int
question: ?
variables
VariableDeclaration
name: foo
semicolon: ;
rightBracket: }
''');
}
test_field_augment() {
var parseResult = parseTestCodeWithDiagnostics(r'''
augment class A {