Skip to content

Commit 6c8ad6a

Browse files
chloestefantsovaCommit Bot
authored and
Commit Bot
committed
[cfe] Report errors on declared 'values' member in enums
Part of #47453 Closes #48389 Closes #48387 Change-Id: I8313e3f63122c85c91a9647ddaa53346591d7238 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/232841 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Chloe Stefantsova <[email protected]>
1 parent 97176be commit 6c8ad6a

14 files changed

+920
-3
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2786,6 +2786,16 @@ const MessageCode messageEnumConstructorTearoff = const MessageCode(
27862786
"EnumConstructorTearoff",
27872787
problemMessage: r"""Enum constructors can't be torn off.""");
27882788

2789+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2790+
const Code<Null> codeEnumContainsValuesDeclaration =
2791+
messageEnumContainsValuesDeclaration;
2792+
2793+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2794+
const MessageCode messageEnumContainsValuesDeclaration = const MessageCode(
2795+
"EnumContainsValuesDeclaration",
2796+
problemMessage:
2797+
r"""Enums can't contain declarations of members with the name 'values'.""");
2798+
27892799
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
27902800
const Code<Null> codeEnumDeclarationEmpty = messageEnumDeclarationEmpty;
27912801

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -722,8 +722,18 @@ class DietListener extends StackListenerImpl {
722722
builder =
723723
lookupConstructor(beginToken, name!) as SourceFunctionBuilderImpl;
724724
} else {
725-
builder = lookupBuilder(beginToken, getOrSet, name as String)
726-
as SourceFunctionBuilderImpl;
725+
Builder? memberBuilder =
726+
lookupBuilder(beginToken, getOrSet, name as String);
727+
if (currentClass?.isEnum == true &&
728+
memberBuilder is SourceFieldBuilder &&
729+
memberBuilder.name == "values") {
730+
// This is the case of a method with the name 'values' declared in an
731+
// Enum. In that case the method is replaced with the synthesized field
732+
// in the outline building phase, and the error is reported there. At
733+
// this point we skip the member.
734+
return;
735+
}
736+
builder = memberBuilder as SourceFunctionBuilderImpl;
727737
}
728738
buildFunctionBody(
729739
createFunctionListener(builder),

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import '../builder/type_variable_builder.dart';
2727
import '../fasta_codes.dart'
2828
show
2929
LocatedMessage,
30+
messageEnumContainsValuesDeclaration,
3031
messageEnumEntryWithTypeArgumentsWithoutArguments,
3132
messageEnumNonConstConstructor,
3233
messageNoUnnamedConstructorInObject,
@@ -242,6 +243,20 @@ class SourceEnumBuilder extends SourceClassBuilder {
242243
referencesFromIndexed.lookupSetterReference(valuesName);
243244
}
244245

246+
Builder? customValuesDeclaration =
247+
scope.lookupLocalMember("values", setter: false);
248+
if (customValuesDeclaration != null) {
249+
// Retrieve the earliest declaration for error reporting.
250+
while (customValuesDeclaration?.next != null) {
251+
customValuesDeclaration = customValuesDeclaration?.next;
252+
}
253+
parent.addProblem(
254+
messageEnumContainsValuesDeclaration,
255+
customValuesDeclaration!.charOffset,
256+
customValuesDeclaration.fullNameForErrors.length,
257+
fileUri);
258+
}
259+
245260
SourceFieldBuilder valuesBuilder = new SourceFieldBuilder(
246261
/* metadata = */ null,
247262
listType,
@@ -338,7 +353,9 @@ class SourceEnumBuilder extends SourceClassBuilder {
338353
final int startCharOffsetComputed =
339354
metadata == null ? startCharOffset : metadata.first.charOffset;
340355
scope.forEachLocalMember((name, member) {
341-
members[name] = member as MemberBuilder;
356+
if (name != "values") {
357+
members[name] = member as MemberBuilder;
358+
}
342359
});
343360
scope.forEachLocalSetter((name, member) {
344361
setters[name] = member;

pkg/front_end/messages.status

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
# Note that test/spelling: Status will have no effect. Spelling errors can
66
# always be fixed by either spelling correctly or updating the dictionary.
77

8+
EnumContainsValuesDeclaration/analyzerCode: Fail
9+
EnumContainsValuesDeclaration/example: Fail
810
AbstractClassConstructorTearOff/analyzerCode: Fail
911
AbstractClassInstantiation/example: Fail
1012
AbstractExtensionField/analyzerCode: Fail

pkg/front_end/messages.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5473,3 +5473,6 @@ EnumConstructorTearoff:
54735473

54745474
EnumFactoryRedirectsToConstructor:
54755475
problemMessage: "Enum factory constructors can't redirect to generative constructors."
5476+
5477+
EnumContainsValuesDeclaration:
5478+
problemMessage: "Enums can't contain declarations of members with the name 'values'."
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
enum E1 {
6+
element;
7+
8+
static const List<E1> values = [E1.element]; // Error in E1.
9+
}
10+
11+
enum E2 {
12+
element;
13+
14+
int values = 42; // Error in E2.
15+
}
16+
17+
enum E3 {
18+
element;
19+
20+
static const List<E3> values = [E3.element]; // Error in E3.
21+
int values = 42; // Duplicate.
22+
}
23+
24+
enum E4 {
25+
element;
26+
27+
static void set values(List<E4> x) {} // Ok.
28+
}
29+
30+
enum E5 {
31+
element;
32+
33+
static void set values(dynamic x) {} // Ok.
34+
}
35+
36+
enum E6 {
37+
element;
38+
39+
static void set values(Never x) {} // Error in E6.
40+
}
41+
42+
enum E7 {
43+
element;
44+
45+
void values() {} // Error in E7.
46+
}
47+
48+
main() {}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/enhanced_enums/declared_values.dart:8:25: Error: Enums can't contain declarations of members with the name 'values'.
6+
// static const List<E1> values = [E1.element]; // Error in E1.
7+
// ^^^^^^
8+
//
9+
// pkg/front_end/testcases/enhanced_enums/declared_values.dart:14:7: Error: Enums can't contain declarations of members with the name 'values'.
10+
// int values = 42; // Error in E2.
11+
// ^^^^^^
12+
//
13+
// pkg/front_end/testcases/enhanced_enums/declared_values.dart:21:7: Error: 'values' is already declared in this scope.
14+
// int values = 42; // Duplicate.
15+
// ^^^^^^
16+
// pkg/front_end/testcases/enhanced_enums/declared_values.dart:20:25: Context: Previous declaration of 'values'.
17+
// static const List<E3> values = [E3.element]; // Error in E3.
18+
// ^^^^^^
19+
//
20+
// pkg/front_end/testcases/enhanced_enums/declared_values.dart:20:25: Error: Enums can't contain declarations of members with the name 'values'.
21+
// static const List<E3> values = [E3.element]; // Error in E3.
22+
// ^^^^^^
23+
//
24+
// pkg/front_end/testcases/enhanced_enums/declared_values.dart:45:8: Error: Enums can't contain declarations of members with the name 'values'.
25+
// void values() {} // Error in E7.
26+
// ^^^^^^
27+
//
28+
// pkg/front_end/testcases/enhanced_enums/declared_values.dart:36:6: Error: The type 'List<E6>' of the getter 'E6.values' is not a subtype of the type 'Never' of the setter 'E6.values'.
29+
// - 'List' is from 'dart:core'.
30+
// - 'E6' is from 'pkg/front_end/testcases/enhanced_enums/declared_values.dart'.
31+
// enum E6 {
32+
// ^^^^^...
33+
// pkg/front_end/testcases/enhanced_enums/declared_values.dart:39:19: Context: This is the declaration of the setter 'E6.values'.
34+
// static void set values(Never x) {} // Error in E6.
35+
// ^^^^^^
36+
//
37+
import self as self;
38+
import "dart:core" as core;
39+
40+
class E1 extends core::_Enum /*isEnum*/ {
41+
static const field core::List<self::E1> values = #C4;
42+
static const field self::E1 element = #C3;
43+
const constructor •(core::int index, core::String name) → self::E1
44+
: super core::_Enum::•(index, name)
45+
;
46+
method toString() → core::String
47+
return "E1.${this.{core::_Enum::_name}{core::String}}";
48+
}
49+
class E2 extends core::_Enum /*isEnum*/ {
50+
static const field core::List<self::E2> values = #C6;
51+
static const field self::E2 element = #C5;
52+
const constructor •(core::int index, core::String name) → self::E2
53+
: super core::_Enum::•(index, name)
54+
;
55+
method toString() → core::String
56+
return "E2.${this.{core::_Enum::_name}{core::String}}";
57+
}
58+
class E3 extends core::_Enum /*isEnum*/ {
59+
static const field core::List<self::E3> values = #C8;
60+
static const field self::E3 element = #C7;
61+
const constructor •(core::int index, core::String name) → self::E3
62+
: super core::_Enum::•(index, name)
63+
;
64+
method toString() → core::String
65+
return "E3.${this.{core::_Enum::_name}{core::String}}";
66+
}
67+
class E4 extends core::_Enum /*isEnum*/ {
68+
static const field core::List<self::E4> values = #C10;
69+
static const field self::E4 element = #C9;
70+
const constructor •(core::int index, core::String name) → self::E4
71+
: super core::_Enum::•(index, name)
72+
;
73+
method toString() → core::String
74+
return "E4.${this.{core::_Enum::_name}{core::String}}";
75+
static set values(core::List<self::E4> x) → void {}
76+
}
77+
class E5 extends core::_Enum /*isEnum*/ {
78+
static const field core::List<self::E5> values = #C12;
79+
static const field self::E5 element = #C11;
80+
const constructor •(core::int index, core::String name) → self::E5
81+
: super core::_Enum::•(index, name)
82+
;
83+
method toString() → core::String
84+
return "E5.${this.{core::_Enum::_name}{core::String}}";
85+
static set values(dynamic x) → void {}
86+
}
87+
class E6 extends core::_Enum /*isEnum*/ {
88+
static const field core::List<self::E6> values = #C14;
89+
static const field self::E6 element = #C13;
90+
const constructor •(core::int index, core::String name) → self::E6
91+
: super core::_Enum::•(index, name)
92+
;
93+
method toString() → core::String
94+
return "E6.${this.{core::_Enum::_name}{core::String}}";
95+
static set values(Never x) → void {}
96+
}
97+
class E7 extends core::_Enum /*isEnum*/ {
98+
static const field core::List<self::E7> values = #C16;
99+
static const field self::E7 element = #C15;
100+
const constructor •(core::int index, core::String name) → self::E7
101+
: super core::_Enum::•(index, name)
102+
;
103+
method toString() → core::String
104+
return "E7.${this.{core::_Enum::_name}{core::String}}";
105+
}
106+
static method main() → dynamic {}
107+
108+
constants {
109+
#C1 = 0
110+
#C2 = "element"
111+
#C3 = self::E1 {index:#C1, _name:#C2}
112+
#C4 = <self::E1>[#C3]
113+
#C5 = self::E2 {index:#C1, _name:#C2}
114+
#C6 = <self::E2>[#C5]
115+
#C7 = self::E3 {index:#C1, _name:#C2}
116+
#C8 = <self::E3>[#C7]
117+
#C9 = self::E4 {index:#C1, _name:#C2}
118+
#C10 = <self::E4>[#C9]
119+
#C11 = self::E5 {index:#C1, _name:#C2}
120+
#C12 = <self::E5>[#C11]
121+
#C13 = self::E6 {index:#C1, _name:#C2}
122+
#C14 = <self::E6>[#C13]
123+
#C15 = self::E7 {index:#C1, _name:#C2}
124+
#C16 = <self::E7>[#C15]
125+
}
126+
127+
128+
Constructor coverage from constants:
129+
org-dartlang-testcase:///declared_values.dart:
130+
- E1. (from org-dartlang-testcase:///declared_values.dart:5:6)
131+
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
132+
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
133+
- E2. (from org-dartlang-testcase:///declared_values.dart:11:6)
134+
- E3. (from org-dartlang-testcase:///declared_values.dart:17:6)
135+
- E4. (from org-dartlang-testcase:///declared_values.dart:24:6)
136+
- E5. (from org-dartlang-testcase:///declared_values.dart:30:6)
137+
- E6. (from org-dartlang-testcase:///declared_values.dart:36:6)
138+
- E7. (from org-dartlang-testcase:///declared_values.dart:42:6)

0 commit comments

Comments
 (0)