Skip to content

Commit 8f477fd

Browse files
jensjohacommit-bot@chromium.org
authored andcommitted
[parser] Disallow covariant on extension method parameters
Fixes #38560. Change-Id: I4c941fb6713983cc01efbe143c7924d0643efe73 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/119332 Commit-Queue: Jens Johansen <jensj@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
1 parent dee6458 commit 8f477fd

20 files changed

Lines changed: 158 additions & 95 deletions

pkg/analyzer/lib/error/error.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ const List<ErrorCode> errorCodeValues = const [
196196
CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET,
197197
CompileTimeErrorCode.INVALID_URI,
198198
CompileTimeErrorCode.INVALID_USE_OF_COVARIANT,
199+
// ignore: deprecated_member_use_from_same_package
199200
CompileTimeErrorCode.INVALID_USE_OF_COVARIANT_IN_EXTENSION,
200201
CompileTimeErrorCode.INVOCATION_OF_EXTENSION_WITHOUT_CALL,
201202
CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE,
@@ -522,6 +523,7 @@ const List<ErrorCode> errorCodeValues = const [
522523
ParserErrorCode.INVALID_STAR_AFTER_ASYNC,
523524
ParserErrorCode.INVALID_SYNC,
524525
ParserErrorCode.INVALID_UNICODE_ESCAPE,
526+
ParserErrorCode.INVALID_USE_OF_COVARIANT_IN_EXTENSION,
525527
ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST,
526528
ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER,
527529
ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR,

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,38 @@ class ParserErrorCode extends ErrorCode {
481481

482482
static const ParserErrorCode INVALID_UNICODE_ESCAPE = _INVALID_UNICODE_ESCAPE;
483483

484+
/**
485+
* No parameters.
486+
*/
487+
// #### Description
488+
//
489+
// The analyzer produces this diagnostic when a member declared inside an
490+
// extension uses the keyword `covariant` in the declaration of a parameter.
491+
// Extensions aren't classes and don't have subclasses, so the keyword serves
492+
// no purpose.
493+
//
494+
// #### Example
495+
//
496+
// The following code produces this diagnostic:
497+
//
498+
// ```dart
499+
// extension E on String {
500+
// void a([!covariant!] int i) {}
501+
// }
502+
// ```
503+
//
504+
// #### Common fixes
505+
//
506+
// Remove the 'covariant' keyword:
507+
//
508+
// ```dart
509+
// extension E on String {
510+
// void a(int i) {}
511+
// }
512+
// ```
513+
static const ParserErrorCode INVALID_USE_OF_COVARIANT_IN_EXTENSION =
514+
_INVALID_USE_OF_COVARIANT_IN_EXTENSION;
515+
484516
static const ParserErrorCode LIBRARY_DIRECTIVE_NOT_FIRST =
485517
_LIBRARY_DIRECTIVE_NOT_FIRST;
486518

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ final fastaAnalyzerErrorCodes = <ErrorCode>[
105105
_MIXIN_DECLARES_CONSTRUCTOR,
106106
_NULL_AWARE_CASCADE_OUT_OF_ORDER,
107107
_MULTIPLE_VARIANCE_MODIFIERS,
108+
_INVALID_USE_OF_COVARIANT_IN_EXTENSION,
108109
];
109110

110111
const ParserErrorCode _ABSTRACT_CLASS_MEMBER = const ParserErrorCode(
@@ -398,6 +399,11 @@ const ParserErrorCode _INVALID_UNICODE_ESCAPE = const ParserErrorCode(
398399
'INVALID_UNICODE_ESCAPE',
399400
r"An escape sequence starting with '\u' must be followed by 4 hexadecimal digits or from 1 to 6 digits between '{' and '}'.");
400401

402+
const ParserErrorCode _INVALID_USE_OF_COVARIANT_IN_EXTENSION =
403+
const ParserErrorCode('INVALID_USE_OF_COVARIANT_IN_EXTENSION',
404+
r"Can't have modifier '#lexeme' in an extension.",
405+
correction: "Try removing '#lexeme'.");
406+
401407
const ParserErrorCode _LIBRARY_DIRECTIVE_NOT_FIRST = const ParserErrorCode(
402408
'LIBRARY_DIRECTIVE_NOT_FIRST',
403409
r"The library directive must appear before all other directives.",

pkg/analyzer/lib/src/error/codes.dart

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2599,40 +2599,9 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
25992599
"methods or before non-final instance fields.",
26002600
correction: "Try removing the 'covariant' keyword.");
26012601

2602-
/**
2603-
* No parameters.
2604-
*/
2605-
// #### Description
2606-
//
2607-
// The analyzer produces this diagnostic when a member declared inside an
2608-
// extension uses the keyword `covariant` in the declaration of a parameter.
2609-
// Extensions aren't classes and don't have subclasses, so the keyword serves
2610-
// no purpose.
2611-
//
2612-
// #### Example
2613-
//
2614-
// The following code produces this diagnostic:
2615-
//
2616-
// ```dart
2617-
// extension E on String {
2618-
// void a([!covariant!] int i) {}
2619-
// }
2620-
// ```
2621-
//
2622-
// #### Common fixes
2623-
//
2624-
// Remove the 'covariant' keyword:
2625-
//
2626-
// ```dart
2627-
// extension E on String {
2628-
// void a(int i) {}
2629-
// }
2630-
// ```
2631-
static const CompileTimeErrorCode INVALID_USE_OF_COVARIANT_IN_EXTENSION =
2632-
const CompileTimeErrorCode('INVALID_USE_OF_COVARIANT_IN_EXTENSION',
2633-
"The 'covariant' keyword can't be used in an extension.",
2634-
correction: "Try removing the 'covariant' keyword.",
2635-
hasPublishedDocs: true);
2602+
@Deprecated('Use ParserErrorCode.INVALID_USE_OF_COVARIANT_IN_EXTENSION')
2603+
static const ParserErrorCode INVALID_USE_OF_COVARIANT_IN_EXTENSION =
2604+
ParserErrorCode.INVALID_USE_OF_COVARIANT_IN_EXTENSION;
26362605

26372606
/**
26382607
* 14.2 Exports: It is a compile-time error if the compilation unit found at

pkg/analyzer/lib/src/generated/error_verifier.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5497,10 +5497,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
54975497
Token keyword = parameter.covariantKeyword;
54985498
if (keyword != null) {
54995499
if (_enclosingExtension != null) {
5500-
_errorReporter.reportErrorForToken(
5501-
CompileTimeErrorCode.INVALID_USE_OF_COVARIANT_IN_EXTENSION,
5502-
keyword,
5503-
);
5500+
// Reported by the parser.
55045501
} else {
55055502
_errorReporter.reportErrorForToken(
55065503
CompileTimeErrorCode.INVALID_USE_OF_COVARIANT,

pkg/analyzer/test/src/diagnostics/invalid_use_of_covariant_in_extension_test.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'package:analyzer/dart/analysis/features.dart';
6-
import 'package:analyzer/src/error/codes.dart';
76
import 'package:analyzer/src/generated/engine.dart';
7+
import 'package:analyzer/src/generated/parser.dart';
88
import 'package:test_reflective_loader/test_reflective_loader.dart';
99

1010
import '../dart/resolution/driver_resolution.dart';
@@ -28,7 +28,7 @@ extension E on String {
2828
void foo({covariant int a}) {}
2929
}
3030
''', [
31-
error(CompileTimeErrorCode.INVALID_USE_OF_COVARIANT_IN_EXTENSION, 36, 9),
31+
error(ParserErrorCode.INVALID_USE_OF_COVARIANT_IN_EXTENSION, 36, 9),
3232
]);
3333
}
3434

@@ -38,7 +38,7 @@ extension E on String {
3838
void foo([covariant int a]) {}
3939
}
4040
''', [
41-
error(CompileTimeErrorCode.INVALID_USE_OF_COVARIANT_IN_EXTENSION, 36, 9),
41+
error(ParserErrorCode.INVALID_USE_OF_COVARIANT_IN_EXTENSION, 36, 9),
4242
]);
4343
}
4444

@@ -48,7 +48,7 @@ extension E on String {
4848
void foo(covariant int a) {}
4949
}
5050
''', [
51-
error(CompileTimeErrorCode.INVALID_USE_OF_COVARIANT_IN_EXTENSION, 35, 9),
51+
error(ParserErrorCode.INVALID_USE_OF_COVARIANT_IN_EXTENSION, 35, 9),
5252
]);
5353
}
5454
}

pkg/analyzer/tool/diagnostics/diagnostics.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1307,7 +1307,7 @@ var x;
13071307

13081308
### invalid_use_of_covariant_in_extension
13091309

1310-
_The 'covariant' keyword can't be used in an extension._
1310+
_Can't have modifier '#lexeme' in an extension._
13111311

13121312
#### Description
13131313

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3573,6 +3573,29 @@ Message _withArgumentsExtraneousModifier(Token token) {
35733573
arguments: {'token': token});
35743574
}
35753575

3576+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
3577+
const Template<Message Function(Token token)>
3578+
templateExtraneousModifierInExtension =
3579+
const Template<Message Function(Token token)>(
3580+
messageTemplate: r"""Can't have modifier '#lexeme' in an extension.""",
3581+
tipTemplate: r"""Try removing '#lexeme'.""",
3582+
withArguments: _withArgumentsExtraneousModifierInExtension);
3583+
3584+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
3585+
const Code<Message Function(Token token)> codeExtraneousModifierInExtension =
3586+
const Code<Message Function(Token token)>(
3587+
"ExtraneousModifierInExtension", templateExtraneousModifierInExtension,
3588+
index: 98);
3589+
3590+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
3591+
Message _withArgumentsExtraneousModifierInExtension(Token token) {
3592+
String lexeme = token.lexeme;
3593+
return new Message(codeExtraneousModifierInExtension,
3594+
message: """Can't have modifier '${lexeme}' in an extension.""",
3595+
tip: """Try removing '${lexeme}'.""",
3596+
arguments: {'token': token});
3597+
}
3598+
35763599
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
35773600
const Code<Null> codeFactoryNotSync = messageFactoryNotSync;
35783601

pkg/front_end/lib/src/fasta/parser/member_kind.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ enum MemberKind {
3232
/// A top-level method.
3333
TopLevelMethod,
3434

35+
/// A non-static method in an extension.
36+
ExtensionNonStaticMethod,
37+
38+
/// A static method in an extension.
39+
ExtensionStaticMethod,
40+
3541
/// An instance field in a class.
3642
NonStaticField,
3743

pkg/front_end/lib/src/fasta/parser/modifier_context.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ class ModifierRecoveryContext {
117117
memberKind == MemberKind.TopLevelMethod) {
118118
reportExtraneousModifier(this.covariantToken);
119119
this.covariantToken = null;
120+
} else if (memberKind == MemberKind.ExtensionNonStaticMethod ||
121+
memberKind == MemberKind.ExtensionStaticMethod) {
122+
reportExtraneousModifierInExtension(this.covariantToken);
123+
this.covariantToken = null;
120124
}
121125
if (constToken != null) {
122126
reportExtraneousModifier(constToken);
@@ -462,6 +466,13 @@ class ModifierRecoveryContext {
462466
}
463467
}
464468

469+
void reportExtraneousModifierInExtension(Token modifier) {
470+
if (modifier != null) {
471+
parser.reportRecoverableErrorWithToken(
472+
modifier, fasta.templateExtraneousModifierInExtension);
473+
}
474+
}
475+
465476
void reportModifierOutOfOrder(Token modifier, String beforeModifier) {
466477
parser.reportRecoverableError(
467478
modifier,

0 commit comments

Comments
 (0)