fix(gts-macros): make GTS type/id field optional and fix deserialization#73
Conversation
📝 WalkthroughWalkthroughRefactors struct_to_gts_schema validation to a properties-driven model: base structs may optionally include ID or GTS Type fields, but only fields listed in the macro's properties are treated as GTS fields. Tests and error messages updated; new compile-time check enforces that GTS fields present on a struct are listed in properties. Changes
Sequence Diagram(s)sequenceDiagram
participant UserMacro as "struct_to_gts_schema (macro)"
participant PropParser as "Properties Parser"
participant FieldValidator as "Field Type Validator"
participant GtsValidator as "GTS Fields-in-Properties Validator"
UserMacro->>PropParser: parse `properties` arg -> property_names
PropParser-->>UserMacro: property_names
UserMacro->>FieldValidator: validate_field_types(fields, property_names)
FieldValidator-->>UserMacro: field-type validation result
UserMacro->>GtsValidator: validate_gts_fields_in_properties(struct, base, property_names)
GtsValidator-->>UserMacro: ensure any GTS fields are listed in properties or emit compile error
alt GTS fields listed in properties
UserMacro->>UserMacro: treat listed fields as GTS id/type (apply GTS rules)
else GTS fields present but not listed
UserMacro-->>UserMacro: emit compile-time error
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@gts-macros/src/lib.rs`:
- Around line 628-631: The function add_serde_skip_for_gts_fields currently
pushes a fresh #[serde(skip, default)] onto field.attrs when a field is not in
property_names, which can create duplicate serde options if the field already
has a serde attribute; update the logic in add_serde_skip_for_gts_fields to
inspect existing attributes in field.attrs for an attribute with path "serde"
and parse its meta to determine if "skip" and/or "default" are already present,
then only add the missing option(s) (either by appending the missing tokens to
the existing serde attribute or by creating a single serde attribute that merges
existing and missing options) so that duplicate serde options are never produced
for the same field_name and serde attribute.
In `@gts/src/gts.rs`:
- Around line 477-481: The Default impls for GtsInstanceId (and the same for
GtsSchemaId) construct an invalid empty ID; remove these impls instead of
returning Self(GtsEntityId::new("")) so core ID types never expose invalid
defaults. Delete the impl Default blocks for GtsInstanceId and GtsSchemaId and
update any code/tests that relied on Default to supply IDs explicitly or use the
macro-generated field defaults/Option at the call site for skipped metadata
fields.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 075b3c7c-b3d3-46c3-a010-d41a1905c5b6
📒 Files selected for processing (18)
gts-macros/README.mdgts-macros/src/lib.rsgts-macros/tests/compile_fail/base_parent_mismatch.stderrgts-macros/tests/compile_fail/base_parent_single_segment.stderrgts-macros/tests/compile_fail/base_struct_both_id_and_type.stderrgts-macros/tests/compile_fail/base_struct_missing_id.rsgts-macros/tests/compile_fail/base_struct_missing_id.stderrgts-macros/tests/compile_fail/base_struct_wrong_gts_type.rsgts-macros/tests/compile_fail/base_struct_wrong_gts_type.stderrgts-macros/tests/compile_fail/base_struct_wrong_id_type.rsgts-macros/tests/compile_fail/base_struct_wrong_id_type.stderrgts-macros/tests/compile_fail/base_true_multi_segment.stderrgts-macros/tests/compile_fail/non_gts_generic.stderrgts-macros/tests/compile_fail/version_mismatch_major.stderrgts-macros/tests/compile_fail/version_mismatch_minor_missing_schema.stderrgts-macros/tests/compile_fail/version_mismatch_minor_missing_struct.stderrgts-macros/tests/inheritance_tests.rsgts/src/gts.rs
💤 Files with no reviewable changes (7)
- gts-macros/tests/compile_fail/base_struct_wrong_gts_type.rs
- gts-macros/tests/compile_fail/base_struct_wrong_gts_type.stderr
- gts-macros/tests/compile_fail/base_struct_missing_id.rs
- gts-macros/tests/compile_fail/base_struct_wrong_id_type.stderr
- gts-macros/tests/compile_fail/base_struct_wrong_id_type.rs
- gts-macros/tests/compile_fail/base_parent_single_segment.stderr
- gts-macros/tests/compile_fail/base_struct_missing_id.stderr
c078e24 to
5d0a0a1
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
gts-macros/src/lib.rs (1)
238-243: Extract sharedpropertiesparsing into one helper.
propertiesparsing is duplicated in multiple places. Centralizing this into a helper reduces drift risk and keeps validation behavior consistent.Also applies to: 607-611, 906-911
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@gts-macros/src/lib.rs` around lines 238 - 243, Extract the duplicated parsing logic into a single helper function (e.g., fn parse_property_names(input: &str) -> Vec<String>) that trims, splits on ',', filters out empty entries, and returns Vec<String>; replace the inline code in places that currently do the split/trim/filter (the block creating property_names from args.properties and the similar blocks at the other occurrences) with calls to this helper (and update callers to pass &str where needed), and keep validation behavior identical by reusing the same helper wherever properties are parsed.gts-macros/tests/inheritance_tests.rs (1)
169-169: Tighten regression coverage for the newidproperty inclusion.Now that
TopicV1includesidinproperties, please also assertidin the schema-field-path expectation to lock this behavior and prevent silent regressions.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@gts-macros/tests/inheritance_tests.rs` at line 169, Update the test that checks schema-field-path expectations for TopicV1 to include an assertion for the new "id" property: locate the test referencing TopicV1 and the variable used for the expected schema field paths (e.g., the schema-field-path expectation array or set) and add "id" to that expectation so the test fails if "id" is ever removed; ensure the assertion references TopicV1 and the same expectation variable name used in the test so the coverage is tightened for the new property.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@gts-macros/src/lib.rs`:
- Around line 628-643: The current code in struct_to_gts_schema that checks
(is_gts_id_field || is_gts_type_field) and returns Err when field_name isn't in
property_names causes a hard compile error; change this to allow the shape
non-fatally by removing the Err return and instead skipping/ignoring that field
so code generation continues (i.e., do not treat GTS id/type fields missing from
properties as a fatal error). If you want to surface diagnostics, emit a
non-blocking warning via proc_macro_error::emit_warning (or equivalent)
referencing ident and input.ident, but do not abort macro expansion.
---
Nitpick comments:
In `@gts-macros/src/lib.rs`:
- Around line 238-243: Extract the duplicated parsing logic into a single helper
function (e.g., fn parse_property_names(input: &str) -> Vec<String>) that trims,
splits on ',', filters out empty entries, and returns Vec<String>; replace the
inline code in places that currently do the split/trim/filter (the block
creating property_names from args.properties and the similar blocks at the other
occurrences) with calls to this helper (and update callers to pass &str where
needed), and keep validation behavior identical by reusing the same helper
wherever properties are parsed.
In `@gts-macros/tests/inheritance_tests.rs`:
- Line 169: Update the test that checks schema-field-path expectations for
TopicV1 to include an assertion for the new "id" property: locate the test
referencing TopicV1 and the variable used for the expected schema field paths
(e.g., the schema-field-path expectation array or set) and add "id" to that
expectation so the test fails if "id" is ever removed; ensure the assertion
references TopicV1 and the same expectation variable name used in the test so
the coverage is tightened for the new property.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 2c8a7f5c-53b2-4094-847c-f67ae00bc749
📒 Files selected for processing (19)
gts-macros/README.mdgts-macros/src/lib.rsgts-macros/tests/compile_fail/base_parent_mismatch.stderrgts-macros/tests/compile_fail/base_parent_single_segment.stderrgts-macros/tests/compile_fail/base_struct_both_id_and_type.stderrgts-macros/tests/compile_fail/base_struct_missing_id.rsgts-macros/tests/compile_fail/base_struct_missing_id.stderrgts-macros/tests/compile_fail/base_struct_wrong_gts_type.rsgts-macros/tests/compile_fail/base_struct_wrong_gts_type.stderrgts-macros/tests/compile_fail/base_struct_wrong_id_type.rsgts-macros/tests/compile_fail/base_struct_wrong_id_type.stderrgts-macros/tests/compile_fail/base_true_multi_segment.stderrgts-macros/tests/compile_fail/gts_field_not_in_properties.rsgts-macros/tests/compile_fail/gts_field_not_in_properties.stderrgts-macros/tests/compile_fail/non_gts_generic.stderrgts-macros/tests/compile_fail/version_mismatch_major.stderrgts-macros/tests/compile_fail/version_mismatch_minor_missing_schema.stderrgts-macros/tests/compile_fail/version_mismatch_minor_missing_struct.stderrgts-macros/tests/inheritance_tests.rs
💤 Files with no reviewable changes (7)
- gts-macros/tests/compile_fail/base_struct_wrong_id_type.stderr
- gts-macros/tests/compile_fail/base_struct_missing_id.rs
- gts-macros/tests/compile_fail/base_struct_wrong_gts_type.rs
- gts-macros/tests/compile_fail/base_struct_missing_id.stderr
- gts-macros/tests/compile_fail/base_struct_wrong_gts_type.stderr
- gts-macros/tests/compile_fail/base_struct_wrong_id_type.rs
- gts-macros/tests/compile_fail/base_parent_single_segment.stderr
🚧 Files skipped from review as they are similar to previous changes (1)
- gts-macros/tests/compile_fail/base_true_multi_segment.stderr
Signed-off-by: Andre Smith <andre.smith@acronis.com>
5d0a0a1 to
e905b30
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
gts-macros/src/lib.rs (1)
628-643:⚠️ Potential issue | 🟠 MajorHard compile rejection regresses the optional GTS field migration path.
This branch aborts macro expansion when a
GtsSchemaId/GtsInstanceIdfield exists but is not listed inproperties, which conflicts with the stated optional-field behavior and can break existing base structs that intentionally keep these fields out of schema properties. Please make this non-fatal and keep the deserialization-safe omission path instead of returning an error here.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@gts-macros/src/lib.rs` around lines 628 - 643, The macro currently returns Err when a field with is_gts_id_field or is_gts_type_field is missing from property_names, which hard-fails expansion; change this to a non-fatal path so omitted GtsSchemaId/GtsInstanceId fields are allowed: instead of returning Err in the branch that references is_gts_id_field, is_gts_type_field, property_names, field_name, and type_desc, skip emitting an error and either continue processing the field (i.e., treat it as a non-property/optional field) or emit a compile-time warning using the span (ident) rather than aborting; ensure downstream code that expects optional omission still behaves the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@gts-macros/README.md`:
- Around line 261-266: The fenced error-output block containing the message
starting with "error: struct_to_gts_schema: Field `gts_type`..." is missing a
language tag; update the opening fence from ``` to ```text so the block is
marked as plain text (this will satisfy markdownlint MD040). Locate the block
showing the struct_to_gts_schema error and change its fence accordingly; no
other content changes are required (the block references
RateLimitErrorV1::gts_schema_id() and RateLimitErrorV1::SCHEMA_ID for context).
---
Duplicate comments:
In `@gts-macros/src/lib.rs`:
- Around line 628-643: The macro currently returns Err when a field with
is_gts_id_field or is_gts_type_field is missing from property_names, which
hard-fails expansion; change this to a non-fatal path so omitted
GtsSchemaId/GtsInstanceId fields are allowed: instead of returning Err in the
branch that references is_gts_id_field, is_gts_type_field, property_names,
field_name, and type_desc, skip emitting an error and either continue processing
the field (i.e., treat it as a non-property/optional field) or emit a
compile-time warning using the span (ident) rather than aborting; ensure
downstream code that expects optional omission still behaves the same.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1fefb5f5-c4dc-43d8-bd3f-281109d306d4
📒 Files selected for processing (19)
gts-macros/README.mdgts-macros/src/lib.rsgts-macros/tests/compile_fail/base_parent_mismatch.stderrgts-macros/tests/compile_fail/base_parent_single_segment.stderrgts-macros/tests/compile_fail/base_struct_both_id_and_type.stderrgts-macros/tests/compile_fail/base_struct_missing_id.rsgts-macros/tests/compile_fail/base_struct_missing_id.stderrgts-macros/tests/compile_fail/base_struct_wrong_gts_type.rsgts-macros/tests/compile_fail/base_struct_wrong_gts_type.stderrgts-macros/tests/compile_fail/base_struct_wrong_id_type.rsgts-macros/tests/compile_fail/base_struct_wrong_id_type.stderrgts-macros/tests/compile_fail/base_true_multi_segment.stderrgts-macros/tests/compile_fail/gts_field_not_in_properties.rsgts-macros/tests/compile_fail/gts_field_not_in_properties.stderrgts-macros/tests/compile_fail/non_gts_generic.stderrgts-macros/tests/compile_fail/version_mismatch_major.stderrgts-macros/tests/compile_fail/version_mismatch_minor_missing_schema.stderrgts-macros/tests/compile_fail/version_mismatch_minor_missing_struct.stderrgts-macros/tests/inheritance_tests.rs
💤 Files with no reviewable changes (7)
- gts-macros/tests/compile_fail/base_struct_missing_id.rs
- gts-macros/tests/compile_fail/base_struct_wrong_id_type.rs
- gts-macros/tests/compile_fail/base_parent_single_segment.stderr
- gts-macros/tests/compile_fail/base_struct_wrong_id_type.stderr
- gts-macros/tests/compile_fail/base_struct_wrong_gts_type.stderr
- gts-macros/tests/compile_fail/base_struct_missing_id.stderr
- gts-macros/tests/compile_fail/base_struct_wrong_gts_type.rs
🚧 Files skipped from review as they are similar to previous changes (4)
- gts-macros/tests/compile_fail/gts_field_not_in_properties.rs
- gts-macros/tests/compile_fail/version_mismatch_minor_missing_struct.stderr
- gts-macros/tests/compile_fail/base_true_multi_segment.stderr
- gts-macros/tests/compile_fail/gts_field_not_in_properties.stderr
Description
The
struct_to_gts_schemamacro required base structs to have a GTS type or ID field, even when the field had no runtime purpose. The schema ID is already accessible viaSelf::gts_schema_id()andSelf::SCHEMA_IDthrough theGtsSchematrait. This forced users into manual serde workarounds to avoid deserialization failures.This change makes the id/type fully optional on base structs. When a GTS field is present, it must be listed in properties, otherwise the macro emits a clear compile error guiding the user to either add it to properties or remove it from the struct.
What changed
id: Uuidare treated as regular fields and would not trigger a GTS field validation.Why this change was necessary
Resolves #72
Type of Change
Testing
id: Uuidis not misidentified as a GTS ID FieldChecklist
cargo test)cargo fmt)cargo clippy)Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Tests