Skip to content

Conversation

Fellmonkey
Copy link
Contributor

@Fellmonkey Fellmonkey commented Sep 16, 2025

What does this PR do?

  • Fixed a bug that caused double (float) to not be generated correctly — there was an incorrect check in the template (a different type/key was used), now real number processing is aligned.
  • Removed duplicate imports of related models (relationships) — imports are now deduplicated.
  • When strict is enabled: attribute ordering — required fields come first (improved constructor readability).
  • Removed unnecessary null-safe type processing for primitives to avoid “dead” code:
    • simplified and aligned logic for primitive types and arrays (int/double/bool/string), removed unnecessary ?? [] / ?? null/additional checks that generated unnecessary code.

Test Plan

Before:
{9180869F-FE86-4671-8E0B-3CC2D22F52F0}

After:
{1D593E89-7D9A-458B-B178-D6B8F7CC3C46}

After with -s:
{A75D2410-26DC-4020-A756-29645113C05A}

Before (duplicate import):
image
After: (duplicate import)
{49B3C84A-A354-4702-8407-7AA085A266C3}

Related PRs and Issues

(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)

Have you read the Contributing Guidelines on issues?

(Write your answer here.)

Summary by CodeRabbit

  • New Features
    • Required-first attribute ordering in strict mode across fields, constructors, and map mappings.
    • Deduplicated imports for relationship types to avoid repeated imports.
    • Improved fromMap/toMap handling for enums, arrays, nullability, and relationships for more predictable models.
  • Refactor
    • Unified attribute iteration to ensure consistent ordering and separators in all generated sections.
  • Style
    • Updated generated map keys to use single quotes.
    • Minor formatting and comma-alignment adjustments in emitted code.

Copy link

coderabbitai bot commented Sep 16, 2025

Walkthrough

The Dart template switches to a centralized attribute list ___attrs (derived from strict mode) and replaces all collection.attributes references with __attrs, including length checks. Attributes are ordered required-first when strict is true; otherwise, original order is used. Relationship imports are deduplicated via __relatedImportsSeen. Field, constructor, fromMap, and toMap generation now iterate over __attrs. fromMap/toMap logic is refactored: enum handling is adjusted; array/nullability behavior is revised; relationship mapping applies element fromMap where applicable. Map key quotes in toMap are changed to single quotes. Comma/separator handling aligns with __attrs.length.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "CLI Dart: model generation fixes" is concise and accurately summarizes the primary purpose of the changeset—fixes to Dart model generation in the CLI templates (type handling, import deduplication, and attribute ordering) as reflected in the raw summary and PR objectives. It is specific enough for a teammate scanning history and avoids noisy or irrelevant details.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
templates/cli/lib/type-generation/languages/dart.js.twig (3)

108-108: Consider adding trailing comma consistency for better diff management.

Currently, the enum generation conditionally adds commas. Adding a trailing comma after the last element would improve git diffs when new enum values are added.

Apply this diff to add consistent trailing commas:

-  <%- strict ? toCamelCase(element) : element %><% if (index < attribute.elements.length - 1) { -%>,<% } %>
+  <%- strict ? toCamelCase(element) : element %>,

131-131: Potential null reference error in enum array mapping.

When map['<%= attribute.key %>'] is null, the optional chaining ?.map() will return null, but there's no null fallback like other array types have. This could cause issues if the consuming code expects a non-null list.

Consider adding a null fallback for consistency:

-(map['<%= attribute.key %>'] as List<dynamic>?)?.map((e) => <%- toPascalCase(attribute.key) %>.values.firstWhere((element) => element.name == e)).toList()
+(map['<%= attribute.key %>'] as List<dynamic>?)?.map((e) => <%- toPascalCase(attribute.key) %>.values.firstWhere((element) => element.name == e)).toList() ?? []

155-155: Missing null fallback for relationship arrays.

Similar to the enum array issue, relationship arrays don't have a null fallback when the map value is null, which could cause inconsistency with other array types.

Consider adding a null fallback for consistency:

-(map['<%= attribute.key %>'] as List<dynamic>?)?.map((e) => <%- toPascalCase(collections.find(c => c.$id === attribute.relatedCollection).name) %>.fromMap(e)).toList()
+(map['<%= attribute.key %>'] as List<dynamic>?)?.map((e) => <%- toPascalCase(collections.find(c => c.$id === attribute.relatedCollection).name) %>.fromMap(e)).toList() ?? []
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6fda9e5 and f483254.

📒 Files selected for processing (1)
  • templates/cli/lib/type-generation/languages/dart.js.twig (1 hunks)
🔇 Additional comments (5)
templates/cli/lib/type-generation/languages/dart.js.twig (5)

86-93: LGTM! Well-structured attribute ordering implementation.

The implementation properly handles required-first ordering when strict mode is enabled, while preserving original order otherwise. The use of __attrs as a single source of truth throughout the template is a clean architectural decision.


88-102: LGTM! Effective deduplication of relationship imports.

The use of a Set to track seen imports efficiently prevents duplicate imports for related models. The logic correctly identifies and imports only unique relationship types.


168-181: LGTM! Clean toMap implementation.

The toMap method correctly handles all attribute types with proper null-safe navigation. The switch to single quotes for map keys is consistent with Dart conventions.


115-122: LGTM! Consistent field and constructor generation.

The field declarations and constructor parameters correctly use __attrs as the source, maintaining consistency with the ordering logic and properly marking required fields.


138-139: String conversion may cause runtime errors for null values.

The .toString() call on Line 139 will throw if map['<%= attribute.key %>'] is null for required string fields. This could cause runtime failures during deserialization.

Apply this diff to handle null values safely:

-map['<%= attribute.key %>']<% if (!attribute.required) { %>?<% } %>.toString()
+<% if (attribute.required) { %>map['<%= attribute.key %>'].toString()<% } else { %>map['<%= attribute.key %>']?.toString()<% } %>

Likely an incorrect or invalid review comment.

@Fellmonkey
Copy link
Contributor Author

@ChiragAgg5k hello

<% } else if (attribute.type === 'float') { -%>
List<int>.from(map['<%= attribute.key %>'] ?? [])<% } else { -%>
map['<%= attribute.key %>']<% } -%>
<% } else if (attribute.type === 'double') { -%>
Copy link
Member

Choose a reason for hiding this comment

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

can we use the Attribute.FLOAT typing from attribute.js file?

i know the mismatch there is confusing but lets keep the confusion in one file only 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Like this?
image

Copy link
Member

Choose a reason for hiding this comment

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

yes please, also in other places applicable

Copy link
Contributor Author

Choose a reason for hiding this comment

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

in C#, we'll also have to do

if (a.required === b.required) return 0;
return a.required ? -1 : 1;
}); -%>
<% const __attrs = strict ? sortedAttributes : collection.attributes; -%>
Copy link
Member

Choose a reason for hiding this comment

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

a question, we have strict flag only for breaking changes. i.e if you enable strict, the casing might change, leading to mismatch between what the API defines and what type defines

is a different strict ordering really needed here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

since strict explicitly enables breaking changes, it's best to apply the language's conventions end-to-end — not just casing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I also customized the generator for myself, a class with constant field values. It's convenient when you need to update 2-5 fields without creating a model. An idea to think about.
{BA00F7BC-93C1-4CAD-984E-8AE8CEC8AFF8}

Copy link
Member

Choose a reason for hiding this comment

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

@Fellmonkey soo ordering by language conversions here is breaking? if not can we follow language conventions by default?

@ChiragAgg5k
Copy link
Member

@Fellmonkey left some very small comments

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants