chaokunyang commented on code in PR #3482:
URL: https://github.com/apache/fory/pull/3482#discussion_r3051235091
##########
dart/packages/fory/lib/src/codegen/analyze/impl/struct/enum_analyzer_impl.dart:
##########
@@ -17,26 +17,103 @@
* under the License.
*/
+import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:fory/src/codegen/analyze/analysis_type_identifier.dart';
import 'package:fory/src/codegen/analyze/interface/enum_analyzer.dart';
import 'package:fory/src/codegen/meta/impl/enum_spec_generator.dart';
class EnumAnalyzerImpl implements EnumAnalyzer {
const EnumAnalyzerImpl();
+ /// Finds a non-constant field annotated with @ForyEnumId().
+ String? _findIdField(EnumElement enumElement) {
+ for (final FieldElement field in enumElement.fields) {
+ if (field.isEnumConstant || field.isSynthetic) continue;
+ for (final ElementAnnotation annotation in field.metadata) {
+ final DartObject? annotationValue = annotation.computeConstantValue();
+ final Element? typeElement = annotationValue?.type?.element;
+ if (typeElement is ClassElement &&
+ AnalysisTypeIdentifier.isForyEnumId(typeElement)) {
+ return field.name;
+ }
+ }
+ }
+ return null;
+ }
+
+ /// Reads @ForyEnumId(id) from per-value annotation.
+ int? _readEnumId(FieldElement enumField) {
+ for (final ElementAnnotation annotation in enumField.metadata) {
+ final DartObject? annotationValue = annotation.computeConstantValue();
+ final Element? typeElement = annotationValue?.type?.element;
+ if (typeElement is ClassElement &&
+ AnalysisTypeIdentifier.isForyEnumId(typeElement)) {
+ return annotationValue?.getField('id')?.toIntValue();
+ }
+ }
+ return null;
+ }
+
@override
EnumSpecGenerator analyze(EnumElement enumElement) {
String packageName = enumElement.location!.components[0];
+ final String enumName = enumElement.name;
+ final List<FieldElement> enumFields =
+ enumElement.fields.where((FieldElement e) =>
e.isEnumConstant).toList();
+ final List<String> enumValues =
+ enumFields.map((FieldElement e) => e.name).toList();
+
+ final String? idFieldName = _findIdField(enumElement);
+ final Map<String, int> enumIds = <String, int>{};
+ final Map<int, String> usedIds = <int, String>{};
+ final List<String> duplicateIds = <String>[];
+ final List<String> missingIdValues = <String>[];
+
+ for (final FieldElement enumField in enumFields) {
+ final int? id = idFieldName != null
Review Comment:
[P1] Validate @ForyEnumId range before generating enum specs
This accepts any `int` from `@ForyEnumId` and later feeds it to
`writeVarUint32Small7(...)`. Negative values do not fail cleanly here: I
reproduced `writeVarUint32Small7(-1)` decoding back as `34359738367`, so
`@ForyEnumId(-1)` silently writes a different wire id than the one the user
declared. Please reject ids outside the unsigned 32-bit range during analysis,
and ideally keep a serializer-side assertion as defense in depth.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]