Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ object CodeGenerator {
outputDir: File,
options: OutputOptions = OutputOptions(),
): Result {
val resolvedApiSpec = spec.resolveInlines()

val hierarchy = Hierarchy(ModelPackage(modelPackage)).apply {
addSchemas(spec.schemas)
addSchemas(resolvedApiSpec.schemas.map { it.schema })
}

val (modelFiles, resolvedSpec) = context(hierarchy, options, NameRegistry()) {
ModelGenerator.generateWithResolvedSpec(spec)
ModelGenerator.generateWithResolvedSpec(resolvedApiSpec)
}

modelFiles.forEach { it.writeTo(outputDir) }
Expand Down
20 changes: 17 additions & 3 deletions core/src/main/kotlin/com/avsystem/justworks/core/gen/Hierarchy.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ internal class Hierarchy(val modelPackage: ModelPackage) {
private val schemaModels = mutableSetOf<SchemaModel>()
private val memoScope = MemoScope()

/**
* Resolution overrides for inline body types nested inside client/model classes,
* keyed by the reference id assigned by [resolved].
*/
private val inlineRefs = mutableMapOf<String, ClassName>()

/** Registers the nested [ClassName] an inline reference id resolves to. */
fun registerInlineRef(id: String, className: ClassName) {
inlineRefs[id] = className
}

/**
* Updates the underlying schemas and invalidates all cached derived views.
* This is necessary when schemas are updated (e.g., after inlining types).
Expand Down Expand Up @@ -60,20 +71,23 @@ internal class Hierarchy(val modelPackage: ModelPackage) {
.mapValues { (_, parents) -> parents.toSet() }
}

/** Top-level [ClassName] for a component schema/enum name, normalized to a PascalCase identifier. */
fun classNameFor(schemaName: String): ClassName = ClassName(modelPackage, schemaName.toPascalCase())

/** Maps schema name to its [ClassName], using nested class for discriminated hierarchy variants. */
private val lookup: Map<String, ClassName> by memoized(memoScope) {
sealedHierarchies
.asSequence()
.filterNot { (parent, _) -> parent in anyOfWithoutDiscriminator }
.flatMap { (parent, variants) ->
val parentClass = ClassName(modelPackage, parent)
val parentClass = classNameFor(parent)
variants.map { variant -> variant to parentClass.nestedClass(variant.toPascalCase()) } +
(parent to parentClass)
}.toMap()
}

/** Resolves a schema name to its [ClassName], falling back to a flat top-level class. */
operator fun get(name: String): ClassName = lookup[name] ?: ClassName(modelPackage, name)
/** Resolves a schema name (or inline-ref id) to its [ClassName], falling back to a flat top-level class. */
operator fun get(name: String): ClassName = inlineRefs[name] ?: lookup[name] ?: classNameFor(name)
}

private fun SchemaModel.variants() = oneOf ?: anyOf

This file was deleted.

This file was deleted.

This file was deleted.

Loading
Loading