This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new 8ef0bf593 feat(dart): add uint annotation types to the fory's codegen 
system (#3181)
8ef0bf593 is described below

commit 8ef0bf5932d6044e9282dac4cec41f5bf17af502
Author: Ayush Kumar <[email protected]>
AuthorDate: Thu Jan 22 16:18:34 2026 +0530

    feat(dart): add uint annotation types to the fory's codegen system (#3181)
    
    ## Why?
    
    While unsigned integer type annotations (`@Uint8Type`, `@Uint16Type`,
    `@Uint32Type`, `@Uint64Type`) were added in PR #3144, they were not
    integrated into the code generation system. This meant:
    
    * The annotation definitions existed but were not recognized by the code
    generator
    * No support for annotation-based type specification like `@Uint8Type()
    int age` in struct fields
    * Users couldn't use the protobuf/flatbuffer-style ergonomic API that
    was intended
    * No way to specify encoding variants (fixed vs varint) for
    uint32/uint64 via annotations during code generation
    
    ## What does this PR do?
    
    ### 1. Created Uint Annotation Analyzer
    
    Added `uint_annotation_analyzer.dart` to detect and parse uint type
    annotations during code generation:
    
    ```dart
    class UintAnnotationAnalyzer {
      UintAnnotationResult analyze(
        List<ElementAnnotation> metadata,
        LocationMark locationMark,
      ) {
        // Detects @Uint8Type, @Uint16Type, @Uint32Type, @Uint64Type
        // Extracts encoding options (fixed, varint, tagged)
        // Returns appropriate ObjType
      }
    }
    ```
    
    **Supported annotations:**
    * `@Uint8Type()` → `ObjType.UINT8`
    * `@Uint16Type()` → `ObjType.UINT16`
    * `@Uint32Type()` → `ObjType.UINT32`
    * `@Uint32Type(encoding: UintEncoding.varint)` → `ObjType.VAR_UINT32`
    * `@Uint64Type()` → `ObjType.UINT64`
    * `@Uint64Type(encoding: UintEncoding.varint)` → `ObjType.VAR_UINT64`
    * `@Uint64Type(encoding: UintEncoding.tagged)` → `ObjType.TAGGED_UINT64`
    
    ### 2. Extended Type Identifier System
    
    Updated `analysis_type_identifier.dart` to recognize uint annotation
    types:
    
    ```dart
    static final List<Type3StringKey> _keys = [
      // ... existing annotations
      Type3StringKey('Uint8Type', 'package', 
'fory/src/annotation/uint_types.dart'),
      Type3StringKey('Uint16Type', 'package', 
'fory/src/annotation/uint_types.dart'),
      Type3StringKey('Uint32Type', 'package', 
'fory/src/annotation/uint_types.dart'),
      Type3StringKey('Uint64Type', 'package', 
'fory/src/annotation/uint_types.dart'),
    ];
    ```
    
    ### 3. Integrated Annotation-Based Type Override
    
    Modified `type_analyzer_impl.dart` to support annotation-based type
    override:
    
    ```dart
    TypeSpecGen getTypeImmutableAndTagWithOverride(
      TypeDecision typeDecision,
      LocationMark locationMark,
      ObjType objTypeOverride,
    ) {
      // Uses annotation-specified ObjType instead of default type resolution
    }
    ```
    
    ### 4. Updated Field Analyzer
    
    Modified `field_analyzer_impl.dart` to check for uint annotations:
    
    ```dart
    // Check for uint annotations
    final uintAnnotationResult = Analyzer.uintAnnotationAnalyzer.analyze(
      element.metadata,
      locationMark,
    );
    
    if (uintAnnotationResult.hasAnnotation) {
      // Use annotation-based type override
      fieldType = Analyzer.typeAnalyzer.getTypeImmutableAndTagWithOverride(
        typeDecision, locationMark, uintAnnotationResult.objType!,
      );
    }
    ```
    
    ## Related issues
    
    Completes the unsigned integer annotation types support initiated in PR
    #3144 by integrating the annotations into the code generation system.
    
    ## Does this PR introduce any user-facing change?
    
    * [x] Does this PR introduce any public API change?
    * **Dart**: Users can now use `@Uint8Type()`, `@Uint16Type()`,
    `@Uint32Type()`, `@Uint64Type()` annotations on native `int` fields in
    `@ForyClass` structs
    * Enables encoding variant specification via `encoding` parameter for
    uint32/uint64
    * Provides more ergonomic API: `@Uint8Type() int age` instead of `UInt8
    age`
    
    * [ ] Does this PR introduce any binary protocol compatibility change?
      * No changes to binary encoding format
      * Uses existing ObjType mappings and serializers
    * Type IDs remain the same: UINT8 (40), UINT16 (41), UINT32 (42),
    VAR_UINT32 (43), UINT64 (44), VAR_UINT64 (45), TAGGED_UINT64 (46)
    
    ## Benchmark
    
    N/A - This PR only adds annotation processing during code generation
    (build-time). No runtime performance impact.
    
    ---------
    
    Co-authored-by: Shawn Yang <[email protected]>
---
 .../uint_annotation_analyzer_test.dart             | 136 +++++++++++++++++++
 .../codegen/analyze/analysis_type_identifier.dart  |  38 +++++-
 .../fory/lib/src/codegen/analyze/analyzer.dart     |   2 +
 .../impl/annotation/uint_annotation_analyzer.dart  | 149 +++++++++++++++++++++
 .../analyze/impl/field/field_analyzer_impl.dart    |  30 ++++-
 .../analyze/impl/type/type_analyzer_impl.dart      |  36 +++++
 .../codegen/analyze/interface/type_analyzer.dart   |  10 ++
 .../exception/constraint_violation_exception.dart  |  10 ++
 8 files changed, 408 insertions(+), 3 deletions(-)

diff --git 
a/dart/packages/fory-test/test/codegen_test/uint_annotation_analyzer_test.dart 
b/dart/packages/fory-test/test/codegen_test/uint_annotation_analyzer_test.dart
new file mode 100644
index 000000000..84621f0f9
--- /dev/null
+++ 
b/dart/packages/fory-test/test/codegen_test/uint_annotation_analyzer_test.dart
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+library;
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:build_test/build_test.dart';
+import 
'package:fory/src/codegen/analyze/impl/annotation/uint_annotation_analyzer.dart';
+import 'package:fory/src/codegen/entity/location_mark.dart';
+import 'package:fory/src/const/obj_type.dart';
+import 'package:test/test.dart';
+
+void main() {
+  group('UintAnnotationAnalyzer integration tests', () {
+    const analyzer = UintAnnotationAnalyzer();
+
+    Future<UintAnnotationResult> analyzeField(String source, String fieldName) 
async {
+      final library = await resolveSource(source, (resolver) => 
resolver.findLibraryByName('test_lib'));
+      final classElement = library!.topLevelElements.firstWhere((e) => e is 
ClassElement) as ClassElement;
+      final fieldElement = classElement.fields.firstWhere((f) => f.name == 
fieldName);
+      
+      final locationMark = LocationMark.fieldLevel(
+        'test_lib',
+        'TestClass',
+        fieldName,
+      );
+      
+      return analyzer.analyze(fieldElement.metadata, locationMark);
+    }
+
+    const String commonSource = '''
+library test_lib;
+import 'package:fory/fory.dart';
+
+class TestClass {
+  @Uint8Type()
+  int f8;
+
+  @Uint16Type()
+  int f16;
+
+  @Uint32Type()
+  int f32;
+
+  @Uint32Type(encoding: UintEncoding.varint)
+  int f32v;
+
+  @Uint64Type()
+  int f64;
+
+  @Uint64Type(encoding: UintEncoding.varint)
+  int f64v;
+
+  @Uint64Type(encoding: UintEncoding.tagged)
+  int f64t;
+
+  int fNone;
+
+  @Uint8Type()
+  @Uint16Type()
+  int fDup;
+}
+''';
+
+    test('analyzes @Uint8Type correctly', () async {
+      final result = await analyzeField(commonSource, 'f8');
+      expect(result.hasAnnotation, isTrue);
+      expect(result.objType, equals(ObjType.UINT8));
+    });
+
+    test('analyzes @Uint16Type correctly', () async {
+      final result = await analyzeField(commonSource, 'f16');
+      expect(result.hasAnnotation, isTrue);
+      expect(result.objType, equals(ObjType.UINT16));
+    });
+
+    test('analyzes @Uint32Type (default) correctly', () async {
+      final result = await analyzeField(commonSource, 'f32');
+      expect(result.hasAnnotation, isTrue);
+      expect(result.objType, equals(ObjType.UINT32));
+    });
+
+    test('analyzes @Uint32Type (varint) correctly', () async {
+      final result = await analyzeField(commonSource, 'f32v');
+      expect(result.hasAnnotation, isTrue);
+      expect(result.objType, equals(ObjType.VAR_UINT32));
+    });
+
+    test('analyzes @Uint64Type (default) correctly', () async {
+      final result = await analyzeField(commonSource, 'f64');
+      expect(result.hasAnnotation, isTrue);
+      expect(result.objType, equals(ObjType.UINT64));
+    });
+
+    test('analyzes @Uint64Type (varint) correctly', () async {
+      final result = await analyzeField(commonSource, 'f64v');
+      expect(result.hasAnnotation, isTrue);
+      expect(result.objType, equals(ObjType.VAR_UINT64));
+    });
+
+    test('analyzes @Uint64Type (tagged) correctly', () async {
+      final result = await analyzeField(commonSource, 'f64t');
+      expect(result.hasAnnotation, isTrue);
+      expect(result.objType, equals(ObjType.TAGGED_UINT64));
+    });
+
+    test('returns none for unannotated field', () async {
+      final result = await analyzeField(commonSource, 'fNone');
+      expect(result.hasAnnotation, isFalse);
+      expect(result.objType, isNull);
+    });
+
+    test('throws exception for duplicated uint annotations', () async {
+      expect(
+        () => analyzeField(commonSource, 'fDup'),
+        throwsA(anything), // Should throw DuplicatedAnnotationException
+      );
+    });
+  });
+}
diff --git 
a/dart/packages/fory/lib/src/codegen/analyze/analysis_type_identifier.dart 
b/dart/packages/fory/lib/src/codegen/analyze/analysis_type_identifier.dart
index 82b6fff8b..4a55a760a 100644
--- a/dart/packages/fory/lib/src/codegen/analyze/analysis_type_identifier.dart
+++ b/dart/packages/fory/lib/src/codegen/analyze/analysis_type_identifier.dart
@@ -35,7 +35,7 @@ class AnalysisTypeIdentifier{
   static int get dartCoreLibId => objectType.element.library.id;
 
 
-  static final List<int?> _ids = [null,null,null,null];
+  static final List<int?> _ids = [null,null,null,null,null,null,null,null];
   static final List<Type3StringKey> _keys = [
     Type3StringKey(
       'ForyClass',
@@ -57,6 +57,26 @@ class AnalysisTypeIdentifier{
       'package',
       'fory/src/annotation/fory_enum.dart',
     ),
+    Type3StringKey(
+      'Uint8Type',
+      'package',
+      'fory/src/annotation/uint_types.dart',
+    ),
+    Type3StringKey(
+      'Uint16Type',
+      'package',
+      'fory/src/annotation/uint_types.dart',
+    ),
+    Type3StringKey(
+      'Uint32Type',
+      'package',
+      'fory/src/annotation/uint_types.dart',
+    ),
+    Type3StringKey(
+      'Uint64Type',
+      'package',
+      'fory/src/annotation/uint_types.dart',
+    ),
   ];
 
   static bool _check(ClassElement element, int index){
@@ -100,4 +120,20 @@ class AnalysisTypeIdentifier{
     _ids[0] = id;
   }
 
+  static bool isUint8Type(ClassElement element){
+    return _check(element, 4);
+  }
+
+  static bool isUint16Type(ClassElement element){
+    return _check(element, 5);
+  }
+
+  static bool isUint32Type(ClassElement element){
+    return _check(element, 6);
+  }
+
+  static bool isUint64Type(ClassElement element){
+    return _check(element, 7);
+  }
+
 }
\ No newline at end of file
diff --git a/dart/packages/fory/lib/src/codegen/analyze/analyzer.dart 
b/dart/packages/fory/lib/src/codegen/analyze/analyzer.dart
index 46add8502..55b6701ae 100644
--- a/dart/packages/fory/lib/src/codegen/analyze/analyzer.dart
+++ b/dart/packages/fory/lib/src/codegen/analyze/analyzer.dart
@@ -20,6 +20,7 @@
 import 
'package:fory/src/codegen/analyze/impl/annotation/class_annotation_analyzer.dart';
 import 
'package:fory/src/codegen/analyze/impl/annotation/enum_annotation_analyzer.dart';
 import 
'package:fory/src/codegen/analyze/impl/annotation/key_annotation_analyzer.dart';
+import 
'package:fory/src/codegen/analyze/impl/annotation/uint_annotation_analyzer.dart';
 import 
'package:fory/src/codegen/analyze/impl/constructor/constructor_analyzer.dart';
 import 'package:fory/src/codegen/analyze/impl/field/access_info_analyzer.dart';
 import 'package:fory/src/codegen/analyze/impl/field/field_analyzer_impl.dart';
@@ -44,6 +45,7 @@ abstract class Analyzer {
   static const ClassAnnotationAnalyzer classAnnotationAnalyzer = 
ClassAnnotationAnalyzer();
   static const KeyAnnotationAnalyzer keyAnnotationAnalyzer = 
KeyAnnotationAnalyzer();
   static const EnumAnnotationAnalyzer enumAnnotationAnalyzer = 
EnumAnnotationAnalyzer();
+  static const UintAnnotationAnalyzer uintAnnotationAnalyzer = 
UintAnnotationAnalyzer();
 
   // Enum analyzers
   static const EnumAnalyzer enumAnalyzer = EnumAnalyzerImpl();
diff --git 
a/dart/packages/fory/lib/src/codegen/analyze/impl/annotation/uint_annotation_analyzer.dart
 
b/dart/packages/fory/lib/src/codegen/analyze/impl/annotation/uint_annotation_analyzer.dart
new file mode 100644
index 000000000..208de6a85
--- /dev/null
+++ 
b/dart/packages/fory/lib/src/codegen/analyze/impl/annotation/uint_annotation_analyzer.dart
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * 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/annotation/location_level_ensure.dart';
+import 'package:fory/src/codegen/const/location_level.dart';
+import 'package:fory/src/codegen/entity/location_mark.dart';
+import 'package:fory/src/codegen/exception/annotation_exception.dart';
+import 'package:fory/src/const/obj_type.dart';
+
+/// Result of uint annotation analysis
+class UintAnnotationResult {
+  final ObjType? objType;
+  final bool hasAnnotation;
+
+  const UintAnnotationResult(this.objType, this.hasAnnotation);
+
+  static const none = UintAnnotationResult(null, false);
+}
+
+class UintAnnotationAnalyzer {
+  const UintAnnotationAnalyzer();
+
+  /// Analyzes uint type annotations on a field.
+  /// Returns the appropriate ObjType if a uint annotation is found, null 
otherwise.
+  UintAnnotationResult analyze(
+    List<ElementAnnotation> metadata,
+    @LocationEnsure(LocationLevel.fieldLevel) LocationMark locationMark,
+  ) {
+    assert(locationMark.ensureFieldLevel);
+    
+    DartObject? uintAnno;
+    String? annotationType;
+    
+    for (ElementAnnotation annoElement in metadata) {
+      final anno = annoElement.computeConstantValue()!;
+      final annoClsElement = anno.type!.element as ClassElement;
+      
+      if (AnalysisTypeIdentifier.isUint8Type(annoClsElement)) {
+        if (uintAnno != null) {
+          throw DuplicatedAnnotationException(
+            'Uint type annotation',
+            locationMark.fieldName!,
+            locationMark.clsLocation,
+          );
+        }
+        uintAnno = anno;
+        annotationType = 'Uint8Type';
+      } else if (AnalysisTypeIdentifier.isUint16Type(annoClsElement)) {
+        if (uintAnno != null) {
+          throw DuplicatedAnnotationException(
+            'Uint type annotation',
+            locationMark.fieldName!,
+            locationMark.clsLocation,
+          );
+        }
+        uintAnno = anno;
+        annotationType = 'Uint16Type';
+      } else if (AnalysisTypeIdentifier.isUint32Type(annoClsElement)) {
+        if (uintAnno != null) {
+          throw DuplicatedAnnotationException(
+            'Uint type annotation',
+            locationMark.fieldName!,
+            locationMark.clsLocation,
+          );
+        }
+        uintAnno = anno;
+        annotationType = 'Uint32Type';
+      } else if (AnalysisTypeIdentifier.isUint64Type(annoClsElement)) {
+        if (uintAnno != null) {
+          throw DuplicatedAnnotationException(
+            'Uint type annotation',
+            locationMark.fieldName!,
+            locationMark.clsLocation,
+          );
+        }
+        uintAnno = anno;
+        annotationType = 'Uint64Type';
+      }
+    }
+
+    if (uintAnno == null) {
+      return UintAnnotationResult.none;
+    }
+
+    // Determine the ObjType based on the annotation
+    ObjType objType;
+    switch (annotationType) {
+      case 'Uint8Type':
+        objType = ObjType.UINT8;
+        break;
+      case 'Uint16Type':
+        objType = ObjType.UINT16;
+        break;
+      case 'Uint32Type':
+        // Check encoding parameter
+        final encodingField = uintAnno.getField('encoding');
+        if (encodingField != null && !encodingField.isNull) {
+          final encodingValue = 
encodingField.getField('_name')?.toStringValue();
+          if (encodingValue == 'varint') {
+            objType = ObjType.VAR_UINT32;
+          } else {
+            objType = ObjType.UINT32;
+          }
+        } else {
+          objType = ObjType.UINT32;
+        }
+        break;
+      case 'Uint64Type':
+        // Check encoding parameter
+        final encodingField = uintAnno.getField('encoding');
+        if (encodingField != null && !encodingField.isNull) {
+          final encodingValue = 
encodingField.getField('_name')?.toStringValue();
+          if (encodingValue == 'varint') {
+            objType = ObjType.VAR_UINT64;
+          } else if (encodingValue == 'tagged') {
+            objType = ObjType.TAGGED_UINT64;
+          } else {
+            objType = ObjType.UINT64;
+          }
+        } else {
+          objType = ObjType.UINT64;
+        }
+        break;
+      default:
+        return UintAnnotationResult.none;
+    }
+
+    return UintAnnotationResult(objType, true);
+  }
+}
diff --git 
a/dart/packages/fory/lib/src/codegen/analyze/impl/field/field_analyzer_impl.dart
 
b/dart/packages/fory/lib/src/codegen/analyze/impl/field/field_analyzer_impl.dart
index 838b4f54a..aacfebf3e 100644
--- 
a/dart/packages/fory/lib/src/codegen/analyze/impl/field/field_analyzer_impl.dart
+++ 
b/dart/packages/fory/lib/src/codegen/analyze/impl/field/field_analyzer_impl.dart
@@ -90,11 +90,37 @@ class FieldAnalyzerImpl implements FieldAnalyzer{
       return null;
     }
 
-    TypeSpecGen fieldType = Analyzer.typeAnalyzer.getTypeImmutableAndTag(
-      Analyzer.typeSystemAnalyzer.decideInterfaceType(element.type),
+    // Check for uint annotations
+    final uintAnnotationResult = Analyzer.uintAnnotationAnalyzer.analyze(
+      element.metadata,
       locationMark,
     );
 
+    TypeSpecGen fieldType;
+    if (uintAnnotationResult.hasAnnotation) {
+      // Validate that @uint is only used on int fields
+      if (!element.type.isDartCoreInt) {
+        throw ConstraintViolationException(
+          locationMark.libPath,
+          locationMark.clsName,
+          element.name,
+          'Please Validate @uint usage only on int fields',
+        );
+      }
+      // Use annotation-based type override
+      fieldType = Analyzer.typeAnalyzer.getTypeImmutableAndTagWithOverride(
+        Analyzer.typeSystemAnalyzer.decideInterfaceType(element.type),
+        locationMark,
+        uintAnnotationResult.objType!,
+      );
+    } else {
+      // Use default type resolution
+      fieldType = Analyzer.typeAnalyzer.getTypeImmutableAndTag(
+        Analyzer.typeSystemAnalyzer.decideInterfaceType(element.type),
+        locationMark,
+      );
+    }
+    
     return Either.left(
       FieldSpecImmutable.publicOr(
         element.isPublic,
diff --git 
a/dart/packages/fory/lib/src/codegen/analyze/impl/type/type_analyzer_impl.dart 
b/dart/packages/fory/lib/src/codegen/analyze/impl/type/type_analyzer_impl.dart
index 54bbd7d7e..7330a3156 100644
--- 
a/dart/packages/fory/lib/src/codegen/analyze/impl/type/type_analyzer_impl.dart
+++ 
b/dart/packages/fory/lib/src/codegen/analyze/impl/type/type_analyzer_impl.dart
@@ -29,6 +29,7 @@ import 'package:fory/src/codegen/const/location_level.dart';
 import 'package:fory/src/codegen/entity/location_mark.dart';
 import 'package:fory/src/codegen/meta/impl/type_immutable.dart';
 import 'package:fory/src/codegen/meta/impl/type_spec_gen.dart';
+import 'package:fory/src/const/obj_type.dart';
 
 class TypeAnalyzerImpl extends TypeAnalyzer{
 
@@ -92,6 +93,41 @@ class TypeAnalyzerImpl extends TypeAnalyzer{
     );
   }
 
+  /// Version of getTypeImmutableAndTag that supports annotation-based ObjType 
override.
+  /// Used when uint annotations are present on int fields.
+  TypeSpecGen getTypeImmutableAndTagWithOverride(
+    TypeDecision typeDecision,
+    @LocationEnsure(LocationLevel.fieldLevel) LocationMark locationMark,
+    ObjType objTypeOverride,
+  ){
+    InterfaceType type = typeDecision.type;
+
+    InterfaceElement element = type.element;
+    int libId = element.library.id;
+    bool nullable = (typeDecision.forceNullable) ? true:  
type.nullabilitySuffix == NullabilitySuffix.question;
+
+    List<TypeSpecGen> typeArgsTypes = [];
+    for (DartType arg in type.typeArguments){
+      typeArgsTypes.add(
+        _analyze(
+          Analyzer.typeSystemAnalyzer.decideInterfaceType(arg),
+          locationMark,
+        ),
+      );
+    }
+    return TypeSpecGen(
+      TypeImmutable(
+        element.name,
+        libId,
+        objTypeOverride,
+        objTypeOverride.independent,
+        true, // certainForSer is true for annotation-based types
+      ),
+      nullable,
+      typeArgsTypes,
+    );
+  }
+
   TypeImmutable _analyzeTypeImmutable(
     InterfaceElement element,
     @LocationEnsure(LocationLevel.fieldLevel) LocationMark locationMark,
diff --git 
a/dart/packages/fory/lib/src/codegen/analyze/interface/type_analyzer.dart 
b/dart/packages/fory/lib/src/codegen/analyze/interface/type_analyzer.dart
index bc17b824e..819267ee9 100644
--- a/dart/packages/fory/lib/src/codegen/analyze/interface/type_analyzer.dart
+++ b/dart/packages/fory/lib/src/codegen/analyze/interface/type_analyzer.dart
@@ -22,6 +22,7 @@ import 
'package:fory/src/codegen/analyze/annotation/location_level_ensure.dart';
 import 'package:fory/src/codegen/const/location_level.dart';
 import 'package:fory/src/codegen/entity/location_mark.dart';
 import 'package:fory/src/codegen/meta/impl/type_spec_gen.dart';
+import 'package:fory/src/const/obj_type.dart';
 
 abstract class TypeAnalyzer{
 
@@ -29,4 +30,13 @@ abstract class TypeAnalyzer{
     TypeDecision typeDecision,
     @LocationEnsure(LocationLevel.fieldLevel) LocationMark locationMark,
   );
+
+  /// Version of getTypeImmutableAndTag that supports annotation-based ObjType 
override.
+  /// Used when uint annotations are present on int fields.
+  TypeSpecGen getTypeImmutableAndTagWithOverride(
+    TypeDecision typeDecision,
+    @LocationEnsure(LocationLevel.fieldLevel) LocationMark locationMark,
+    ObjType objTypeOverride,
+  );
+
 }
\ No newline at end of file
diff --git 
a/dart/packages/fory/lib/src/codegen/exception/constraint_violation_exception.dart
 
b/dart/packages/fory/lib/src/codegen/exception/constraint_violation_exception.dart
index a6d3bc305..e068a4d52 100644
--- 
a/dart/packages/fory/lib/src/codegen/exception/constraint_violation_exception.dart
+++ 
b/dart/packages/fory/lib/src/codegen/exception/constraint_violation_exception.dart
@@ -197,3 +197,13 @@ class UnsupportedTypeException extends 
ForyCodegenException {
     return buf.toString();
   }
 }
+
+class ConstraintViolationException extends FieldException {
+  ConstraintViolationException(
+    String libPath,
+    String className,
+    String fieldName,
+    String constraint, [
+    String? where,
+  ]) : super(libPath, className, [fieldName], constraint, where);
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to