Skip to content

feat(macros): add compile-time GTS ID validation to struct_to_gts_schema (#47)#51

Merged
Artifizer merged 7 commits intoGlobalTypeSystem:mainfrom
KvizadSaderah:feature/47-validate-gts-id-in-macro
Feb 12, 2026
Merged

feat(macros): add compile-time GTS ID validation to struct_to_gts_schema (#47)#51
Artifizer merged 7 commits intoGlobalTypeSystem:mainfrom
KvizadSaderah:feature/47-validate-gts-id-in-macro

Conversation

@KvizadSaderah
Copy link
Copy Markdown
Collaborator

@KvizadSaderah KvizadSaderah commented Feb 4, 2026

Summary

  • Add compile-time GTS schema ID validation to struct_to_gts_schema macro, catching invalid IDs before runtime
  • Validate gts. prefix, token count (5-6), version format (vMAJOR[.MINOR]), and token naming rules
  • Detect "too many name tokens before version" case (e.g., x.core.license_enforcer.integration.plugin.v1~ has 5 name tokens instead of 4)
  • Add runtime detection for the same case in gts/src/gts.rs for consistency

Closes #47

Test plan

  • Added compile_fail test invalid_gts_id_too_many_tokens.rs with exact Issue struct_to_gts_schema to ensure if GTS string is valid #47 case
  • Added compile_fail test invalid_gts_id_missing_prefix.rs for prefix validation
  • Updated existing tests with valid GTS IDs
  • All 758 tests pass
  • Clippy clean with -D warnings

Summary by CodeRabbit

  • New Features

    • Added a shared GTS ID validation library and integrated it across the project for unified parsing/validation.
  • Bug Fixes

    • Enforced strict GTS ID format (required prefix, token count, version rules) with clearer, contextual error messages.
    • Replaced ad-hoc local checks with the centralized validator to ensure consistent behavior.
  • Tests

    • Added and updated compile-fail tests to validate new ID parsing and error diagnostics.

Dmitry Efremov added 3 commits February 4, 2026 13:04
Fixes GlobalTypeSystem#47

The macro now validates schema_id format at compile time, catching
invalid GTS IDs early. Validation mirrors the logic from gts/src/gts.rs:

- Must start with 'gts.' prefix
- Must be lowercase, no hyphens
- Must end with '~' (type marker)
- Each segment must have 5-6 tokens
(vendor.package.namespace.type.vMAJOR[.MINOR])
- Version token must start with 'v' followed by integer

Also fixes existing tests that used invalid GTS IDs:
- pretty_test.rs: gts.test.pretty.v1~ -> gts.x.test.entities.pretty.v1~
- inheritance_tests.rs: x.app.content.v1 -> x.app.entities.content.v1
- base_parent_mismatch.rs: gts.x.wrong.parent.v1~ ->
gts.x.wrong.parent.type.v1~
- Use tokens.contains(&"*") instead of iter().any() (clippy::manual_contains)
- Fix GtsError::InvalidSegment -> GtsError::Segment (correct variant name)
- Update version_missing_*.stderr to expect GTS validation error
  (GTS ID validation now catches missing version as "Too few tokens"
  before the version mismatch check runs)
@KvizadSaderah
Copy link
Copy Markdown
Collaborator Author

@Artifizer please review

Comment thread gts-macros/tests/compile_fail/version_missing_both.stderr Outdated
Comment thread gts-macros/src/lib.rs Outdated
Dmitry Efremov added 2 commits February 12, 2026 10:40
Move GTS ID validation logic into a new lightweight gts-id crate to
eliminate duplication between gts (runtime) and gts-macros (compile-time).
Both crates now delegate to gts_id::validate_gts_id() as the single
source of truth.

Also fix segment GlobalTypeSystem#1 error messages to show expected format with gts.
prefix (gts.vendor.package.namespace.type.vMAJOR[.MINOR]) while
segments GlobalTypeSystem#2+ show without prefix, per reviewer feedback.

Signed-off-by: Dmitry Efremov <Dmitry.Efremov@acronis.com>
Signed-off-by: Dmitry Efremov <Dmitry.Efremov@acronis.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 12, 2026

📝 Walkthrough

Walkthrough

A new workspace crate gts-id centralizes GTS ID parsing and validation. The root workspace and crates gts and gts-macros now depend on it; gts delegates runtime parsing and gts-macros uses it for compile-time schema_id validation. Tests and compile-fail expectations were adjusted.

Changes

Cohort / File(s) Summary
Workspace / Manifests
Cargo.toml, gts-macros/Cargo.toml, gts/Cargo.toml
Added gts-id as a workspace member and added gts-id.workspace = true dependencies to gts-macros and gts.
New crate: gts-id
gts-id/Cargo.toml, gts-id/src/lib.rs
Introduced gts-id crate with GTS_PREFIX, GTS_MAX_LENGTH, GtsIdError, ParsedSegment, token/version parsing helpers, validate_segment and validate_gts_id APIs, and unit tests.
gts crate integration
gts/src/gts.rs
Replaced inline GTS parsing with calls to gts_id::validate_segment / gts_id::validate_gts_id; updated GTS_PREFIX to gts_id::GTS_PREFIX; mapped gts-id errors to local GtsError and converted parsed segments into local segment structures.
gts-macros logic
gts-macros/src/lib.rs
Macro now enforces schema_id format (must end with ~) and performs compile-time validation via gts_id::validate_gts_id, translating GtsIdError into compile diagnostics.
gts-macros tests (compile-fail)
gts-macros/tests/compile_fail/*
Added tests invalid_gts_id_missing_prefix.rs and invalid_gts_id_too_many_tokens.rs; updated error expectation stderr files and adjusted base_parent_mismatch.rs literals.
gts-macros tests (integration/attrs)
gts-macros/tests/inheritance_tests.rs, gts-macros/tests/pretty_test.rs
Updated schema_id attribute values on test structs to match expected canonical forms (e.g., switching to ...entities... paths).

Sequence Diagram(s)

sequenceDiagram
    actor Dev
    participant Compiler
    participant Macro as gts-macros (compile-time)
    participant GtsId as gts-id (validator)

    Dev->>Compiler: compile crate with #[struct_to_gts_schema(..., schema_id=...)]
    Compiler->>Macro: expand struct_to_gts_schema (parse attributes)
    Macro->>GtsId: validate_gts_id(schema_id, allow_wildcards=false)
    GtsId-->>Macro: Ok(parsed_segments) / Err(GtsIdError)
    alt Ok
        Macro-->>Compiler: embed validated schema_id / proceed
    else Err
        Macro-->>Compiler: emit compile_error with mapped diagnostics
    end
Loading
sequenceDiagram
    participant Runtime
    participant GtsCrate as gts
    participant GtsId as gts-id (validator)

    Runtime->>GtsCrate: create/parse GTS ID string
    GtsCrate->>GtsId: validate_gts_id(id, allow_wildcards=...)
    GtsId-->>GtsCrate: parsed segments or error
    alt Ok
        GtsCrate->>Runtime: return GtsId instance constructed from parsed data
    else Err
        GtsCrate->>Runtime: return mapped GtsError
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A new burrow called gts-id I made,
To tidy the trails where schema-strings played.
Macros now ask, runtimes agree,
One trusted validator sets IDs free.
Hop, parse, and validate — what a fine parade! 🥕✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely describes the main change: adding compile-time GTS ID validation to the struct_to_gts_schema macro, which matches the core objective of the changeset.
Linked Issues check ✅ Passed All coding requirements from issue #47 are met: compile-time GTS ID validation enforces prefix requirement, token counts (5-6 per segment), version format, naming rules, and trailing tilde marker. New compile_fail tests validate these checks.
Out of Scope Changes check ✅ Passed All changes are directly aligned with #47 objectives: new gts-id crate provides shared validation logic, macros enforce validation at compile-time, and gts crate uses this shared logic for runtime consistency. Test file updates align with new validation requirements.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)

✅ Unit Test PR creation complete.

  • Create PR with unit tests
  • Commit unit tests in branch feature/47-validate-gts-id-in-macro
  • Post copyable unit tests in a comment

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

Signed-off-by: Dmitry Efremov <Dmitry.Efremov@acronis.com>
Copy link
Copy Markdown

@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

🤖 Fix all issues with AI agents
In `@gts-id/src/lib.rs`:
- Around line 564-614: The tests currently use a wildcard `_` arm when asserting
error variants; change those to explicit enum-variant matches to satisfy clippy:
in tests that expect GtsIdError::Id (e.g., test_gts_id_start,
test_gts_id_uppercase, test_gts_id_hyphen) replace `_ => panic!(...)` with an
explicit GtsIdError::Segment { .. } => panic!(...) (or any other concrete non-Id
variant if different), and in test_gts_id_segment_error_carries_num_and_offset
replace `_ => panic!(...)` with an explicit GtsIdError::Id { .. } =>
panic!(...); keep the panic message unchanged and use the same pattern binding
style (`{ .. }`) so the arms remain exhaustive and clear.

Comment thread gts-id/src/lib.rs
Copy link
Copy Markdown

@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

🤖 Fix all issues with AI agents
In `@gts-id/src/lib.rs`:
- Around line 172-192: The current logic skips validating the first four tokens
when ends_with_wildcard is true, letting invalid tokens like "gts.1bad.*" pass;
update the validation in the function handling segment parsing to always
validate tokens[0..4] with is_valid_segment_token, and separately allow a single
'*' only if it is the final token by explicitly rejecting '*' in any of the
first four positions (e.g., check tokens.iter().take(4) and return an error if
token == "*" or !is_valid_segment_token(token)); keep the existing error
messages (using token_name mapping) and ensure the code still permits a trailing
'*' but not wildcards in middle positions.

Comment thread gts-id/src/lib.rs
Tokens preceding a trailing '*' wildcard are now validated against
naming rules. Previously 'gts.1bad.*' would bypass token validation
entirely. Also reject '*' in non-final positions with a clear error.

Signed-off-by: Dmitry Efremov <Dmitry.Efremov@acronis.com>
@KvizadSaderah
Copy link
Copy Markdown
Collaborator Author

Reviewed by Claude — no actionable issues found.

Both Artifizer's review comments addressed:

  1. Segment feat: initial gts-rust implementation - library, cli, server, 90% coverage #1 error messages now show gts.vendor.package... format, segments feat(yaml): added YAML files support #2+ show vendor.package...
  2. Shared validation extracted into gts-id crate (no duplication between gts and gts-macros)

CodeRabbit's wildcard validation bypass — fixed (tokens before * are now validated, * only allowed as the final token).

All CI checks green, 797 tests pass.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 12, 2026

Note

Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

@Artifizer Artifizer merged commit 59ced63 into GlobalTypeSystem:main Feb 12, 2026
7 checks passed
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 12, 2026

✅ Created PR with unit tests: #54

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.

struct_to_gts_schema to ensure if GTS string is valid

2 participants