Skip to content
This repository was archived by the owner on Feb 16, 2026. It is now read-only.

Update codegen#417

Merged
jpeiffer merged 6 commits into
mainfrom
update_codegen
Nov 9, 2025
Merged

Update codegen#417
jpeiffer merged 6 commits into
mainfrom
update_codegen

Conversation

@jpeiffer

@jpeiffer jpeiffer commented Nov 9, 2025

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Added a radio-group widget and improved ID support for widgets and examples.
  • Compatibility

    • Updated for Flutter 3.35 and Dart 3.9; package versions bumped.
  • Improvements

    • Dropdowns: barrierDismissible, initialValue, padding, errorBuilder, forceErrorText.
    • Text fields: cursorErrorColor, errorBuilder, selectAllOnFocus and enhanced interaction controls.
    • Exposed InputDecorationThemeSchema and better theme encoder/decoder usage.
  • Other

    • Example pages updated with IDs and layout tweaks.

@coderabbitai

coderabbitai Bot commented Nov 9, 2025

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

Walkthrough

Introduces a Param model and migrates codegen to use it; refactors the code generator into staged emitters with debug mode; adds a requiresId flag to JsonWidget annotation; migrates theme encoder/decoder access to singleton instances; adds a radio_group builder; exposes InputDecorationThemeSchema; bumps package versions and SDK constraints to ^3.9.0.

Changes

Cohort / File(s) Change Summary
Annotation package
packages/annotation/lib/dynamic_widget_annotation.dart, packages/annotation/pubspec.yaml, packages/annotation/CHANGELOG.md
Added requiresId bool field to JsonWidget (default false) and updated top-level jsonWidget constant; version bumped 3.0.0 → 3.0.1; Dart SDK constraint → ^3.9.0; changelog entry added.
Codegen core: model & exports
packages/codegen/lib/src/model/param.dart, packages/codegen/lib/json_dynamic_widget_codegen.dart, packages/codegen/lib/src/extension/dart_type_extension.dart, packages/codegen/CHANGELOG.md, packages/codegen/pubspec.yaml
New Param class added and exported; removed DartTypeNullability extension and deleted its file; replaced export of dart_type_extension.dart with src/model/param.dart; pubspec bumped 3.0.0 → 4.0.0 and SDK → ^3.9.0; changelog updated.
Codegen builders & generation flow
packages/codegen/lib/src/builder/json_widget_library_builder.dart, packages/codegen/lib/src/builder/json_widget_registrar_builder.dart
Large refactor: staged generation (_generateClass, _generateWidgetClass, _generateModel, _generateSchema, _prepareCode) with try/catch instrumentation and debug-mode flag via assertion; TypeChecker.fromRuntime → TypeChecker.typeNamed in places and registration key switched to displayName.
Decoders / Schema decoders / Encoders
packages/codegen/lib/src/decoder/decoders.dart, packages/codegen/lib/src/decoder/schema_decoders.dart, packages/codegen/lib/src/encoder/encoders.dart
Replaced ParameterElement usage with Param across typedefs and function signatures; nullability/type helpers switched to typeNullable/typeName/displayName; imports updated to param.dart; added List schema decoder; restored/adapted theme decoders.
json_dynamic_widget package: exports & models
packages/json_dynamic_widget/lib/builders.dart, packages/json_dynamic_widget/lib/json_dynamic_widget.dart, packages/json_dynamic_widget/lib/src/models/json_widget_data.dart, packages/json_dynamic_widget/lib/src/models/deferred_json_widget_data.dart, packages/json_dynamic_widget/CHANGELOG.md, packages/json_dynamic_widget/pubspec.yaml
Added export for json_radio_group_builder.dart; removed InputDecorationThemeSchema from the hidden export list (now publicly exported); added hasProvidedId boolean to JsonWidgetData and propagated to deferred variant; package bumped 10.0.2 → 11.0.0 and SDK → ^3.9.0.
Theme encoder/decoder singleton migration (multiple builders)
packages/json_dynamic_widget/lib/src/builders/*, packages/json_dynamic_widget/lib/src/decoders/input_decoration_decoder.dart
Replaced static calls like ThemeDecoder.decodeXxx/ThemeEncoder.encodeXxx with singleton access ThemeDecoder.instance.decodeXxx / ThemeEncoder.instance.encodeXxx across many builders and decoders.
requiresId annotation adoption (many builders)
packages/json_dynamic_widget/lib/src/builders/* (animated_theme, checkbox, cupertino_switch, layout_builder_builder, measured_builder, text_form_field, switch, radio_builder, etc.)
Updated builder annotations from @jsonWidget to @JsonWidget(requiresId: true) where shown; metadata on builders updated accordingly.
Radio builder & new radio_group
packages/json_dynamic_widget/lib/src/builders/json_radio_builder.dart, packages/json_dynamic_widget/lib/src/builders/json_radio_group_builder.dart
Simplified json_radio_builder (removed internal _Radio widget, buildCustom now returns Radio); added new private _JsonRadioGroupBuilder, _RadioGroup widget/state implementing registry-aware radio group behavior.
DropdownButtonFormField builder
packages/json_dynamic_widget/lib/src/builders/json_dropdown_button_form_field_builder.dart
Added model fields barrierDismissable, errorBuilder, forceErrorText, initialValue, padding; removed value field and local subscription/value-tracking; updated (de)serialization, schema, and widget wiring; switched theme access to singleton instances.
Switch, Checkbox, CupertinoSwitch, Measured, TextFormField builders
packages/json_dynamic_widget/lib/src/builders/json_switch_builder.dart, json_checkbox_builder.dart, json_cupertino_switch_builder.dart, json_measured_builder.dart, json_text_form_field_builder.dart
Annotation changes to requiresId; renames and added fields (e.g., activeColoractiveThumbColor, added focus/outline properties for Switch; many new text-field properties like cursorErrorColor, errorBuilder, forceErrorText, groupId, hintLocales, statesController); formatting/indent updates and new properties wired into model/state.
Scaffold builder enhancement
packages/json_dynamic_widget/lib/src/builders/json_scaffold_builder.dart
Added dart:math import, new constants, and _defaultBottomSheetScrimBuilder implementing adaptive scrim opacity for bottom sheets.
Widget builder runtime behavior
packages/json_dynamic_widget/lib/src/builders/json_widget_builder.dart
Listener now ignores self-originated registry events (prevents self-triggered rebuilds); ErrorWidget formatting wraps error details with a "message:" label.
Example assets & app changes
packages/json_dynamic_widget/example/assets/pages/*, packages/json_dynamic_widget/example/lib/src/custom_schemas/*, packages/json_dynamic_widget/example/pubspec.yaml, packages/json_dynamic_widget/example/.gitignore, macOS project files
Added many id attributes in example pages (checkbox, switch, radio, cupertino_switch, null_value_passing, etc.), restructured radio usage to radio_group, moved icon size properties, reduced some icon sizes, swapped button_baroverflow_bar, updated custom schema imports (json_theme_schemas.dartjson_theme.dart), example pubspec bumped SDK and dev deps, added Podfile.lock to .gitignore, macOS deployment target bumped 10.14 → 10.15 and GPU validation enabled.
Root workspace & CI
pubspec.yaml, .github/workflows/pull_request.yml
Root SDK constraint raised to ^3.9.0; removed example workspace entry for packages/json_dynamic_widget/example; PR workflow pull_request types updated to include opened, reopened, synchronize.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Analyzer as Analyzer
    participant CodeGen as Code Generator
    participant Param as Param Model
    participant Decoders as Decoders
    Note over Analyzer,CodeGen: Parameter extraction → Param conversion → decode
    Analyzer->>CodeGen: FormalParameterElement(s)
    CodeGen->>Param: Param.fromFormalParameter(...)
    Param-->>CodeGen: Param (displayName, typeName, typeNullable, defaultValueCode)
    CodeGen->>Decoders: decode(ClassElement, Param)
    Decoders-->>CodeGen: decode snippet / code fragment
    CodeGen->>CodeGen: _generateModel / _generateClass / _prepareCode
    CodeGen-->>FS: emit generated Dart file
Loading
sequenceDiagram
    autonumber
    participant Widget as Builder/Widget
    participant ThemeInst as ThemeEncoder/ThemeDecoder.instance
    Note over Widget,ThemeInst: Singleton theme access used throughout
    Widget->>ThemeInst: ThemeDecoder.instance.decodeXxx(value)
    ThemeInst-->>Widget: decoded value
    Note right of Widget: Old static access (ThemeDecoder.decodeXxx) removed
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • Param adoption across decoders/encoders/schema files: ensure nullability, name mappings and defaultValue handling preserved (typeNullable, typeName, displayName, defaultValueCode).
  • json_widget_library_builder refactor: verify generated outputs remain stable; confirm debug-mode assertion and try/catch behavior.
  • Removal of dart_type_extension.dart and corresponding changes to nullability helpers: ensure all call sites updated to typeNullable/typeName.
  • DropdownButtonFormField changes: validate serialization/schema updates, removal of local value tracking/subscription, and new fields propagation.
  • Radio builder/group: confirm registry integration, groupValue propagation, and example assets compatibility.
  • Broad singleton migration for ThemeEncoder/ThemeDecoder: verify instance APIs exist and behave identically.

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Update codegen' is vague and overly generic, failing to convey the specific scope or nature of changes in this substantial changeset. Use a more descriptive title that captures the main change, such as 'Refactor code generation to use Param model and support requiresId flag' or 'Upgrade dependencies and introduce new annotation requirements'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2aea5cb and c66adcf.

📒 Files selected for processing (3)
  • packages/annotation/CHANGELOG.md (1 hunks)
  • packages/codegen/CHANGELOG.md (2 hunks)
  • packages/json_dynamic_widget/CHANGELOG.md (1 hunks)

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/codegen/lib/src/decoder/decoders.dart (1)

246-252: Fix PreferredSizeWidget default normalization.

Converting default value code with .replaceAll('PreferredSizeWidget', 'JsonWidgetData').replaceAll('Widget', 'JsonWidgetData') corrupts strings such as const <PreferredSizeWidget>[]: after the first replacement we have const <JsonWidgetData>[], and the second replacement then turns that into const <JsonJsonWidgetDataData>[], yielding invalid generated code. Please update the normalization logic to avoid reprocessing the Widget substring once it’s already inside JsonWidgetData (e.g., by using a helper that applies regex replacements with a negative lookbehind).

One way to fix this is to extract a helper:

+String _normalizeWidgetDefault(String value) {
+  return value
+      .replaceAllMapped(RegExp(r'PreferredSizeWidget(\?)?'),
+          (match) => 'JsonWidgetData${match[1] ?? ''}')
+      .replaceAllMapped(RegExp(r'(?<![A-Za-z])Widget(\?)?'),
+          (match) => 'JsonWidgetData${match[1] ?? ''}');
+}
+
 String _widgetDecoder(
   Param element,
   String name,
   String funName,
   String? defaultValueCode,
 ) =>
     '''
 () {
   dynamic parsed = $funName(map['$name'], registry: registry,);
-  ${defaultValueCode == null ? '' : 'parsed ??= ${defaultValueCode.replaceAll('PreferredSizeWidget', 'JsonWidgetData').replaceAll('Widget', 'JsonWidgetData')};'}
+  ${defaultValueCode == null ? '' : 'parsed ??= ${_normalizeWidgetDefault(defaultValueCode)};'}
🧹 Nitpick comments (4)
packages/json_dynamic_widget/CHANGELOG.md (1)

1-7: Clarify whether widget replacement is a breaking change.

This is a major version bump (11.0.0) that replaces Radio with an auto-generated version. Consider adding explicit migration guidance or a note indicating whether this is a breaking change and what impact existing implementations should expect. The PR summary mentions a "new radio group builder," which might warrant additional documentation in the changelog entry.

packages/json_dynamic_widget/lib/src/builders/json_scaffold_builder.dart (1)

34-42: Simplify the opacity calculation and improve variable naming.

The variable name floatingButtonVisibilityValue is misleading—it's actually calculating a scrim opacity adjustment factor, not floating action button visibility. Additionally, the multi-step calculation can be simplified for better clarity and maintainability.

The current calculation:

  • extentRemaining = 0.3 * (1.0 - animation.value)
  • floatingButtonVisibilityValue = extentRemaining * 0.3 * 10 = 0.9 * (1.0 - animation.value)
  • opacity = max(0.1, 0.6 - 0.9 * (1.0 - animation.value))

This simplifies to: opacity = max(0.1, 0.9 * animation.value - 0.3)

Apply this diff to simplify:

-      final extentRemaining =
-          _kBottomSheetDominatesPercentage * (1.0 - animation.value);
-      final floatingButtonVisibilityValue =
-          extentRemaining * _kBottomSheetDominatesPercentage * 10;
-
-      final double opacity = math.max(
+      final double opacity = math.max(
         _kMinBottomSheetScrimOpacity,
-        _kMaxBottomSheetScrimOpacity - floatingButtonVisibilityValue,
+        0.9 * animation.value - 0.3,
       );

Alternatively, if the intermediate calculations are intentional for readability, rename the variable:

       final extentRemaining =
           _kBottomSheetDominatesPercentage * (1.0 - animation.value);
-      final floatingButtonVisibilityValue =
+      final opacityReduction =
           extentRemaining * _kBottomSheetDominatesPercentage * 10;

       final double opacity = math.max(
         _kMinBottomSheetScrimOpacity,
-        _kMaxBottomSheetScrimOpacity - floatingButtonVisibilityValue,
+        _kMaxBottomSheetScrimOpacity - opacityReduction,
       );
packages/json_dynamic_widget/example/assets/pages/radio.json (1)

37-38: Guard against null when composing the status string.

Because + binds tighter than ??, the current expression runs 'Selected radio group value: ' + radioGroupValue first. If radioGroupValue is ever null (for example after clearing the selection), the String + operator will throw before ?? '' can run. Wrap the nullable operand so you always concatenate a string.

Apply this diff:

-                      "text": "${'Selected radio group value: ' + radioGroupValue ?? ''}"
+                      "text": "${'Selected radio group value: ' + (radioGroupValue ?? '')}"
packages/json_dynamic_widget/lib/src/builders/json_radio_group_builder.dart (1)

53-82: Consider performance optimization for registry reads.

The build method reads from the registry on every build (line 56-58), which could be inefficient if the widget rebuilds frequently. Consider caching the value in state and listening to registry changes instead.

@override
void initState() {
  super.initState();
  _groupValue = widget.data.jsonWidgetRegistry.getValue(
    widget.data.jsonWidgetId,
  ) ?? widget.groupValue;
  
  // Listen to external changes
  widget.data.jsonWidgetRegistry.valueStream
    .where((event) => 
      !event.isSelfTriggered && 
      event.id == widget.data.jsonWidgetId
    )
    .listen((event) {
      if (mounted) {
        setState(() {
          _groupValue = event.value;
        });
      }
    });
}

@override
Widget build(BuildContext context) {
  return RadioGroup<dynamic>(
    groupValue: _groupValue,  // Use cached state value
    onChanged: (value) {
      if (widget.onChanged != null) {
        widget.onChanged!(value);
      }
      _groupValue = value;
      widget.data.jsonWidgetRegistry.setValue(
        widget.data.jsonWidgetId,
        value,
        originator: widget.data.jsonWidgetId,
      );
      if (mounted) {
        setState(() {});
      }
    },
    child: widget.child?.build(
      childBuilder: widget.childBuilder,
      context: context,
      registry: widget.data.jsonWidgetRegistry,
    ) ?? const SizedBox(),
  );
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7d7336 and 656f20a.

⛔ Files ignored due to path filters (1)
  • packages/json_dynamic_widget/example/macos/Podfile.lock is excluded by !**/*.lock
📒 Files selected for processing (56)
  • packages/annotation/CHANGELOG.md (1 hunks)
  • packages/annotation/lib/dynamic_widget_annotation.dart (5 hunks)
  • packages/annotation/pubspec.yaml (2 hunks)
  • packages/codegen/CHANGELOG.md (2 hunks)
  • packages/codegen/lib/json_dynamic_widget_codegen.dart (1 hunks)
  • packages/codegen/lib/src/builder/json_widget_library_builder.dart (19 hunks)
  • packages/codegen/lib/src/builder/json_widget_registrar_builder.dart (4 hunks)
  • packages/codegen/lib/src/decoder/decoders.dart (5 hunks)
  • packages/codegen/lib/src/decoder/schema_decoders.dart (3 hunks)
  • packages/codegen/lib/src/encoder/encoders.dart (1 hunks)
  • packages/codegen/lib/src/extension/dart_type_extension.dart (0 hunks)
  • packages/codegen/lib/src/model/param.dart (1 hunks)
  • packages/codegen/pubspec.yaml (2 hunks)
  • packages/json_dynamic_widget/CHANGELOG.md (1 hunks)
  • packages/json_dynamic_widget/README.md (1 hunks)
  • packages/json_dynamic_widget/example/.gitignore (1 hunks)
  • packages/json_dynamic_widget/example/assets/pages/card.json (1 hunks)
  • packages/json_dynamic_widget/example/assets/pages/checkbox.json (4 hunks)
  • packages/json_dynamic_widget/example/assets/pages/cupertino_switch.yaml (1 hunks)
  • packages/json_dynamic_widget/example/assets/pages/dynamic.json (2 hunks)
  • packages/json_dynamic_widget/example/assets/pages/form.json (3 hunks)
  • packages/json_dynamic_widget/example/assets/pages/null_value_passing.json (1 hunks)
  • packages/json_dynamic_widget/example/assets/pages/radio.json (1 hunks)
  • packages/json_dynamic_widget/example/assets/pages/switch.json (3 hunks)
  • packages/json_dynamic_widget/example/assets/pages/theme.json (2 hunks)
  • packages/json_dynamic_widget/example/lib/src/custom_schemas/dotted_border_schema.dart (1 hunks)
  • packages/json_dynamic_widget/example/lib/src/custom_schemas/svg_schema.dart (1 hunks)
  • packages/json_dynamic_widget/example/macos/Runner.xcodeproj/project.pbxproj (3 hunks)
  • packages/json_dynamic_widget/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (1 hunks)
  • packages/json_dynamic_widget/example/pubspec.yaml (2 hunks)
  • packages/json_dynamic_widget/lib/builders.dart (1 hunks)
  • packages/json_dynamic_widget/lib/json_dynamic_widget.dart (1 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_animated_container_builder.dart (1 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_animated_theme_builder.dart (1 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_checkbox_builder.dart (2 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_circular_progress_indicator_builder.dart (1 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_container_builder.dart (1 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_cupertino_switch_builder.dart (2 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_decorated_box_builder.dart (1 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_dropdown_button_form_field_builder.dart (12 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_layout_builder_builder.dart (1 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_linear_progress_indicator_builder.dart (1 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_measured_builder.dart (1 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_radio_builder.dart (1 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_radio_group_builder.dart (1 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_rich_text_builder.dart (1 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_scaffold_builder.dart (2 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_semantics_builder.dart (1 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_switch_builder.dart (5 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_text_form_field_builder.dart (11 hunks)
  • packages/json_dynamic_widget/lib/src/builders/json_widget_builder.dart (2 hunks)
  • packages/json_dynamic_widget/lib/src/decoders/input_decoration_decoder.dart (4 hunks)
  • packages/json_dynamic_widget/lib/src/models/deferred_json_widget_data.dart (2 hunks)
  • packages/json_dynamic_widget/lib/src/models/json_widget_data.dart (4 hunks)
  • packages/json_dynamic_widget/pubspec.yaml (3 hunks)
  • pubspec.yaml (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/codegen/lib/src/extension/dart_type_extension.dart
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
packages/json_dynamic_widget/CHANGELOG.md

5-5: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

🔇 Additional comments (60)
packages/json_dynamic_widget/example/.gitignore (1)

32-32: LGTM!

Adding Podfile.lock to the gitignore is a sensible addition that aligns with Flutter best practices. The iOS CocoaPods lockfile is auto-generated and environment-specific, so excluding it from version control prevents spurious diffs and merge conflicts.

packages/json_dynamic_widget/example/assets/pages/form.json (1)

106-108: Icon size adjustments look good.

The reduction of suffix icon sizes from 50 to 20 across all three form fields (first name, last name, email address) is consistent and reasonable for Material Design conventions. The fontFamily is properly preserved as "MaterialIcons" in all cases.

Also applies to: 155-157, 199-201

packages/json_dynamic_widget/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (1)

61-61: Verify scope: GPU validation mode seems unrelated to codegen updates.

This Xcode scheme change (enabling GPU validation mode for the macOS example app's Debug configuration) appears tangential to the stated PR objectives about codegen updates, the new Param model, and version bumps. While the change is harmless and valid, consider whether it should be in this PR or separated into a distinct, focused change.

packages/json_dynamic_widget/example/assets/pages/null_value_passing.json (1)

20-20: ID addition is correct and necessary.

The text_form_field widget builder explicitly requires an ID via @JsonWidget(requiresId: true) (packages/json_dynamic_widget/lib/src/builders/json_text_form_field_builder.dart). The addition of "id": "text_field" is therefore necessary and aligns with the PR's ID-based registration improvements.

packages/json_dynamic_widget/example/assets/pages/card.json (1)

75-111: Widget type change approved; overflow_bar is properly supported.

The overflow_bar widget is registered and supported in json_dynamic_widget, with a dedicated builder implementation and test coverage. The JSON structure, styling, and callback configuration are all correct and consistent with framework patterns.

packages/json_dynamic_widget/example/assets/pages/cupertino_switch.yaml (2)

62-77: Verify the bare example_switch widget is intentional.

The cupertino_switch at lines 62–63 has no args properties (label, value, enabled), unlike the other switches in the file (lines 24–27, 37–40, 50–52). The conditional widget then references this switch's state at line 68.

Confirm this is intentional (e.g., a minimal example showing id-based referencing) rather than an incomplete definition.


2-77: YAML structure and syntax look good.

The indentation is consistent, the widget IDs are unique and well-formed, and the conditional logic is sound. The changes align well with the PR objectives of introducing id-based wiring and conditional rendering for dynamic widgets.

packages/json_dynamic_widget/lib/src/builders/json_rich_text_builder.dart (1)

12-12: LGTM! Clean migration to singleton pattern.

The change from static method access to singleton instance access is straightforward and aligns with the broader project-wide migration mentioned in the PR summary.

packages/json_dynamic_widget/lib/src/decoders/input_decoration_decoder.dart (1)

76-194: LGTM! Singleton migration applied consistently.

All ThemeDecoder calls have been successfully migrated from static methods to the singleton instance pattern (ThemeDecoder.instance.decodeX). The changes are mechanical, consistent, and preserve all existing parameters and logic.

packages/json_dynamic_widget/example/macos/Runner.xcodeproj/project.pbxproj (1)

410-410: LGTM! Deployment target bump is consistent.

The macOS deployment target has been updated to 10.15 across all project-level build configurations (Profile, Debug, Release), which aligns with the broader SDK updates in this PR.

Note: The target-level configurations specify 11.5 (lines 436, 567, 592), which will be the effective deployment target since target settings override project settings.

Also applies to: 494-494, 541-541

packages/json_dynamic_widget/lib/src/builders/json_semantics_builder.dart (2)

18-20: Based on my verification:

ThemeDecoder provides functionality to decode theme related objects from JSON maps, and the usage pattern ThemeDecoder.instance.decodeAppBarTheme with validate: false is established in the json_theme package documentation, which is a dependency of json_dynamic_widget.

The change in _decodeSortKey correctly migrates from static access to the singleton pattern using ThemeDecoder.instance while preserving the validate: false parameter. The Singleton pattern in Dart ensures a class has only one instance and provides a global point of access to it, helping eliminate redundant code. This method is now consistent with other builder methods in the codebase that already use ThemeDecoder.instance pattern.



13-16: Migration to singleton instance is verified and correct.

ThemeEncoder.instance and ThemeDecoder.instance are external singletons provided by the json_theme (v10.0.0) package and are already properly initialized by that dependency. The refactoring at lines 15 and 20 in json_semantics_builder.dart follows the established pattern used consistently throughout the codebase.

packages/json_dynamic_widget/example/lib/src/custom_schemas/svg_schema.dart (1)

1-1: No action required—import is correct and already standard in the codebase.

The import path package:json_theme/json_theme.dart is already the established pattern across the codebase. Multiple existing files (input_decoration_decoder.dart, json_dropdown_button_form_field_builder.dart, json_text_form_field_builder.dart, issue_219_page.dart, and others) successfully import from this path and use SchemaHelper and ColorSchema without issues. The change in svg_schema.dart aligns it with this existing standard, not introducing a new or risky import.

packages/json_dynamic_widget/lib/src/builders/json_scaffold_builder.dart (2)

9-11: LGTM!

The constants are well-named and the values are reasonable for configuring bottom sheet scrim behavior.


44-47: Verify that non-dismissible scrim is intentional.

The ModalBarrier has dismissible: false, which prevents users from dismissing the bottom sheet by tapping the scrim. This differs from typical bottom sheet behavior where tapping outside dismisses the sheet. Please confirm this is the intended UX.

packages/json_dynamic_widget/example/lib/src/custom_schemas/dotted_border_schema.dart (1)

1-1: The import path change is correct and aligns with the documented json_theme pattern.

The documented import pattern for json_theme is import 'package:json_theme/json_theme.dart', which matches the change made in this file. The SchemaHelper and ColorSchema symbols used in the file (line 14) are correctly accessed from this import path. The change is approved and requires no further modifications.

pubspec.yaml (1)

5-5: SDK constraint updated to ^3.9.0.

The Dart SDK constraint has been raised from ^3.7.0 to ^3.9.0, which aligns with the broader toolchain upgrades across the workspace packages.

Verify that all consumers of this workspace can support Dart SDK ^3.9.0 and that the removal of the example package from the workspace is intentional and won't break any existing build/test pipelines.

packages/json_dynamic_widget/lib/src/builders/json_linear_progress_indicator_builder.dart (1)

11-17: LGTM! Migrated to singleton pattern.

The update correctly switches from static ThemeDecoder.decodeColor to ThemeDecoder.instance.decodeColor, maintaining the same decode logic while adopting the singleton pattern used throughout this PR.

packages/json_dynamic_widget/README.md (1)

131-154: LGTM! Documentation updated to reflect instance method usage.

The README correctly updates the pre-7.0.0 example code to use ThemeDecoder.instance methods instead of static methods, maintaining consistency with the singleton pattern adopted throughout this PR.

packages/json_dynamic_widget/example/pubspec.yaml (2)

7-7: LGTM! Dependency versions updated.

The SDK constraint and dependencies have been appropriately updated:

  • Dart SDK: ^3.9.0 (consistent with workspace)
  • json_theme: ^10.0.0 (major version bump)
  • build_runner: ^2.10.1
  • json_dynamic_widget_codegen: ^4.0.0 (major version bump aligning with this PR)

Also applies to: 20-20, 25-25, 30-30


33-37: Dependency overrides added for local development.

The addition of dependency_overrides with path references to local annotation and codegen packages is appropriate for development and testing within the workspace. Note that these overrides should not be present when publishing packages.

packages/json_dynamic_widget/lib/src/builders/json_decorated_box_builder.dart (1)

11-17: LGTM! Migrated to singleton pattern.

Both decoder methods correctly use ThemeDecoder.instance instead of static calls, maintaining the same decode logic while adopting the consistent singleton pattern used throughout this PR.

packages/json_dynamic_widget/lib/json_dynamic_widget.dart (1)

13-13: Verify intentional exposure of InputDecorationThemeSchema.

The InputDecorationThemeSchema is no longer hidden from the json_theme export, making it publicly accessible through json_dynamic_widget. This is a public API change that expands the library's surface area.

Please confirm:

  1. This exposure is intentional and aligns with the PR objectives
  2. The change is documented in the changelog
  3. There are no naming conflicts or unintended side effects from exposing this schema

If this change is part of the codegen refactor mentioned in the AI summary, consider documenting the reason for exposing this schema in the changelog or migration guide.

packages/json_dynamic_widget/example/assets/pages/dynamic.json (1)

126-131: The JSON structure described in this review comment does not match the actual file state.

The review claims the size property was moved to be a sibling of icon at the same level. However, the actual file shows size is nested inside the args object:

"icon": {
  "type": "icon",
  "args": {
    "icon": { "codePoint": 61912, "fontFamily": "MaterialIcons" },
    "size": 50
  }
}

This is the Param-based parameter model using the type/args wrapper pattern. The file is already in this state, and the review's "After structure" example with size as a direct sibling to icon does not reflect the actual implementation.

The icon builder code (json_icon_builder.dart) uses @jsonWidget code-generation annotations consistent with this structure, and the CHANGELOG contains no recent entries documenting a specific change to the size property position.

Likely an incorrect or invalid review comment.

packages/json_dynamic_widget/example/assets/pages/switch.json (1)

30-30: LGTM! ID attributes added consistently.

The addition of id attributes to the switch widgets is clean and follows a consistent naming pattern that clearly identifies each switch's purpose.

Also applies to: 52-52, 74-74

packages/json_dynamic_widget/example/assets/pages/theme.json (2)

88-89: LGTM! Checkbox ID added.

The addition of the id attribute to the checkbox widget is consistent with the PR's objective to support widget identification.


98-124: Verify the radio button value design.

The new radio_group structure uses boolean values (true/false) for the two radio buttons. Typically, radio buttons should have distinct, meaningful values that represent different options rather than boolean states. Using booleans may limit the semantics and make it unclear what each radio represents.

Consider whether these values should be more descriptive (e.g., "option1"/"option2" or specific feature flags) to better convey their purpose.

packages/json_dynamic_widget/lib/src/builders/json_container_builder.dart (2)

18-21: LGTM! Singleton pattern migration for encoders.

The migration from static method calls to singleton instance access for ThemeEncoder is consistent with the broader refactoring pattern in this PR.

Also applies to: 24-27


30-31: LGTM! Singleton pattern migration for decoders.

The migration from static method calls to singleton instance access for ThemeDecoder aligns with the encoder changes and maintains consistency.

Also applies to: 34-35

packages/json_dynamic_widget/pubspec.yaml (3)

4-4: Major version bump to 11.0.0.

This major version bump signals breaking changes. Ensure that all breaking changes introduced in this PR are documented in the CHANGELOG and that migration guidance is provided for users upgrading from 10.x.

Do you want me to check if the CHANGELOG has been updated with breaking changes and migration notes?


44-45: Test API override noted.

The test_api: '^0.7.6' dependency override may indicate a compatibility workaround. Ensure this override is still necessary and doesn't mask underlying dependency conflicts.


7-7: Verify dependency requirements for SDK 3.9.0 constraint.

Codebase analysis reveals no Dart 3.9.0-specific language features in use (no extension types, sealed classes, augmentation syntax, etc.). The codebase uses only Dart 3.0+ features like super parameters. Dart 3.9.0's notable changes include stricter null safety type promotion, AOT-compiled CLI snapshots, pub workspace handling improvements, and cross-compilation targets—none of which are evident as direct requirements in the code.

The SDK constraint bump to ^3.9.0 may be driven by the coordinated major version updates to json_theme and json_dynamic_widget_codegen, or by workspace pub changes. Verify that the dependent packages actually require Dart 3.9.0, or if the constraint could be relaxed to ^3.8.0 or lower to maintain broader compatibility.

packages/annotation/pubspec.yaml (2)

4-4: Verify the patch version bump is appropriate.

This package is bumped to 3.0.1 (patch), while the main json_dynamic_widget package bumps to 11.0.0 (major) and json_dynamic_widget_codegen bumps to 4.0.0 (major). Given the PR introduces a new requiresId field to the annotation according to the AI summary, verify whether this should be a minor version bump (3.1.0) rather than a patch, as it adds new functionality.


7-7: LGTM! SDK and test dependency updates.

The SDK constraint increase to ^3.9.0 and test version update to ^1.26.3 maintain consistency with other packages in the workspace.

Also applies to: 20-20

packages/json_dynamic_widget/lib/src/builders/json_cupertino_switch_builder.dart (2)

10-10: LGTM! ID requirement added.

The change from @jsonWidget to @JsonWidget(requiresId: true) enforces that this widget must have an ID, which aligns with the PR's objective to standardize ID usage for stateful form widgets like switches.


89-137: LGTM! Formatting improvements.

The indentation and formatting adjustments improve readability without changing the validation or builder logic.

packages/codegen/pubspec.yaml (2)

4-4: LGTM! Major version bump with SDK update.

The major version bump to 4.0.0 and SDK constraint increase to ^3.9.0 are appropriate for the significant codegen refactoring (Param model, singleton patterns) described in the PR.

Also applies to: 7-7


16-17: LGTM! Codegen toolchain updates.

The major version updates to analyzer (^8.4.0), build (^4.0.0), json_theme (^10.0.0), and source_gen (^4.0.2) provide the necessary tooling support for the enhanced code generation capabilities.

Also applies to: 21-23

packages/json_dynamic_widget/lib/src/builders/json_dropdown_button_form_field_builder.dart (5)

65-65: LGTM! API expanded with new fields.

The addition of barrierDismissable, errorBuilder, forceErrorText, initialValue, and padding fields enhances the dropdown form field's capabilities, aligning with Flutter's DropdownButtonFormField API.

Also applies to: 73-73, 76-76, 82-82, 91-91, 102-102, 110-110, 113-113, 119-119, 128-128


280-349: LGTM! Singleton pattern migration with backward compatibility.

The migration to ThemeDecoder.instance is consistent with the PR's refactoring pattern. Importantly, line 329 provides backward compatibility by falling back to map['value'] if map['initialValue'] is not present, which helps with migration from the old API.


357-391: LGTM! Encoder updates with new field serialization.

The toJson method correctly uses ThemeEncoder.instance and includes all new fields in the serialization output.


584-657: LGTM! Widget build updated with new properties.

The widget build correctly passes all new properties (barrierDismissible, errorBuilder, forceErrorText, initialValue, padding) to the DropdownButtonFormField, and the state management has been appropriately simplified.


119-119: Breaking change: Verify migration documentation.

The value field has been replaced with initialValue. While line 329 provides backward compatibility by falling back to map['value'], this is still a breaking change in the public API. Ensure this change is documented in the CHANGELOG with clear migration instructions.

Do you want me to check if the CHANGELOG documents this breaking change?

Also applies to: 329-329

packages/json_dynamic_widget/lib/src/builders/json_widget_builder.dart (1)

165-167: Avoids self-originated rebuild loops

The additional originator check keeps widgets from thrashing when they write back into the registry and immediately observe their own event. Nice catch.

packages/json_dynamic_widget/lib/src/models/json_widget_data.dart (3)

9-20: LGTM! Clean implementation of ID provision tracking.

The hasProvidedId field is properly initialized based on whether an ID was explicitly provided or defaulted. The logic correctly distinguishes between user-provided IDs and auto-generated UUIDs.


224-242: Verify that preserving hasProvidedId in copyWith is intentional.

The copyWith method preserves the original hasProvidedId value even when a different jsonWidgetId might be provided. This means the flag tracks the original provision state rather than the current ID state. If this is intentional (to maintain the original "was an ID provided" semantics), this is correct. However, if copyWith with a new ID should update hasProvidedId, this would need adjustment.

Consider whether copyWith should recalculate hasProvidedId when jsonWidgetId is explicitly provided:

JsonWidgetData copyWith({
  dynamic jsonWidgetArgs,
  JsonWidgetBuilder? jsonWidgetBuilder,
  Set<String>? jsonWidgetListenVariables,
  String? jsonWidgetId,
  JsonWidgetRegistry? jsonWidgetRegistry,
  String? jsonWidgetType,
}) => JsonWidgetData(
  hasProvidedId: jsonWidgetId != null ? true : hasProvidedId,
  // ... rest of parameters
);

100-104: LGTM! Clean timer initialization.

The inline timer construction with .start() is more concise than the previous two-step approach.

packages/json_dynamic_widget/lib/src/builders/json_switch_builder.dart (3)

8-8: LGTM! Annotation updated to require ID.

The change from @jsonWidget to @JsonWidget(requiresId: true) aligns with the PR's goal of requiring IDs for widgets that need state management through the registry.


140-187: LGTM! Widget properties correctly wired to Switch.

All the new properties (activeThumbColor, onFocusChanged, trackOutlineColor, trackOutlineWidth) are correctly passed through to the underlying Flutter Switch widget, and the state management logic remains intact.


28-62: ****

The review comment incorrectly attributes the activeColor parameter to the _Switch class. The Switch builder in json_switch_builder.dart uses activeThumbColor (not activeColor). The parameter activeColor exists in other builders—json_checkbox_builder.dart and json_cupertino_switch_builder.dart—but those are different widgets with their own API surfaces. No breaking change to the Switch builder regarding this parameter rename has been identified.

Likely an incorrect or invalid review comment.

packages/json_dynamic_widget/lib/src/builders/json_radio_group_builder.dart (1)

1-17: LGTM! New radio group builder with required ID.

The builder is properly annotated with @JsonWidget(requiresId: true) and follows the established pattern for JSON widget builders.

packages/json_dynamic_widget/lib/src/builders/json_text_form_field_builder.dart (3)

9-9: LGTM! Annotation updated to require ID.

The builder now correctly requires an ID, which is essential for text form field state management through the registry.


270-368: LGTM! All new parameters correctly propagated.

All the new parameters are properly passed through to the underlying TextFormField widget, maintaining consistency with Flutter's API.


56-133: groupId parameter is correctly configured.

The groupId parameter is of type Object and its default value is EditableText. The code at line 84 (groupId = EditableText) correctly matches Flutter's TextFormField API specification. The other new parameters also appropriately extend the widget's capabilities.

packages/annotation/lib/dynamic_widget_annotation.dart (2)

5-5: LGTM! Backward-compatible default for requiresId.

The jsonWidget constant is updated to explicitly include requiresId: false, maintaining backward compatibility for existing widgets.


130-158: LGTM! Well-documented new annotation field.

The requiresId field is properly documented and added to the JsonWidget annotation with a sensible default of false, ensuring backward compatibility while enabling new functionality for widgets that require IDs.

packages/codegen/lib/src/model/param.dart (2)

1-36: LGTM! Clean parameter model implementation.

The Param class provides a clean, immutable representation of parameter metadata. The fromFormalParameter factory appropriately extracts all necessary information from the analyzer's FormalParameterElement.


16-27: Verify null-safety of param.name access.

Line 22 uses param.name! with a force unwrap. While FormalParameterElement.name should always be non-null for valid formal parameters, consider adding a null check or assertion for defensive programming.

factory Param.fromFormalParameter(
  FormalParameterElement param, {
  required TypeChecker builderParamChecker,
}) {
  assert(param.name != null, 'Parameter name cannot be null');
  return Param(
    custom: false,
    defaultValueCode: param.defaultValueCode,
    displayName: param.name!,
    isBuilderParam: builderParamChecker.annotationsOf(param).isNotEmpty,
    isRequired: param.isRequired,
    typeName: param.type.getDisplayString(),
    typeNullable: param.type.nullabilitySuffix == NullabilitySuffix.question,
  );
}
packages/codegen/lib/src/decoder/schema_decoders.dart (1)

1-43: LGTM! Clean migration to Param model.

The schema decoders have been successfully migrated from ParameterElement to the new Param model. All decoder signatures are consistently updated, and the addition of List<int> schema decoder (line 23) fills a previous gap in type coverage.

packages/codegen/lib/src/encoder/encoders.dart (1)

1-72: LGTM! Successful migration to Param model.

The encoders have been cleanly migrated from ParameterElement to the new Param model. The signature changes are consistent throughout, and the logic for handling nullability, type names, and default values has been correctly adapted to use Param's properties (displayName, typeNullable, typeName).

Comment thread packages/codegen/CHANGELOG.md Outdated
Comment thread packages/codegen/CHANGELOG.md
Comment thread packages/codegen/lib/src/builder/json_widget_library_builder.dart
Comment thread packages/json_dynamic_widget/CHANGELOG.md
@jpeiffer jpeiffer merged commit 6646c85 into main Nov 9, 2025
1 of 3 checks passed
@jpeiffer jpeiffer deleted the update_codegen branch November 9, 2025 19:37
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant