Skip to content

Generate typed enums for inline enums in array items#76

Open
halotukozak wants to merge 9 commits into
masterfrom
fix/inline-enum-array-items
Open

Generate typed enums for inline enums in array items#76
halotukozak wants to merge 9 commits into
masterfrom
fix/inline-enum-array-items

Conversation

@halotukozak

Copy link
Copy Markdown
Member

Summary

Fixes #74. Inline enums declared directly in array items (or inline on a property) were generated as plain String, losing both the enum values and type safety.

Before

public val measurements: List<String>? = null

After

@Serializable
public enum class ExecuteSpeedTestRequest_MeasurementsItem {
    @SerialName("DownloadSpeed") DOWNLOAD_SPEED,
    @SerialName("UploadSpeed") UPLOAD_SPEED,
}
// ...
public val measurements: List<ExecuteSpeedTestRequest_MeasurementsItem>? = null

Changes

  • New TypeRef.InlineEnum variant.
  • SpecParser emits InlineEnum for enum schemas that are not named components (named component enums still resolve to Reference). Null enum entries (nullable markers) are filtered.
  • ModelGenerator collects inline enums, deduplicates structurally (InlineEnumKey), registers names via the shared NameRegistry, generates an EnumModel, and resolves references — mirroring inline-object handling.
  • The duplicated collect → dedup → name → model pipeline for inline objects and enums is unified into collectInlineDefinitions + topLevelTypeRefs.

Tests

  • SpecParserInlineEnumTest — parser produces Array(InlineEnum) from the spec.
  • ModelGeneratorInlineEnumTest — a typed enum class is generated and the property references it.
  • Naming follows the existing inline convention (<Parent>_<Property>Item).

Out of scope (separate follow-ups, noted in #74)

  • uniqueItems: true still maps to List (not Set).
  • Array default is still dropped (nullable property defaults to null).

🤖 Generated with Claude Code

Inline enums declared in array `items` (or inline on a property) were
emitted as plain `String`, dropping enum values and type safety.

Add `TypeRef.InlineEnum`; the parser now emits it for enum schemas that
are not named components. `ModelGenerator` collects, deduplicates, names,
and generates an `EnumModel` for each, resolving references like inline
objects. The shared collect/dedup/name pipeline for inline objects and
enums is unified in `collectInlineDefinitions`.

Closes #74

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

Coverage Report

Overall Project 96.5% -0.65% 🍏
Files changed 88.49% 🍏

File Coverage
InlineCollector.kt 100% 🍏
TypeRef.kt 100% 🍏
SpecParser.kt 95.58% -0.24% 🍏
ModelGenerator.kt 95.18% -0.1% 🍏
InlineTypeResolver.kt 92.82% -2.56% 🍏
InlineSchemaKey.kt 86.75% -6.62%
Utils.kt 80.3% -19.32%

halotukozak and others added 8 commits June 8, 2026 16:18
Traversal order is irrelevant downstream (results are sorted by
contextHint then deduplicated), so drop the addFirst container handling.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
collectInlineTypeRefs and collectInlineEnumRefs were the same tree walk
differing only in the collected variant. Replace both with walkTypeRefs;
callers filterIsInstance for the variant they need. Structural dedup
already happens downstream via distinctBy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the manual ArrayDeque loop with a DeepRecursiveFunction that
returns each node plus its descendants, matching the codebase idiom used
by containsUnknown. Stack-safe on deeply nested schemas.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The marker named a capability ("has a context hint") rather than the
concept. InlineType is a proper sealed subtype grouping Inline and
InlineEnum: schemas defined anonymously inline that must be hoisted into
named declarations, with contextHint as the naming seed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the inline schema/enum collection (walk, dedup, name, model) out of
ModelGenerator into InlineCollector, alongside the resolution half. The
generic pipeline is now collectInlineSchemas/collectInlineEnums building on
inlineRefs + toNamedModels. ModelGenerator stays focused on KotlinPoet
generation (729 -> 634 lines).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
inlineRefs now returns a Sequence and toNamedModels consumes it directly,
removing the intermediate flatMap/filterIsInstance lists before the sort.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lazy from the roots through descendants/filter into the sort, dropping the
intermediate root lists and the asSequence hop in inlineRefs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@halotukozak halotukozak self-assigned this Jun 8, 2026
@halotukozak halotukozak added this to the 1.0.0 milestone Jun 9, 2026
@halotukozak halotukozak requested a review from mzielu June 9, 2026 15:00
@halotukozak halotukozak added the bug Something isn't working label Jun 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inline enums in array items are generated as plain String

1 participant