codec_gen 0.2.0
codec_gen: ^0.2.0 copied to clipboard
Code generator for the codec package: reads @Codable / @CodecEnum annotations and generates type-safe JSON codec fields with $.path error locations, via build_runner.
Changelog #
0.2.0 #
Dependency Upgrades #
- analyzer 13 / build 4 / source_gen 4 / build_test 3: Migrated to the new
analyzer element model (
Element2/LibraryElement2and related interfaces), aligning with the Dart SDK 3.6+ toolchain. codecdependency bumped to^0.2.0: Matches the runtime exception system refactor (CodecExceptionas a standalone type,withFormatExceptions()combinator).
Added #
build.yamloptionexception_style(codec|format, defaultcodec): When set toformat, every top-level codec (_$xxxCodec) generated by this builder automatically has.withFormatExceptions()appended, sodecode/encodethrow Dart's built-inFormatExceptioninstead ofCodecException. This provides a zero-touch migration path for existing code that catcheson FormatException, with no changes required at call sites.
0.1.6 #
Added #
@CodecField(enumValueField:)supportsunknownEnumValue:: Declare a fallback enum value for unrecognised codes. The generated top-level helper emitsCodec.enumOf<E, V>(..., unknownFallback: E.xxx). When omitted the parameter is not emitted, keeping generated code and behaviour identical to 0.1.5 (fully backward-compatible). Runtime support is provided by codec 0.1.6.
Codegen-time validation (new error paths) #
unknownEnumValueset withoutenumValueField(including cases where the field is overridden bycodec:) throwsInvalidGenerationSourceErrorduringbuild_runner; it is never silently ignored.unknownEnumValuewhose enum type does not match the field's enum type throwsInvalidGenerationSourceError, preventing the generation of code that would not compile.
Tests #
- Added 3 generator golden tests:
enumValueField+unknownEnumValueproducingunknownFallback:, standaloneunknownEnumValuethrowing, and mismatched enum type throwing. Total codec_gen test suite: 64 cases.
Version #
- Generator code changed;
versionbumped 0.1.5 → 0.1.6, aligned with CHANGELOG and codec 0.1.6.
0.1.5 #
Added #
- Field-level
@CodecField(enumValueField: 'code'): Maps an enum field by the value of a named property on each enum instance. The enum does not need@CodecEnum(keeping core/domain layers free of codec imports and part files). Mirrors the existingdateTime:pattern — declarative field-level codec selection without writing a top-level codec or acodec: '...'string. Priority:codec>enumValueField>dateTime> inferred from type. - Generation:
CodableGeneratoremits a top-level helper codec_$<ClassName><FieldName>EnumCodec = Codec.enumOf<E, V>(...)referenced by the field. The top-levelfinalis constructed only once, avoiding inline reconstruction of the (non-const) mapping map on every encode/decode call. Helpers are named by class name + field name to prevent top-level name collisions when multiple@Codableclasses in the same file reference the same enum. naming.dartaddsupperFirst(used when assembling helper variable names).
Behaviour change (generated code format) #
- Codec part files are now formatted with an extra-wide page width
(
SharedPartBuilderpasses a customformatOutputusingDartFormatter(pageWidth: 1 << 16)). Structural blocks inside a codec part (Codec.object/ constructor / encode map / enum mapping map) already carry trailing commas that drive line breaks; individual reader calls are single-line expressions. Long type or field names caused reader calls to be soft-wrapped at 80 columns without a trailing comma, triggering the host project'srequire_trailing_commaslint. With the widened page width, soft wrapping no longer occurs and that lint is truly avoided at the source, without needingignore_for_filein the consumer'sbuild.yaml.
Codegen-time validation (new error paths) #
@CodecField(enumValueField:)applied to a non-enum field, an enum that has no such property, or a target property whose type is notint/String/double/numthrowsInvalidGenerationSourceErrorduringbuild_runner, never deferring the error to runtime.
Tests #
- Added 5 generator golden tests:
int/Stringvalue-field mapping with helper reference, helper name uniqueness when multiple@Codableclasses in the same file reference the same enum, non-enum field error, and illegal value-field type error.codable_generator_test.dart: 14 → 19 cases.
0.1.4 #
Behaviour change (generated code) #
- All field reader calls now emit explicit type arguments:
b.required<T>(...)/b.optional<T>(...)/b.optionalOr<T>(...)always include the type parameter; the Dart compiler's inference from constructor parameters is no longer relied upon. Rationale: the built-inCodec.anyisCodec<Object?>, andTitself carries nullability information. When assigned to anObject?-typed field, the compiler inferredT=Object(dropping nullability), causing a type mismatch against theCodec<Object?>argument and a compile error. Explicit type arguments permanently fix this inference ambiguity, and any future nullableTcodec will not hit the same issue. CodecResolver.resolveinterface change: return type changed fromString(a codec expression) to({String expr, String typeArg}). ThetypeArgfield carries the string representation ofTfor that codec; the generator injects it directly as the explicit type argument. In nestedList<T?>/Map<String, V?>scenariostypeArgandexprkeep element nullability in sync.
Tests #
- Impact: re-running
build_runner build --delete-conflicting-outputsregenerates all*.g.dartfiles;fvm flutter analyzeon the host project confirmed zero regressions. - New generator golden tests (
test/codable_generator_test.dart, 14 cases): usesbuild_test'sresolveSourcesto obtain aLibraryElement, then callsCodableGenerator.generateForAnnotatedElementdirectly and asserts on the output string. Locks down the explicit type argument shape for primitives /Object?/dynamic/ nestedList/Map/ enum / dateTime / custom codec / nullable+required combinations — sub-second feedback; regressions in generated code no longer require a fullbuild_runnerre-run + analyze to surface. build_test: ^2.2.0added todev_dependencies.
Historical debt #
pubspec.yamlversionfield backfilled from the stale0.1.0to0.1.4in one step, aligned with CHANGELOG. The same version drift existed in the codec runtimepubspec.yamlbut was not touched here (left as a separate cleanup task).
Build / workspace #
- Joined pub workspace: this package's
pubspec.yamladdsresolution: workspace; the root project lists this package underworkspace:. Test files'package:test/test.dartimports are now resolved by the root analyzer without false errors. - SDK lower bound raised:
^3.4.0→^3.6.0(required by pub workspace). - Removed sub-package
dependency_overrides: previously pinnedanalyzer 7.3.0/analyzer_plugin 0.12.0; workspace mode allows overrides only at the root, and the rootpubspec.yamlalready declared the same values, so removal has no effect. lintsdowngraded to^4.0.0: compatible with the root project'sflutter_lints ^4.0.0joint resolution..gitignoreappendsbuild/: sub-packageflutter testproduces hundreds of asset files that should not be committed.
0.1.3 #
Added #
DateTimeMode.millisUtc/DateTimeMode.secondsUtc: dispatches to the newCodec.dateTimeMillisUtc/Codec.dateTimeSecondsUtc. For backends that send millisecond (or second) timestamps where time-zone correctness matters — decodes to aDateTimewithisUtc=true, encodes back to a number; fully symmetric.
0.1.2 #
Added #
@CodecIgnore()shorthand annotation: equivalent to@CodecField(ignore: true); shorter and more prominent for single-field skip use cases.FieldRename.screamingSnake:userName→USER_NAME, for interoperability with Java/Spring backends that use SCREAMING_SNAKE_CASE for enums and constants.@CodecField(dateTime: DateTimeMode.local/utc/seconds): lets the newCodec.dateTimeUtc/Codec.dateTimeSecondsbe selected via annotation without writing acodec: 'Codec.dateTimeUtc'string reference.@CodecField(defaultValue: ...)supports constList/ constMap: nested literals are also supported via recursive parsing. Unsupported element or key/value types raise an explicit codegen error.
Fixes #
- Field-level
CodecField.includeIfNullimplemented: fulfils the semantics already documented in dartdoc. The generator buckets fields separately — fields that keepnullare emitted directly; fields that omitnulluse a Dart map literalifelement:if (v.x != null) 'x': codec.encode(v.x!). The class-levelomitNullscall is no longer emitted by codec_gen (retained for hand-written codecs).
0.1.1 #
Fixes #
- String literal escaping:
@CodecField(defaultValue:)and@CodecValuevalues containing'/\/$/\n\r\t/ Unicode characters no longer cause compile errors from raw string concatenation in the generated code. AddeddartStringLiteralutility function. FieldRename.snake/kebab/pascalconsecutive-uppercase word splitting:userID→user_id,URLPath→url_path,userIDValue→user_id_value. The original algorithm only detected lower→upper boundaries; it missed the boundary between a consecutive-uppercase run and a following lowercase letter (behaviour now aligned with Lodash / inflection and similar libraries; a purely consecutive-uppercase sequence with no embedded lowercase is still treated as a single word).@CodecEnumwith only partial@CodecValuecoverage rejected at codegen time: previously the generated mapping omitted values and only threwEncodeExceptionat runtime on encode; nowInvalidGenerationSourceErroris raised during generation, listing the unannotated values.
Tests #
- First unit tests (previously 0): 36 cases covering
renameFieldedge cases,lowerFirst,dartStringLiteralescaping order and Unicode, and full-coverage validation for@CodecEnum.
0.1.0 #
- Initial release:
@Codable/@CodecEnumannotations trigger codegen, generating top-level_$xxxCodecconst/final fields. - Automatic field-type resolution: primitives / nullable / default values /
List/Map<String, V>/ nested models (must carry@Codable) / enums (default inline.name;@CodecEnumuses a shared codec) / self-references (automatically usesCodec.lazy). - Field-level escape hatch
@CodecField(codec: 'xxx')for arbitrary complex scenarios. @Codable(includeIfNull: false)class-level control:toJsonautomatically appends.omitNulls.