Skip to content

Commit 00d47d2

Browse files
fix: use raw enum values for cross-enum conflict detection
GetValues() returns prefixed identifier names for enums already marked as conflicting. Using it in the cross-enum comparison loop makes the result order-dependent: an enum that was prefixed in an earlier iteration produces keys like FooStateReady, which no longer match the unprefixed key Ready in a later enum, so the later enum misses the conflict and stays unprefixed. Fix by comparing Schema.EnumValues keys directly, which are always the raw (unprefixed) Go-safe identifiers regardless of PrefixTypeName state.
1 parent d5e17e9 commit 00d47d2

2 files changed

Lines changed: 59 additions & 2 deletions

File tree

pkg/codegen/codegen.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,8 +1028,10 @@ func GenerateEnums(t *template.Template, types []TypeDefinition) (string, error)
10281028
for j := i + 1; j < len(enums); j++ {
10291029
e2 := enums[j]
10301030

1031-
for e1key := range e1.GetValues() {
1032-
_, found := e2.GetValues()[e1key]
1031+
// Use Schema.EnumValues (always unprefixed) rather than GetValues(),
1032+
// which returns prefixed names once an enum is already marked.
1033+
for e1key := range e1.Schema.EnumValues {
1034+
_, found := e2.Schema.EnumValues[e1key]
10331035
if found {
10341036
e1.PrefixTypeName = true
10351037
e2.PrefixTypeName = true

pkg/codegen/codegen_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,5 +329,60 @@ paths:
329329
assert.Contains(t, code, "roleName string")
330330
}
331331

332+
// TestEnumConflictDetectionOrderIndependent checks that conflict detection
333+
// doesn't miss overlaps because an enum was already marked for prefixing.
334+
func TestEnumConflictDetectionOrderIndependent(t *testing.T) {
335+
// AState+BState share "running" (both prefixed), AState+CState share "migrating".
336+
// The bug: once AState was marked, GetValues() returned prefixed names that
337+
// no longer matched CState's raw values, so CState's conflict was missed.
338+
const spec = `
339+
openapi: "3.0.0"
340+
info:
341+
version: 1.0.0
342+
title: Test Enum Conflict Detection
343+
paths: {}
344+
components:
345+
schemas:
346+
AState:
347+
type: string
348+
enum:
349+
- running
350+
- migrating
351+
BState:
352+
type: string
353+
enum:
354+
- running
355+
CState:
356+
type: string
357+
enum:
358+
- migrating
359+
`
360+
loader := openapi3.NewLoader()
361+
swagger, err := loader.LoadFromData([]byte(spec))
362+
require.NoError(t, err)
363+
364+
opts := Configuration{
365+
PackageName: "api",
366+
Generate: GenerateOptions{
367+
Models: true,
368+
},
369+
OutputOptions: OutputOptions{
370+
SkipPrune: true,
371+
},
372+
}
373+
374+
code, err := Generate(swagger, opts)
375+
require.NoError(t, err)
376+
377+
_, err = format.Source([]byte(code))
378+
require.NoError(t, err)
379+
380+
// All three enums share values with at least one other enum; all must be prefixed.
381+
assert.Contains(t, code, "AStateRunning")
382+
assert.Contains(t, code, "AStateMigrating")
383+
assert.Contains(t, code, "BStateRunning")
384+
assert.Contains(t, code, "CStateMigrating")
385+
}
386+
332387
//go:embed test_spec.yaml
333388
var testOpenAPIDefinition string

0 commit comments

Comments
 (0)