Skip to content

Conversation

@Ocsidot
Copy link

@Ocsidot Ocsidot commented Jan 20, 2026

Overview

This PR resolves critical a critical issue in the Protobuf schema code generator related to discriminator handling.

Following this fix, during our investigation we also found another issue related on enum management: without extrating enum in separated messages, if enums have similar values, a conflict appears. Thus, we propose to add a new parameter to allow enum extraction, and proper support for enums within array types. The changes ensure correct protobuf generation when models use inheritance, discriminators, and inline/extracted enums.

Issues Fixed

This PR addresses multiple related issues in protobuf code generation:

  1. Import Path Generation: Fixed protobuf import paths for discriminator-based models
  2. Enum Value Collision: Improved logic when extracting enums to prevent naming collisions between enum values
  3. Enum Extraction with Inheritance/Discriminator: Fixed incorrect handling of inline enums in models using inheritance or discriminators
  4. Array of Enums Support: Added proper support for enums within array types when using extractEnumsToSeparateFiles option

Changes Made

1. Improved Protobuf Generation Core

  • Enhanced inheritance management for protobuf models
  • Improved discriminator handling to correctly process complex type hierarchies
  • Implemented enum extraction to separate files with proper message wrapping
  • Added comprehensive unit tests for the new functionality

2. Fixed Enum Value Collision

  • Corrected enum extraction logic when models use inheritance or discriminators
  • Ensures parent model properties are properly included when processing enum values
  • Prevents duplicate or missing field assignments in generated protobuf schemas

3. Added Array of Enums Support

  • Added detection for arrays of enums (property.isArray && property.items.isEnum)
  • Properly applies enum wrapper naming conventions (ParentModel_FieldName.Enum) to array items
  • Ensures consistent enum reference handling between direct properties and array elements
  • Correctly updates protobuf data types for array elements

4. Fixed Enum Extraction in Complex Scenarios

  • Recomputes model hierarchy after processing inherited properties
  • Properly handles wrapper message naming for both inline and referenced enums
  • Corrects data type references when enums are already wrapped with .Enum suffix
  • Improves template compatibility for arrays of extracted enums

Enum Extraction Pattern

When extractEnumsToSeparateFiles is enabled, the generator now properly wraps inline enums to prevent naming collisions:

// Generated enum in separate file (collision-free)
message MyModel_Status {
  enum Enum {
    UNSPECIFIED = 0;
    ACTIVE = 1;
    INACTIVE = 2;
  }
}

message MyModel {
  MyModel_Status.Enum status = 1;
  repeated MyModel_Status.Enum previous_statuses = 2;
}

Testing

  • Updated existing unit tests in ProtobufSchemaCodegenTest
  • Added test coverage for models with inheritance, discriminators, and enum arrays
  • Verified import path generation and wrapper message naming conventions
  • All sample files regenerated successfully

Files Modified

  • modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java
  • modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/protobuf/ProtobufSchemaCodegenTest.java
  • Generated protobuf-schema sample files

Backwards Compatibility

✅ Maintains full backwards compatibility:

  • Changes are internal to the protobuf generator logic
  • Configuration options remain unchanged
  • Existing non-discriminator models continue to generate identically
  • Only fixes generation for previously broken scenarios

PR checklist

  • Read the contribution guidelines.
  • Pull Request title clearly describes the work in the pull request and Pull Request description provides details about how to validate the work. Missing information here may result in delayed response from the community.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • File the PR against the correct branch: master (upcoming 7.x.0 minor release - breaking changes with fallbacks), 8.0.x (breaking changes without fallbacks)
  • If your PR solves a reported issue, reference it using GitHub's linking syntax (e.g., having "fixes #123" present in the PR description)
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Fixes discriminator handling and import paths in the Protobuf schema generator, and adds an option to extract enums to separate files with full support for arrays. This prevents enum name collisions and generates valid schemas for models using inheritance and discriminators.

  • Bug Fixes

    • Correct import paths for allOf + discriminator models, including child references.
    • Fix inline enum handling under inheritance/discriminator hierarchies.
    • Properly reference enums inside arrays.
    • Avoid duplicate model imports.
  • New Features

    • New option: extractEnumsToSeparateFiles, wrapping enums as MessageName.Enum to avoid collisions.
    • Support arrays of enums with the same wrapper pattern.
    • Improved multi-level inheritance and discriminator processing.
    • Updated templates and added targeted unit tests.

Written for commit b94931e. Summary will update on new commits.

Anthony TODISCO and others added 12 commits November 19, 2025 09:52
This PR fixes a critical bug in the protobuf schema generator where models using discriminators with �llOf composition were generating invalid import paths when child schemas contained references to other models.
* Improve management of inheritance
* Improve management of discriminator
* Allow to separate inline enums in external files
* Add unit test
Fix issue linked to enum in array when there is inheritance or discriminator
Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 11 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="modules/openapi-generator/src/test/resources/3_0/protobuf-schema/pet.proto">

<violation number="1" location="modules/openapi-generator/src/test/resources/3_0/protobuf-schema/pet.proto:15">
P1: Imported proto file `models/characteristics.proto` is missing, leaving `Characteristics` unresolved and making the schema uncompilable.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.


package openapitools;

import public "models/characteristics.proto";
Copy link

@cubic-dev-ai cubic-dev-ai bot Jan 20, 2026

Choose a reason for hiding this comment

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

P1: Imported proto file models/characteristics.proto is missing, leaving Characteristics unresolved and making the schema uncompilable.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/test/resources/3_0/protobuf-schema/pet.proto, line 15:

<comment>Imported proto file `models/characteristics.proto` is missing, leaving `Characteristics` unresolved and making the schema uncompilable.</comment>

<file context>
@@ -12,14 +12,20 @@ syntax = "proto3";
 
 package openapitools;
 
+import public "models/characteristics.proto";
+
 message Pet {
</file context>
Fix with Cubic

@wing328
Copy link
Member

wing328 commented Jan 26, 2026

Thanks for the PR.

Is extractEnumsToSeparateFiles similar to the following option in inline schema handling?

RESOLVE_INLINE_ENUMS=true will refactor inline enum definitions into $ref. This must be activated to allow the renaming of inline enum definitions using inlineSchemaMappings.

https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#inline-schema-naming

@Ocsidot
Copy link
Author

Ocsidot commented Jan 27, 2026

Thanks for the PR.

Is extractEnumsToSeparateFiles similar to the following option in inline schema handling?

RESOLVE_INLINE_ENUMS=true will refactor inline enum definitions into $ref. This must be activated to allow the renaming of inline enum definitions using inlineSchemaMappings.

https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#inline-schema-naming

Hello @wing328, good point.

I took some reflection time on this (I've missied this feature at first). I did some test runs to check it and here are my conclusions

While both features deal with enums, extractEnumsToSeparateFiles is fundamentally different from RESOLVE_INLINE_ENUMS. They operate at different layers and solve different problems:

Technical Comparison

RESOLVE_INLINE_ENUMS (InlineModelResolver)

  • Phase: OpenAPI spec normalization (pre-generation)
  • Scope: Generator-agnostic (works for ALL generators)
  • Action: Refactors the OpenAPI spec itself by converting inline enum definitions to $ref references in components/schemas
  • Implementation: InlineModelResolver.java - runs during flatten() before any generator sees the spec
  • Output: Modified OpenAPI document structure
  • Example transformation:
# Before RESOLVE_INLINE_ENUMS
Property: { enum: [A, B, C] }

# After RESOLVE_INLINE_ENUMS
Property: { $ref: '#/components/schemas/Property_inline_enum' }
components/schemas:
  Property_inline_enum: { enum: [A, B, C] }

extractEnumsToSeparateFiles (ProtobufSchemaCodegen)

  • Phase: Protobuf code generation (post-spec processing)
  • Scope: Protobuf-specific only
  • Action: Generates separate .proto files with message wrappers for enums during code generation
  • Implementation: ProtobufSchemaCodegen.java - runs during postProcessModels()
  • Output: Physical .proto files with specific protobuf structure
  • Example transformation:
// Generated file: model_a_status.proto
message ModelA_Status {
  enum Enum {
    UNSPECIFIED = 0;
    ACTIVE = 1;
    INACTIVE = 2;
  }
}

// In model_a.proto
import public "models/model_a_status.proto";
message ModelA {
  ModelA_Status.Enum status = 1;
}

The Critical Difference: Message Wrappers

The key protobuf-specific innovation in extractEnumsToSeparateFiles is the message wrapper pattern with .Enum suffix (see ProtobufSchemaCodegen.java:795):

property.vendorExtensions.put("x-protobuf-data-type", enumTypeName + "." + ENUM_WRAPPER_INNER_NAME);
// Results in: ModelA_Status.Enum

This pattern prevents enum value collisions in protobuf's global namespace - a problem RESOLVE_INLINE_ENUMS doesn't address because it works at the spec level, not the code generation level.

Real-World Problem This PR Solves

Without extractEnumsToSeparateFiles, this OpenAPI spec causes protobuf compilation failures:

ModelA:
  properties:
    status: { enum: [ACTIVE, INACTIVE] }
ModelB:
  properties:
    status: { enum: [ACTIVE, PENDING] }

Both would generate ACTIVE in the global protobuf namespace → collision!

With this PR's solution:

  • ModelA_Status.Enum contains MODELASTATUS_ACTIVE
  • ModelB_Status.Enum contains MODELBSTATUS_ACTIVE
  • No collision ✓

Additional Features in This PR

The new code also fixes critical issues that RESOLVE_INLINE_ENUMS doesn't address:

  1. Arrays of enums (lines 740-760): Properly handles repeated Status.Enum syntax
  2. Discriminator inheritance (lines 744-812, 996-1050): Ensures parent models import child enum files
  3. Referenced vs inline enums (lines 881-948): Both get the .Enum wrapper treatment

I can provide a sample test to verify the behavior of both parameters (I did it to check if I was not missing a point)

Relationship Between Features

These features are complementary, not redundant:

OpenAPI Spec 
    ↓
[RESOLVE_INLINE_ENUMS] ← Spec normalization (optional)
    ↓
Normalized OpenAPI Spec
    ↓
[ProtobufSchemaCodegen]
    ↓
[extractEnumsToSeparateFiles] ← Protobuf-specific code gen (optional)
    ↓
Generated .proto files with message wrappers

You can use both together or independently. They solve different problems at different layers.

Conclusion

extractEnumsToSeparateFiles is a protobuf-specific solution to enum value collision problems that only exist in protobuf's global namespace. RESOLVE_INLINE_ENUMS is a cross-generator spec normalization feature.

Let me know if you'd like me to clarify any specific aspect!

@wing328
Copy link
Member

wing328 commented Jan 27, 2026

extractEnumsToSeparateFiles is a protobuf-specific solution to enum value collision problems that only exist in protobuf's global namespace. RESOLVE_INLINE_ENUMS is a cross-generator spec normalization feature.

Personally I would avoid the overhead in maintaining a specified option in protobuf generator that can potentially be done by RESOLVE_INLINE_ENUMS in inline model resolver but it's entirely your choice. I'm with this option. Just want to make sure you aware of the inline schema resolver option that's already available.

cc @lucy66hw @andrewwilsonnew as well to see if they've opinions on this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants