@@ -15,6 +15,8 @@ import 'package:source_gen/source_gen.dart';
15
15
/// See https://github.com/google/enum_class.dart/tree/master/example for how
16
16
/// to use it.
17
17
class EnumClassGenerator extends Generator {
18
+ Set <String > _usedGeneratedIdentifiers = new Set <String >();
19
+
18
20
Future <String > generate (Element element) async {
19
21
if (element is ! ClassElement ) {
20
22
return null ;
@@ -27,13 +29,13 @@ class EnumClassGenerator extends Generator {
27
29
.where ((i) => i.displayName == 'EnumClass' )
28
30
.isEmpty) return null ;
29
31
30
- final fields = getApplicableFields (classElement);
32
+ final fields = _getApplicableFields (classElement);
31
33
final errors = concat ([
32
- checkPart (classElement),
33
- checkFields (fields),
34
- checkConstructor (classElement),
35
- checkValuesGetter (classElement),
36
- checkValueOf (classElement)
34
+ _checkPart (classElement),
35
+ _checkFields (fields),
36
+ _checkConstructor (classElement),
37
+ _checkValuesGetter (classElement),
38
+ _checkValueOf (classElement)
37
39
]);
38
40
39
41
if (errors.isNotEmpty) {
@@ -42,10 +44,10 @@ class EnumClassGenerator extends Generator {
42
44
todo: errors.join (' ' ));
43
45
}
44
46
45
- return generateCode ( enumName, fields. map ((field) => field.displayName) );
47
+ return _generateCode (classElement, enumName, fields);
46
48
}
47
49
48
- Iterable <String > checkPart (ClassElement classElement) {
50
+ Iterable <String > _checkPart (ClassElement classElement) {
49
51
final fileName =
50
52
classElement.library.source.shortName.replaceAll ('.dart' , '' );
51
53
final expectedCode = "part '$fileName .g.dart';" ;
@@ -54,7 +56,7 @@ class EnumClassGenerator extends Generator {
54
56
: < String > ['Import generated part: $expectedCode ' ];
55
57
}
56
58
57
- Iterable <FieldElement > getApplicableFields (ClassElement classElement) {
59
+ Iterable <FieldElement > _getApplicableFields (ClassElement classElement) {
58
60
final enumName = classElement.displayName;
59
61
final result = < FieldElement > [];
60
62
for (final field in classElement.fields) {
@@ -64,7 +66,7 @@ class EnumClassGenerator extends Generator {
64
66
return result;
65
67
}
66
68
67
- Iterable <String > checkFields (Iterable <FieldElement > fields) {
69
+ Iterable <String > _checkFields (Iterable <FieldElement > fields) {
68
70
final result = < String > [];
69
71
for (final field in fields) {
70
72
final fieldName = field.displayName;
@@ -76,66 +78,128 @@ class EnumClassGenerator extends Generator {
76
78
continue ;
77
79
}
78
80
79
- if (field.computeNode ().toString () != '$fieldName = _\$ $fieldName ' ) {
80
- result.add (
81
- 'Initialize field "$fieldName " with generated value "_\$ $fieldName ".' );
81
+ if (! field.computeNode ().toString ().startsWith ('$fieldName = _\$ ' )) {
82
+ result
83
+ .add ('Initialize field "$fieldName " with a value starting "_\$ ".' );
84
+ }
85
+
86
+ final identifier = _getGeneratedIdentifier (field);
87
+ if (_usedGeneratedIdentifiers.contains (identifier)) {
88
+ result
89
+ .add ('Generated identifier "_\$ $identifier " is used multiple times,'
90
+ ' change to something else.' );
82
91
}
92
+ _usedGeneratedIdentifiers.add (identifier);
83
93
}
84
94
return result;
85
95
}
86
96
87
- Iterable <String > checkConstructor (ClassElement classElement) {
97
+ Iterable <String > _checkConstructor (ClassElement classElement) {
88
98
final enumName = classElement.displayName;
89
99
final expectedCode = 'const $enumName ._(String name) : super(name);' ;
90
100
return classElement.constructors.length == 1 &&
91
101
classElement.constructors.single.computeNode ().toString () ==
92
102
expectedCode ? < String > [] : < String > ['Constructor: $expectedCode ' ];
93
103
}
94
104
95
- Iterable <String > checkValuesGetter (ClassElement classElement) {
105
+ Iterable <String > _checkValuesGetter (ClassElement classElement) {
96
106
// TODO(davidmorgan): do this without reading the whole source.
97
107
final enumName = classElement.displayName;
98
- final expectedCode = 'static BuiltSet<$enumName > get values => _\$ values;' ;
99
- return classElement.source.contents.data.contains (expectedCode)
100
- ? < String > []
101
- : < String > ['Getter: $expectedCode ' ];
108
+ final valuesIdentifier =
109
+ _getValuesIdentifier (classElement.source.contents.data, enumName);
110
+ if (valuesIdentifier == null ) {
111
+ return < String > [
112
+ 'Getter: static BuiltSet<$enumName > get values => _\$ values'
113
+ ];
114
+ } else {
115
+ if (_usedGeneratedIdentifiers.contains (valuesIdentifier)) {
116
+ return < String > [
117
+ 'Generated identifier "_\$ $valuesIdentifier " is used multiple times,'
118
+ ' change to something else.'
119
+ ];
120
+ } else {
121
+ return < String > [];
122
+ }
123
+ }
102
124
}
103
125
104
- Iterable <String > checkValueOf (ClassElement classElement) {
126
+ Iterable <String > _checkValueOf (ClassElement classElement) {
105
127
// TODO(davidmorgan): do this without reading the whole source.
106
128
final enumName = classElement.displayName;
107
- final expectedCode =
108
- 'static $enumName valueOf(String name) => _\$ valueOf(name);' ;
109
- return classElement.source.contents.data.contains (expectedCode)
110
- ? < String > []
111
- : < String > ['Method: $expectedCode ' ];
129
+
130
+ final valueOfIdentifier =
131
+ _getValueOfIdentifier (classElement.source.contents.data, enumName);
132
+
133
+ if (valueOfIdentifier == null ) {
134
+ return < String > [
135
+ 'Method: static $enumName valueOf(String name) => _\$ valueOf(name)'
136
+ ];
137
+ } else {
138
+ if (_usedGeneratedIdentifiers.contains (valueOfIdentifier)) {
139
+ return < String > [
140
+ 'Generated identifier "_\$ $valueOfIdentifier " is used multiple times,'
141
+ ' change to something else.'
142
+ ];
143
+ } else {
144
+ return < String > [];
145
+ }
146
+ }
112
147
}
113
148
114
- String generateCode (String enumName, Iterable <String > fieldNames) {
149
+ String _generateCode (ClassElement classElement, String enumName,
150
+ Iterable <FieldElement > fields) {
115
151
final result = new StringBuffer ();
116
152
117
- for (final fieldName in fieldNames) {
118
- result.writeln ('const $enumName _\$ $fieldName = '
153
+ for (final field in fields) {
154
+ final fieldName = field.displayName;
155
+ result.writeln ('const $enumName _\$ ${_getGeneratedIdentifier (field )} = '
119
156
'const $enumName ._(\' $fieldName \' );' );
120
157
}
121
158
122
159
result.writeln ('' );
123
- result.writeln ('$enumName _\$ valueOf(String name) {'
160
+
161
+ final valueOf =
162
+ _getValueOfIdentifier (classElement.source.contents.data, enumName);
163
+ result.writeln ('$enumName _\$ $valueOf (String name) {'
124
164
'switch (name) {' );
125
- for (final fieldName in fieldNames) {
126
- result.writeln ('case \' $fieldName \' : return _\$ $fieldName ;' );
165
+ for (final field in fields) {
166
+ final fieldName = field.displayName;
167
+ result.writeln (
168
+ 'case \' $fieldName \' : return _\$ ${_getGeneratedIdentifier (field )};' );
127
169
}
128
170
result.writeln ('default: throw new ArgumentError(name);' );
129
171
result.writeln ('}}' );
130
172
131
173
result.writeln ('' );
132
- result.writeln ('final BuiltSet<$enumName > _\$ values ='
174
+
175
+ final values =
176
+ _getValuesIdentifier (classElement.source.contents.data, enumName);
177
+ result.writeln ('final BuiltSet<$enumName > _\$ $values ='
133
178
'new BuiltSet<$enumName >(const [' );
134
- for (final fieldName in fieldNames ) {
135
- result.writeln ('_\$ $fieldName ,' );
179
+ for (final field in fields ) {
180
+ result.writeln ('_\$ ${ _getGeneratedIdentifier ( field )} ,' );
136
181
}
137
182
result.writeln (']);' );
138
183
139
184
return result.toString ();
140
185
}
186
+
187
+ String _getGeneratedIdentifier (FieldElement field) {
188
+ final fieldName = field.displayName;
189
+ return field.computeNode ().toString ().substring ('$fieldName = _\$ ' .length);
190
+ }
191
+
192
+ String _getValueOfIdentifier (String source, String enumName) {
193
+ final matches = new RegExp (r'static ' +
194
+ enumName +
195
+ r' valueOf\(String name\) \=\> \_\$(\w+)\(name\)\;' ).allMatches (source);
196
+ return matches.isEmpty ? null : matches.first.group (1 );
197
+ }
198
+
199
+ String _getValuesIdentifier (String source, String enumName) {
200
+ final matches = new RegExp (
201
+ r'static BuiltSet<' + enumName + r'> get values => _\$(\w+)\;' )
202
+ .allMatches (source);
203
+ return matches.isEmpty ? null : matches.first.group (1 );
204
+ }
141
205
}
0 commit comments