Skip to content

feat: add codegen support for @BoundAny field generation#660

Merged
david-waltermire merged 1 commit intometaschema-framework:developfrom
david-waltermire:feature/any-codegen
Feb 8, 2026
Merged

feat: add codegen support for @BoundAny field generation#660
david-waltermire merged 1 commit intometaschema-framework:developfrom
david-waltermire:feature/any-codegen

Conversation

@david-waltermire
Copy link
Contributor

@david-waltermire david-waltermire commented Feb 8, 2026

Summary

  • Add AnyInstanceTypeInfoImpl to generate @BoundAny-annotated IAnyContent fields during code generation
  • Update AssemblyDefinitionTypeInfoImpl.processModel() to handle IAnyInstance from assembly definitions
  • Add codegen test verifying generated class structure matches the hand-written AnyAssembly fixture
  • Add Claude rule documenting the full scope of changes required when adding new Metaschema model features

This complements PR #657 which added runtime <any/> support (core model, databind I/O, schemagen) but did not update the code generator. Without this change, generated binding classes for assemblies with <any/> would not capture unmodeled content.

Closes #220

Test plan

  • AnyCodegenTest verifies generated class has @BoundAny field of type IAnyContent with getter/setter
  • All 236 databind tests pass
  • Full CI build (mvn clean install -PCI -Prelease) passes with 0 SpotBugs/Checkstyle violations

Summary by CodeRabbit

  • New Features

    • Code generation now supports assemblies with unmodeled (flexible) content, producing appropriately-typed fields with the needed annotations.
  • Tests

    • Added tests verifying generation of annotated fields and corresponding accessors for flexible-content assemblies.
  • Documentation

    • Added a comprehensive Metaschema feature checklist covering mandatory/conditional areas and verification steps.

@coderabbitai
Copy link

coderabbitai bot commented Feb 8, 2026

📝 Walkthrough

Walkthrough

Adds Java binding support for Metaschema "any" instances: new AnyInstanceTypeInfoImpl, integration into assembly type-info mapping, a codegen test, and a new checklist document. No runtime behavior changes beyond codegen/typeinfo and tests.

Changes

Cohort / File(s) Summary
Documentation
.claude/rules/new-metaschema-feature-checklist.md
Adds a new checklist documenting mandatory/conditional areas and verification steps for implementing Metaschema features.
TypeInfo Implementation
databind/src/main/java/dev/metaschema/databind/codegen/typeinfo/AnyInstanceTypeInfoImpl.java
New class providing type info for IAnyInstance: base name "any", non-required, Java field type IAnyContent, and buildField() adds @BoundAny.
Assembly Integration
databind/src/main/java/dev/metaschema/databind/codegen/typeinfo/def/AssemblyDefinitionTypeInfoImpl.java
Includes handling of definition.getAnyInstance() by wrapping it with AnyInstanceTypeInfoImpl and appending it to the instance-to-type-info stream.
Tests
databind/src/test/java/dev/metaschema/databind/codegen/AnyCodegenTest.java
New unit test asserting generated field is annotated with @BoundAny, typed as IAnyContent, and has corresponding accessors.

Sequence Diagram

sequenceDiagram
    participant Codegen as Codegen
    participant Assy as AssemblyDefinitionTypeInfoImpl
    participant AnyInfo as AnyInstanceTypeInfoImpl
    participant Builder as TypeSpec.Builder

    Codegen->>Assy: buildInstanceMap(definition)
    Assy->>Assy: collect flag & model instances
    alt definition.getAnyInstance() != null
        Assy->>AnyInfo: wrap(definition.getAnyInstance(), parent)
        AnyInfo-->>Assy: AnyInstanceTypeInfoImpl
        Assy->>Assy: append AnyInstance to instance stream
    end
    Assy->>AnyInfo: buildField(typeBuilder, fieldBuilder)
    AnyInfo->>Builder: add `@BoundAny` to field
    AnyInfo-->>Assy: return (empty set)
    Assy-->>Codegen: instance-to-type-info map ready
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested reviewers

  • aj-stein

Poem

🐰 I hopped through defs to find "any" at play,

Bound with a tag where content may stay;
IAnyContent tucked in a field so neat,
Tests nod approval with every beat,
Hooray for codegen — a rabbit's small treat!

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: adding code generation support for @BoundAny field generation, which is the main focus of the PR.
Linked Issues check ✅ Passed The PR fulfills the coding requirements of issue #220 by implementing @BoundAny annotation support in code generation, complementing prior XML/YAML parsing changes.
Out of Scope Changes check ✅ Passed All changes align with the PR's stated objective of adding codegen support for @BoundAny fields. The documentation file and tests are supporting artifacts for this core change.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
databind/src/test/java/dev/metaschema/databind/codegen/AnyCodegenTest.java (1)

52-59: Redundant assertNotNull calls after getMethod().

The assertNotNull checks on lines 53 and 59 are unnecessary because Class.getMethod() already throws NoSuchMethodException if the method is not found (which is declared in the test's throws clause). The test would fail with a clear exception message either way.

♻️ Suggested simplification
     // Verify getter exists and returns IAnyContent
     Method getter = rootClass.getMethod("getAny");
-    assertNotNull(getter, "Generated class should have getAny() method");
     assertTrue(IAnyContent.class.isAssignableFrom(getter.getReturnType()),
         "getAny() should return IAnyContent");

     // Verify setter exists and accepts IAnyContent
     Method setter = rootClass.getMethod("setAny", IAnyContent.class);
-    assertNotNull(setter, "Generated class should have setAny(IAnyContent) method");

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 PMD (7.21.0)
databind/src/main/java/dev/metaschema/databind/codegen/typeinfo/def/AssemblyDefinitionTypeInfoImpl.java

[ERROR] Cannot load ruleset pmd/category/java/custom.xml: Cannot resolve rule/ruleset reference 'pmd/category/java/custom.xml'. Make sure the resource is a valid file or URL and is on the CLASSPATH. Use --debug (or a fine log level) to see the current classpath.
[WARN] Progressbar rendering conflicts with reporting to STDOUT. No progressbar will be shown. Try running with argument -r to output the report to a file instead.

databind/src/main/java/dev/metaschema/databind/codegen/typeinfo/AnyInstanceTypeInfoImpl.java

[ERROR] Cannot load ruleset pmd/category/java/custom.xml: Cannot resolve rule/ruleset reference 'pmd/category/java/custom.xml'. Make sure the resource is a valid file or URL and is on the CLASSPATH. Use --debug (or a fine log level) to see the current classpath.
[WARN] Progressbar rendering conflicts with reporting to STDOUT. No progressbar will be shown. Try running with argument -r to output the report to a file instead.

databind/src/test/java/dev/metaschema/databind/codegen/AnyCodegenTest.java

[ERROR] Cannot load ruleset pmd/category/java/custom.xml: Cannot resolve rule/ruleset reference 'pmd/category/java/custom.xml'. Make sure the resource is a valid file or URL and is on the CLASSPATH. Use --debug (or a fine log level) to see the current classpath.
[WARN] Progressbar rendering conflicts with reporting to STDOUT. No progressbar will be shown. Try running with argument -r to output the report to a file instead.


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

…framework#220)

The code generator now emits @BoundAny-annotated IAnyContent fields
when an assembly definition contains <any/> in its model. This
complements the runtime <any/> support added in PR metaschema-framework#657 by enabling
generated binding classes to capture unmodeled content.

Also adds a Claude rule documenting the full scope of changes required
when adding new Metaschema model features.
@david-waltermire david-waltermire merged commit 1ce3494 into metaschema-framework:develop Feb 8, 2026
6 checks passed
@david-waltermire david-waltermire deleted the feature/any-codegen branch February 8, 2026 16:05
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.

1 participant