Skip to content

Commit 2eec09d

Browse files
FMorschelCommit Queue
authored andcommitted
[DAS] Makes EXTENSION_DECLARES_INSTANCE_FIELD trigger on all field names
[email protected], [email protected] Fixes #59847 Change-Id: Ic4b41973d0d74d809d813ba57b85f50fab4c9a47 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/407080 Auto-Submit: Felipe Morschel <[email protected]> Reviewed-by: Paul Berry <[email protected]> Reviewed-by: Jens Johansen <[email protected]> Commit-Queue: Jens Johansen <[email protected]>
1 parent a14aa26 commit 2eec09d

22 files changed

+171
-87
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
// NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
66
//
7-
// Instead modify 'pkg/front_end/messages.yaml' and run
8-
// 'pkg/front_end/tool/cfe generate-messages' to update.
7+
// Instead modify 'pkg/front_end/messages.yaml' and defer to it for the
8+
// commands to update this file.
99

1010
// ignore_for_file: lines_longer_than_80_chars
1111

@@ -5380,7 +5380,7 @@ const Code<Null> codeExtensionAugmentationHasOnClause =
53805380
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
53815381
const MessageCode messageExtensionAugmentationHasOnClause = const MessageCode(
53825382
"ExtensionAugmentationHasOnClause",
5383-
index: 179,
5383+
index: 93,
53845384
problemMessage: r"""Extension augmentations can't have 'on' clauses.""",
53855385
correctionMessage: r"""Try removing the 'on' clause.""",
53865386
);
@@ -5416,7 +5416,7 @@ const Code<Null> codeExtensionDeclaresInstanceField =
54165416
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
54175417
const MessageCode messageExtensionDeclaresInstanceField = const MessageCode(
54185418
"ExtensionDeclaresInstanceField",
5419-
index: 93,
5419+
analyzerCodes: <String>["EXTENSION_DECLARES_INSTANCE_FIELD"],
54205420
problemMessage: r"""Extensions can't declare instance fields""",
54215421
correctionMessage:
54225422
r"""Try removing the field declaration or making it a static field""",

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,10 @@ CompileTimeErrorCode.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE:
651651
status: noFix
652652
CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT:
653653
status: hasFix
654+
CompileTimeErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD:
655+
status: needsFix
656+
notes: |-
657+
Remove the field, or add `static`.
654658
CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER:
655659
status: hasFix
656660
CompileTimeErrorCode.EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE:
@@ -666,9 +670,9 @@ CompileTimeErrorCode.EXTENSION_TYPE_CONSTRUCTOR_WITH_SUPER_FORMAL_PARAMETER:
666670
CompileTimeErrorCode.EXTENSION_TYPE_CONSTRUCTOR_WITH_SUPER_INVOCATION:
667671
status: needsFix
668672
notes: |-
669-
Remove it.
673+
Remove the field, or add `static`.
670674
CompileTimeErrorCode.EXTENSION_TYPE_DECLARES_INSTANCE_FIELD:
671-
status: noFix
675+
status: needsFix
672676
CompileTimeErrorCode.EXTENSION_TYPE_DECLARES_MEMBER_OF_OBJECT:
673677
status: hasFix
674678
CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_DISALLOWED_TYPE:
@@ -2771,10 +2775,6 @@ ParserErrorCode.EXTENSION_DECLARES_ABSTRACT_MEMBER:
27712775
Provide an empty body for the member.
27722776
ParserErrorCode.EXTENSION_DECLARES_CONSTRUCTOR:
27732777
status: hasFix
2774-
ParserErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD:
2775-
status: needsFix
2776-
notes: |-
2777-
Remove the field, or add `static`.
27782778
ParserErrorCode.EXTENSION_TYPE_EXTENDS:
27792779
status: needsEvaluation
27802780
ParserErrorCode.EXTENSION_TYPE_WITH:

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

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ final fastaAnalyzerErrorCodes = <ErrorCode?>[
114114
ParserErrorCode.INVALID_INITIALIZER,
115115
ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS,
116116
ParserErrorCode.EXTENSION_DECLARES_CONSTRUCTOR,
117-
ParserErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD,
117+
ParserErrorCode.EXTENSION_AUGMENTATION_HAS_ON_CLAUSE,
118118
ParserErrorCode.EXTENSION_DECLARES_ABSTRACT_MEMBER,
119119
ParserErrorCode.MIXIN_DECLARES_CONSTRUCTOR,
120120
ParserErrorCode.NULL_AWARE_CASCADE_OUT_OF_ORDER,
@@ -200,7 +200,6 @@ final fastaAnalyzerErrorCodes = <ErrorCode?>[
200200
ParserErrorCode.ABSTRACT_FINAL_BASE_CLASS,
201201
ParserErrorCode.ABSTRACT_FINAL_INTERFACE_CLASS,
202202
ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_FIELD_INITIALIZERS,
203-
ParserErrorCode.EXTENSION_AUGMENTATION_HAS_ON_CLAUSE,
204203
];
205204

206205
class ParserErrorCode extends ErrorCode {
@@ -752,16 +751,6 @@ class ParserErrorCode extends ErrorCode {
752751
hasPublishedDocs: true,
753752
);
754753

755-
/// No parameters.
756-
static const ParserErrorCode EXTENSION_DECLARES_INSTANCE_FIELD =
757-
ParserErrorCode(
758-
'EXTENSION_DECLARES_INSTANCE_FIELD',
759-
"Extensions can't declare instance fields",
760-
correctionMessage:
761-
"Try removing the field declaration or making it a static field",
762-
hasPublishedDocs: true,
763-
);
764-
765754
static const ParserErrorCode EXTENSION_TYPE_EXTENDS = ParserErrorCode(
766755
'EXTENSION_TYPE_EXTENDS',
767756
"An extension type declaration can't have an 'extends' clause.",

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,6 +1745,15 @@ class CompileTimeErrorCode extends ErrorCode {
17451745
hasPublishedDocs: true,
17461746
);
17471747

1748+
/// No parameters.
1749+
static const CompileTimeErrorCode EXTENSION_DECLARES_INSTANCE_FIELD =
1750+
CompileTimeErrorCode(
1751+
'EXTENSION_DECLARES_INSTANCE_FIELD',
1752+
"Extensions can't declare instance fields.",
1753+
correctionMessage: "Try replacing the field with a getter.",
1754+
hasPublishedDocs: true,
1755+
);
1756+
17481757
/// No parameters.
17491758
static const CompileTimeErrorCode EXTENSION_DECLARES_MEMBER_OF_OBJECT =
17501759
CompileTimeErrorCode(

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ const List<ErrorCode> errorCodeValues = [
208208
CompileTimeErrorCode.EXTENDS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
209209
CompileTimeErrorCode.EXTENSION_AS_EXPRESSION,
210210
CompileTimeErrorCode.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE,
211+
CompileTimeErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD,
211212
CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT,
212213
CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER,
213214
CompileTimeErrorCode.EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE,
@@ -735,7 +736,6 @@ const List<ErrorCode> errorCodeValues = [
735736
ParserErrorCode.EXTENSION_AUGMENTATION_HAS_ON_CLAUSE,
736737
ParserErrorCode.EXTENSION_DECLARES_ABSTRACT_MEMBER,
737738
ParserErrorCode.EXTENSION_DECLARES_CONSTRUCTOR,
738-
ParserErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD,
739739
ParserErrorCode.EXTENSION_TYPE_EXTENDS,
740740
ParserErrorCode.EXTENSION_TYPE_WITH,
741741
ParserErrorCode.EXTERNAL_CLASS,

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ class FastaErrorReporter {
141141
errorCode: ParserErrorCode.EXPECTED_TYPE_NAME,
142142
);
143143
return;
144+
case "EXTENSION_DECLARES_INSTANCE_FIELD":
145+
// Reported by
146+
// [ErrorVerifier._checkForExtensionDeclaresInstanceField]
147+
return;
144148
case "FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR":
145149
errorReporter?.atOffset(
146150
offset: offset,
@@ -517,7 +521,7 @@ class FastaErrorReporter {
517521
return;
518522
case "ABSTRACT_EXTENSION_FIELD":
519523
// Not reported but followed by a
520-
// ParserErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD.
524+
// CompileTimeErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD.
521525
return;
522526
case "EXTENSION_TYPE_WITH_ABSTRACT_MEMBER":
523527
// Reported by [ErrorVerifier._checkForExtensionTypeWithAbstractMember].

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
885885
var oldHasAccessToThis = _hasAccessToThis;
886886
try {
887887
_hasAccessToThis = !node.isStatic && node.fields.isLate;
888+
_checkForExtensionDeclaresInstanceField(node);
888889
_checkForExtensionTypeDeclaresInstanceField(node);
889890
_checkForNotInitializedNonNullableStaticField(node);
890891
_checkForWrongTypeParameterVarianceInField(node);
@@ -3389,6 +3390,23 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
33893390
_typeProvider.isNonSubtypableClass(type.element);
33903391
}
33913392

3393+
void _checkForExtensionDeclaresInstanceField(FieldDeclaration node) {
3394+
if (node.parent is! ExtensionDeclaration) {
3395+
return;
3396+
}
3397+
3398+
if (node.isStatic || node.externalKeyword != null) {
3399+
return;
3400+
}
3401+
3402+
for (var field in node.fields.variables) {
3403+
errorReporter.atToken(
3404+
field.name,
3405+
CompileTimeErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD,
3406+
);
3407+
}
3408+
}
3409+
33923410
void _checkForExtensionDeclaresMemberOfObject(MethodDeclaration node) {
33933411
if (_enclosingExtension != null) {
33943412
if (node.hasObjectMemberName) {

pkg/analyzer/messages.yaml

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
# Run
66
#
7-
# dart run analyzer/tool/messages/generate.dart
7+
# dart run pkg/analyzer/tool/messages/generate.dart
88
#
99
# to regenerate messages after having edited this file.
1010

@@ -5111,6 +5111,61 @@ CompileTimeErrorCode:
51115111
static int b() => 0;
51125112
}
51135113
```
5114+
EXTENSION_DECLARES_INSTANCE_FIELD:
5115+
problemMessage: "Extensions can't declare instance fields."
5116+
correctionMessage: Try replacing the field with a getter.
5117+
hasPublishedDocs: true
5118+
comment: No parameters.
5119+
documentation: |-
5120+
#### Description
5121+
5122+
The analyzer produces this diagnostic when an instance field declaration is
5123+
found in an extension. It isn't valid to define an instance field because
5124+
extensions can only add behavior, not state.
5125+
5126+
#### Example
5127+
5128+
The following code produces this diagnostic because `s` is an instance
5129+
field:
5130+
5131+
```dart
5132+
%language=2.9
5133+
extension E on String {
5134+
String [!s!];
5135+
}
5136+
```
5137+
5138+
#### Common fixes
5139+
5140+
If the value can be computed without storing it in a field, then try using a getter or a method:
5141+
5142+
```dart
5143+
extension E on String {
5144+
String get s => '';
5145+
5146+
void s(String value) => print(s);
5147+
}
5148+
```
5149+
5150+
If the value must be stored, but is the same for every instance, try using a static field:
5151+
5152+
```dart
5153+
extension E on String {
5154+
static String s = '';
5155+
}
5156+
```
5157+
5158+
If each instance needs to have its own value stored, then try using a getter and setter pair backed by a static Expando:
5159+
5160+
```dart
5161+
extension E on SomeType {
5162+
static final _s = Expando<String>();
5163+
5164+
String get s => _s[this] ?? '';
5165+
set s(String value) => _s[this] = value;
5166+
}
5167+
```
5168+
51145169
EXTENSION_DECLARES_MEMBER_OF_OBJECT:
51155170
problemMessage: "Extensions can't declare members with the same name as a member declared by 'Object'."
51165171
correctionMessage: Try specifying a different name for the member.

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
65
import 'package:analyzer/src/error/codes.dart';
76
import 'package:test_reflective_loader/test_reflective_loader.dart';
87

@@ -246,7 +245,7 @@ extension<U> on A<U> {
246245
''', [
247246
// An instance field is illegal, but we should not also report an
248247
// additional error for the type variable.
249-
error(ParserErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD, 63, 1),
248+
error(CompileTimeErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD, 63, 1),
250249
]);
251250
}
252251

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

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
5+
import 'package:analyzer/src/error/codes.dart';
66
import 'package:test_reflective_loader/test_reflective_loader.dart';
77

88
import '../dart/resolution/context_collection_resolution.dart';
@@ -15,15 +15,19 @@ main() {
1515

1616
@reflectiveTest
1717
class ExtensionDeclaresFieldTest extends PubPackageResolutionTest {
18-
test_multiple() async {
18+
Future<void> test_multiple() async {
1919
await assertErrorsInCode('''
2020
extension E on String {
2121
String? one, two, three;
2222
}
23-
''', [error(ParserErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD, 34, 3)]);
23+
''', [
24+
error(CompileTimeErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD, 34, 3),
25+
error(CompileTimeErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD, 39, 3),
26+
error(CompileTimeErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD, 44, 5),
27+
]);
2428
}
2529

26-
test_none() async {
30+
Future<void> test_none() async {
2731
await assertNoErrorsInCode('''
2832
extension E on String {}
2933
''');
@@ -34,10 +38,10 @@ extension E on String {}
3438
extension E on String {
3539
String? s;
3640
}
37-
''', [error(ParserErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD, 34, 1)]);
41+
''', [error(CompileTimeErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD, 34, 1)]);
3842
}
3943

40-
test_static() async {
44+
Future<void> test_static() async {
4145
await assertNoErrorsInCode('''
4246
extension E on String {
4347
static String EMPTY = '';

0 commit comments

Comments
 (0)