Skip to content

Commit 8ca0aa2

Browse files
johnniwintherCommit Queue
authored and
Commit Queue
committed
[cfe] Report error on covariant in extension type methods
Closes #53324 Change-Id: Iff86c4eb7c141f27c64de29459390ac395e1c4ee Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/341487 Reviewed-by: Chloe Stefantsova <[email protected]> Reviewed-by: Paul Berry <[email protected]> Commit-Queue: Johnni Winther <[email protected]>
1 parent 9bb61c0 commit 8ca0aa2

File tree

48 files changed

+1459
-490
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1459
-490
lines changed

pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4726,6 +4726,60 @@ Message _withArgumentsExtraneousModifierInExtension(Token token) {
47264726
arguments: {'lexeme': token});
47274727
}
47284728

4729+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
4730+
const Template<Message Function(Token token)>
4731+
templateExtraneousModifierInExtensionType =
4732+
const Template<Message Function(Token token)>(
4733+
"ExtraneousModifierInExtensionType",
4734+
problemMessageTemplate:
4735+
r"""Can't have modifier '#lexeme' in an extension type.""",
4736+
correctionMessageTemplate: r"""Try removing '#lexeme'.""",
4737+
withArguments: _withArgumentsExtraneousModifierInExtensionType);
4738+
4739+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
4740+
const Code<Message Function(Token token)>
4741+
codeExtraneousModifierInExtensionType =
4742+
const Code<Message Function(Token token)>(
4743+
"ExtraneousModifierInExtensionType",
4744+
index: 174);
4745+
4746+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
4747+
Message _withArgumentsExtraneousModifierInExtensionType(Token token) {
4748+
String lexeme = token.lexeme;
4749+
return new Message(codeExtraneousModifierInExtensionType,
4750+
problemMessage:
4751+
"""Can't have modifier '${lexeme}' in an extension type.""",
4752+
correctionMessage: """Try removing '${lexeme}'.""",
4753+
arguments: {'lexeme': token});
4754+
}
4755+
4756+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
4757+
const Template<Message Function(Token token)>
4758+
templateExtraneousModifierInPrimaryConstructor =
4759+
const Template<Message Function(Token token)>(
4760+
"ExtraneousModifierInPrimaryConstructor",
4761+
problemMessageTemplate:
4762+
r"""Can't have modifier '#lexeme' in a primary constructor.""",
4763+
correctionMessageTemplate: r"""Try removing '#lexeme'.""",
4764+
withArguments: _withArgumentsExtraneousModifierInPrimaryConstructor);
4765+
4766+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
4767+
const Code<Message Function(Token token)>
4768+
codeExtraneousModifierInPrimaryConstructor =
4769+
const Code<Message Function(Token token)>(
4770+
"ExtraneousModifierInPrimaryConstructor",
4771+
index: 175);
4772+
4773+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
4774+
Message _withArgumentsExtraneousModifierInPrimaryConstructor(Token token) {
4775+
String lexeme = token.lexeme;
4776+
return new Message(codeExtraneousModifierInPrimaryConstructor,
4777+
problemMessage:
4778+
"""Can't have modifier '${lexeme}' in a primary constructor.""",
4779+
correctionMessage: """Try removing '${lexeme}'.""",
4780+
arguments: {'lexeme': token});
4781+
}
4782+
47294783
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
47304784
const Code<Null> codeFactoryNotSync = messageFactoryNotSync;
47314785

pkg/_fe_analyzer_shared/lib/src/parser/member_kind.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ enum MemberKind {
3838
/// A static method in an extension.
3939
ExtensionStaticMethod,
4040

41+
/// A non-static method or constructor in an extension type.
42+
// TODO(johnniwinther): Can we separate constructors from instance methods?
43+
ExtensionTypeNonStaticMethod,
44+
45+
/// A static method in an extension type.
46+
ExtensionTypeStaticMethod,
47+
4148
/// An instance field in a class.
4249
NonStaticField,
4350

pkg/_fe_analyzer_shared/lib/src/parser/modifier_context.dart

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -197,12 +197,28 @@ class ModifierContext {
197197
if (parameterKind != FormalParameterKind.optionalNamed) {
198198
reportExtraneousModifier(requiredToken);
199199
}
200-
if (memberKind == MemberKind.StaticMethod ||
201-
memberKind == MemberKind.TopLevelMethod) {
202-
reportExtraneousModifier(this.covariantToken);
203-
} else if (memberKind == MemberKind.ExtensionNonStaticMethod ||
204-
memberKind == MemberKind.ExtensionStaticMethod) {
205-
reportExtraneousModifierInExtension(this.covariantToken);
200+
switch (memberKind) {
201+
case MemberKind.StaticMethod:
202+
case MemberKind.TopLevelMethod:
203+
reportExtraneousModifier(this.covariantToken);
204+
case MemberKind.ExtensionNonStaticMethod:
205+
case MemberKind.ExtensionStaticMethod:
206+
reportExtraneousModifierInExtension(this.covariantToken);
207+
case MemberKind.ExtensionTypeNonStaticMethod:
208+
case MemberKind.ExtensionTypeStaticMethod:
209+
reportExtraneousModifierInExtensionType(this.covariantToken);
210+
case MemberKind.PrimaryConstructor:
211+
reportExtraneousModifierInPrimaryConstructor(this.covariantToken);
212+
case MemberKind.Catch:
213+
case MemberKind.Factory:
214+
case MemberKind.FunctionTypeAlias:
215+
case MemberKind.FunctionTypedParameter:
216+
case MemberKind.GeneralizedFunctionType:
217+
case MemberKind.Local:
218+
case MemberKind.NonStaticMethod:
219+
case MemberKind.NonStaticField:
220+
case MemberKind.StaticField:
221+
case MemberKind.TopLevelField:
206222
}
207223
if (constToken != null) {
208224
reportExtraneousModifier(constToken);
@@ -626,6 +642,20 @@ class ModifierContext {
626642
}
627643
}
628644

645+
void reportExtraneousModifierInExtensionType(Token? modifier) {
646+
if (modifier != null) {
647+
parser.reportRecoverableErrorWithToken(
648+
modifier, codes.templateExtraneousModifierInExtensionType);
649+
}
650+
}
651+
652+
void reportExtraneousModifierInPrimaryConstructor(Token? modifier) {
653+
if (modifier != null) {
654+
parser.reportRecoverableErrorWithToken(
655+
modifier, codes.templateExtraneousModifierInPrimaryConstructor);
656+
}
657+
}
658+
629659
void reportModifierOutOfOrder(Token modifier, String beforeModifier) {
630660
parser.reportRecoverableError(
631661
modifier,

pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1826,13 +1826,28 @@ class Parser {
18261826
/// Return the message that should be produced when the formal parameters are
18271827
/// missing.
18281828
codes.Message missingParameterMessage(MemberKind kind) {
1829-
if (kind == MemberKind.FunctionTypeAlias) {
1830-
return codes.messageMissingTypedefParameters;
1831-
} else if (kind == MemberKind.NonStaticMethod ||
1832-
kind == MemberKind.StaticMethod) {
1833-
return codes.messageMissingMethodParameters;
1829+
switch (kind) {
1830+
case MemberKind.FunctionTypeAlias:
1831+
return codes.messageMissingTypedefParameters;
1832+
case MemberKind.StaticMethod:
1833+
case MemberKind.NonStaticMethod:
1834+
return codes.messageMissingMethodParameters;
1835+
case MemberKind.TopLevelMethod:
1836+
case MemberKind.ExtensionNonStaticMethod:
1837+
case MemberKind.ExtensionStaticMethod:
1838+
case MemberKind.ExtensionTypeNonStaticMethod:
1839+
case MemberKind.ExtensionTypeStaticMethod:
1840+
case MemberKind.Catch:
1841+
case MemberKind.Factory:
1842+
case MemberKind.FunctionTypedParameter:
1843+
case MemberKind.GeneralizedFunctionType:
1844+
case MemberKind.Local:
1845+
case MemberKind.NonStaticField:
1846+
case MemberKind.StaticField:
1847+
case MemberKind.TopLevelField:
1848+
case MemberKind.PrimaryConstructor:
1849+
return codes.messageMissingFunctionParameters;
18341850
}
1835-
return codes.messageMissingFunctionParameters;
18361851
}
18371852

18381853
/// Check if [token] is the usage of 'required' in a formal parameter in a
@@ -1923,12 +1938,29 @@ class Parser {
19231938

19241939
if (isModifier(next)) {
19251940
if (optional('covariant', next)) {
1926-
if (memberKind != MemberKind.StaticMethod &&
1927-
memberKind != MemberKind.TopLevelMethod &&
1928-
memberKind != MemberKind.ExtensionNonStaticMethod &&
1929-
memberKind != MemberKind.ExtensionStaticMethod) {
1930-
covariantToken = token = next;
1931-
next = token.next!;
1941+
switch (memberKind) {
1942+
case MemberKind.StaticMethod:
1943+
case MemberKind.TopLevelMethod:
1944+
case MemberKind.ExtensionNonStaticMethod:
1945+
case MemberKind.ExtensionStaticMethod:
1946+
case MemberKind.ExtensionTypeNonStaticMethod:
1947+
case MemberKind.ExtensionTypeStaticMethod:
1948+
case MemberKind.PrimaryConstructor:
1949+
// Error cases reported in
1950+
// [ModifierContext.parseFormalParameterModifiers].
1951+
break;
1952+
case MemberKind.Catch:
1953+
case MemberKind.Factory:
1954+
case MemberKind.FunctionTypeAlias:
1955+
case MemberKind.FunctionTypedParameter:
1956+
case MemberKind.GeneralizedFunctionType:
1957+
case MemberKind.Local:
1958+
case MemberKind.NonStaticMethod:
1959+
case MemberKind.NonStaticField:
1960+
case MemberKind.StaticField:
1961+
case MemberKind.TopLevelField:
1962+
covariantToken = token = next;
1963+
next = token.next!;
19321964
}
19331965
}
19341966

@@ -4846,19 +4878,28 @@ class Parser {
48464878
// that a constructor. We issue an error about the name below.
48474879
}
48484880
}
4881+
MemberKind memberKind;
4882+
switch (kind) {
4883+
case DeclarationKind.TopLevel:
4884+
case DeclarationKind.Class:
4885+
case DeclarationKind.Mixin:
4886+
case DeclarationKind.Enum:
4887+
memberKind = staticToken != null
4888+
? MemberKind.StaticMethod
4889+
: MemberKind.NonStaticMethod;
4890+
case DeclarationKind.Extension:
4891+
memberKind = staticToken != null
4892+
? MemberKind.ExtensionStaticMethod
4893+
: MemberKind.ExtensionNonStaticMethod;
4894+
case DeclarationKind.ExtensionType:
4895+
memberKind = staticToken != null
4896+
? MemberKind.ExtensionTypeStaticMethod
4897+
: MemberKind.ExtensionTypeNonStaticMethod;
4898+
}
48494899

48504900
Token beforeParam = token;
48514901
Token? beforeInitializers = parseGetterOrFormalParameters(
4852-
token,
4853-
name,
4854-
isConsideredGetter,
4855-
kind == DeclarationKind.Extension
4856-
? staticToken != null
4857-
? MemberKind.ExtensionStaticMethod
4858-
: MemberKind.ExtensionNonStaticMethod
4859-
: staticToken != null
4860-
? MemberKind.StaticMethod
4861-
: MemberKind.NonStaticMethod);
4902+
token, name, isConsideredGetter, memberKind);
48624903
token = parseInitializersOpt(beforeInitializers);
48634904
if (token == beforeInitializers) beforeInitializers = null;
48644905

pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2834,6 +2834,10 @@ ParserErrorCode.EXTRANEOUS_MODIFIER:
28342834
status: needsFix
28352835
notes: |-
28362836
Remove the extraneous keyword.
2837+
ParserErrorCode.EXTRANEOUS_MODIFIER_IN_EXTENSION_TYPE:
2838+
status: needsEvaluation
2839+
ParserErrorCode.EXTRANEOUS_MODIFIER_IN_PRIMARY_CONSTRUCTOR:
2840+
status: needsEvaluation
28372841
ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION:
28382842
status: needsFix
28392843
notes: |-

pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ final fastaAnalyzerErrorCodes = <ErrorCode?>[
195195
ParserErrorCode.EXPECTED_SWITCH_EXPRESSION_BODY,
196196
ParserErrorCode.EXPECTED_SWITCH_STATEMENT_BODY,
197197
ParserErrorCode.EXPECTED_EXTENSION_BODY,
198+
ParserErrorCode.EXTRANEOUS_MODIFIER_IN_EXTENSION_TYPE,
199+
ParserErrorCode.EXTRANEOUS_MODIFIER_IN_PRIMARY_CONSTRUCTOR,
198200
];
199201

200202
class ParserErrorCode extends ErrorCode {
@@ -881,6 +883,20 @@ class ParserErrorCode extends ErrorCode {
881883
correctionMessage: "Try removing '{0}'.",
882884
);
883885

886+
static const ParserErrorCode EXTRANEOUS_MODIFIER_IN_EXTENSION_TYPE =
887+
ParserErrorCode(
888+
'EXTRANEOUS_MODIFIER_IN_EXTENSION_TYPE',
889+
"Can't have modifier '{0}' in an extension type.",
890+
correctionMessage: "Try removing '{0}'.",
891+
);
892+
893+
static const ParserErrorCode EXTRANEOUS_MODIFIER_IN_PRIMARY_CONSTRUCTOR =
894+
ParserErrorCode(
895+
'EXTRANEOUS_MODIFIER_IN_PRIMARY_CONSTRUCTOR',
896+
"Can't have modifier '{0}' in a primary constructor.",
897+
correctionMessage: "Try removing '{0}'.",
898+
);
899+
884900
static const ParserErrorCode FACTORY_TOP_LEVEL_DECLARATION = ParserErrorCode(
885901
'FACTORY_TOP_LEVEL_DECLARATION',
886902
"Top-level declarations can't be declared to be 'factory'.",

pkg/analyzer/lib/src/error/error_code_values.g.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,8 @@ const List<ErrorCode> errorCodeValues = [
742742
ParserErrorCode.EXTERNAL_SETTER_WITH_BODY,
743743
ParserErrorCode.EXTERNAL_TYPEDEF,
744744
ParserErrorCode.EXTRANEOUS_MODIFIER,
745+
ParserErrorCode.EXTRANEOUS_MODIFIER_IN_EXTENSION_TYPE,
746+
ParserErrorCode.EXTRANEOUS_MODIFIER_IN_PRIMARY_CONSTRUCTOR,
745747
ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION,
746748
ParserErrorCode.FACTORY_WITHOUT_BODY,
747749
ParserErrorCode.FACTORY_WITH_INITIALIZERS,

pkg/analyzer/lib/src/fasta/ast_builder.dart

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1801,16 +1801,7 @@ class AstBuilder extends StackListener {
18011801
startToken: requiredKeyword,
18021802
);
18031803
}
1804-
// TODO(scheglov): https://github.com/dart-lang/sdk/issues/53324
1805-
// If the issue fixed, we can remove this from the analyzer.
1806-
if (_classLikeBuilder is _ExtensionTypeDeclarationBuilder &&
1807-
covariantKeyword != null) {
1808-
errorReporter.errorReporter?.reportErrorForToken(
1809-
ParserErrorCode.EXTRANEOUS_MODIFIER,
1810-
covariantKeyword,
1811-
[covariantKeyword.lexeme],
1812-
);
1813-
}
1804+
18141805
var metadata = pop() as List<AnnotationImpl>?;
18151806
var comment = _findComment(metadata,
18161807
thisKeyword ?? typeOrFunctionTypedParameter?.beginToken ?? nameToken);

pkg/analyzer/test/src/dart/parser/extension_type_test.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ ExtensionTypeDeclaration
4545
extension type A(covariant int it) {}
4646
''');
4747
parseResult.assertErrors([
48-
error(ParserErrorCode.EXTRANEOUS_MODIFIER, 17, 9),
48+
error(ParserErrorCode.EXTRANEOUS_MODIFIER_IN_PRIMARY_CONSTRUCTOR, 17, 9),
4949
]);
5050

5151
final node = parseResult.findNode.singleExtensionTypeDeclaration;
@@ -70,7 +70,7 @@ ExtensionTypeDeclaration
7070
extension type A(covariant final int it) {}
7171
''');
7272
parseResult.assertErrors([
73-
error(ParserErrorCode.EXTRANEOUS_MODIFIER, 17, 9),
73+
error(ParserErrorCode.EXTRANEOUS_MODIFIER_IN_PRIMARY_CONSTRUCTOR, 17, 9),
7474
error(ParserErrorCode.REPRESENTATION_FIELD_MODIFIER, 27, 5),
7575
]);
7676

@@ -173,7 +173,7 @@ extension type A(int it) {
173173
}
174174
''');
175175
parseResult.assertErrors([
176-
error(ParserErrorCode.EXTRANEOUS_MODIFIER, 38, 9),
176+
error(ParserErrorCode.EXTRANEOUS_MODIFIER_IN_EXTENSION_TYPE, 38, 9),
177177
]);
178178

179179
final node = parseResult.findNode.singleExtensionTypeDeclaration;
@@ -217,7 +217,7 @@ extension type A(int it) {
217217
}
218218
''');
219219
parseResult.assertErrors([
220-
error(ParserErrorCode.EXTRANEOUS_MODIFIER, 45, 9),
220+
error(ParserErrorCode.EXTRANEOUS_MODIFIER_IN_EXTENSION_TYPE, 45, 9),
221221
]);
222222

223223
final node = parseResult.findNode.singleExtensionTypeDeclaration;

pkg/front_end/lib/src/fasta/modifier.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,4 +150,9 @@ class Modifier {
150150
static int removeRequiredMask(int mask) {
151151
return mask & ~requiredMask;
152152
}
153+
154+
/// Sets the bit in [mask] corresponding to [covariantMask] to 0.
155+
static int removeCovariantMask(int mask) {
156+
return mask & ~covariantMask;
157+
}
153158
}

pkg/front_end/lib/src/fasta/source/diet_listener.dart

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -776,13 +776,12 @@ class DietListener extends StackListenerImpl {
776776
// constructor body. An error is reported by the parser but we skip
777777
// the body here to avoid overwriting the already lowering const
778778
// constructor.
779+
// TODO(johnniwinther): Pass [memberKind] from the caller.
780+
MemberKind memberKind = builder.isStatic
781+
? MemberKind.StaticMethod
782+
: MemberKind.NonStaticMethod;
779783
buildFunctionBody(
780-
createFunctionListener(builder),
781-
beginParam,
782-
metadata,
783-
builder.isStatic
784-
? MemberKind.StaticMethod
785-
: MemberKind.NonStaticMethod);
784+
createFunctionListener(builder), beginParam, metadata, memberKind);
786785
}
787786
}
788787

0 commit comments

Comments
 (0)