Skip to content

Commit

Permalink
Fix inline schema definitions inherited from a parent. (#269)
Browse files Browse the repository at this point in the history
* Fix inline schema definitions inherited from a parent.
When an inline schema is inherited, the child should reference the parent definition, and not build ain incompatible child version

* Add test for enum
  • Loading branch information
cjbooms authored Mar 5, 2024
1 parent a8a6c85 commit 1222719
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -282,16 +282,20 @@ class JacksonModelGenerator(
} else {
when (it) {
is PropertyInfo.ObjectInlinedField -> {
val props = it.schema.topLevelProperties(HTTP_SETTINGS, enclosingSchema)
val currentModel = standardDataClass(
ModelNameRegistry.getOrRegister(it.schema, enclosingSchema.toEnclosingSchemaInfo()),
it.name,
props,
it.schema.extensions,
oneOfInterfaces = emptySet(),
)
val inlinedModels = buildInLinedModels(props, enclosingSchema, apiDocUrl)
inlinedModels + currentModel
if (it.isInherited) {
emptySet() // Rely on the parent definition
} else {
val props = it.schema.topLevelProperties(HTTP_SETTINGS, enclosingSchema)
val currentModel = standardDataClass(
ModelNameRegistry.getOrRegister(it.schema, enclosingSchema.toEnclosingSchemaInfo()),
it.name,
props,
it.schema.extensions,
oneOfInterfaces = emptySet(),
)
val inlinedModels = buildInLinedModels(props, enclosingSchema, apiDocUrl)
inlinedModels + currentModel
}
}

is PropertyInfo.ObjectRefField -> emptySet() // Not an inlined definition, so do nothing
Expand All @@ -314,15 +318,18 @@ class JacksonModelGenerator(
}

is PropertyInfo.Field ->
if (it.typeInfo is KotlinTypeInfo.Enum) {
if (it.typeInfo is KotlinTypeInfo.Enum && !it.isInherited) {
setOf(buildEnumClass(it.typeInfo as KotlinTypeInfo.Enum))
} else {
emptySet()
}

is PropertyInfo.ListField ->
buildInlinedListDefinition(it.schema, it.name, enclosingSchema, apiDocUrl)

if (it.isInherited) {
emptySet() // Rely on the parent definition
} else {
buildInlinedListDefinition(it.schema, it.name, enclosingSchema, apiDocUrl)
}
is PropertyInfo.OneOfAny -> emptySet()
}
}
Expand Down Expand Up @@ -707,20 +714,20 @@ class JacksonModelGenerator(
): TypeSpec.Builder {
this.forEach {
it.addToClass(
schemaName,
toModelType(
schemaName = schemaName,
type = toModelType(
packages.base,
it.typeInfo,
it.isNullable(),
),
toClassName(
parameterizedType = toClassName(
packages.base,
it.typeInfo,
),
classBuilder,
constructorBuilder,
classType,
validationAnnotations,
classBuilder = classBuilder,
constructorBuilder = constructorBuilder,
classSettings = classType,
validationAnnotations = validationAnnotations,
)
}
if (constructorBuilder.parameters.isNotEmpty() && classBuilder.modifiers.isEmpty()) {
Expand Down
12 changes: 10 additions & 2 deletions src/main/kotlin/com/cjbooms/fabrikt/model/PropertyInfo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,11 @@ sealed class PropertyInfo {
val enclosingSchema: Schema?
) : PropertyInfo(), CollectionValidation {
override val typeInfo: KotlinTypeInfo =
KotlinTypeInfo.from(schema, oasKey, enclosingSchema?.toEnclosingSchemaInfo())
if (isInherited) {
KotlinTypeInfo.from(schema, oasKey, parentSchema.toEnclosingSchemaInfo())
} else {
KotlinTypeInfo.from(schema, oasKey, enclosingSchema?.toEnclosingSchemaInfo())
}
override val minItems: Int? = schema.minItems
override val maxItems: Int? = schema.maxItems
}
Expand Down Expand Up @@ -220,7 +224,11 @@ sealed class PropertyInfo {
val enclosingSchema: Schema?
) : PropertyInfo() {
override val typeInfo: KotlinTypeInfo =
KotlinTypeInfo.from(schema, oasKey, enclosingSchema?.toEnclosingSchemaInfo())
if (isInherited) {
KotlinTypeInfo.from(schema, oasKey, parentSchema.toEnclosingSchemaInfo())
} else {
KotlinTypeInfo.from(schema, oasKey, enclosingSchema?.toEnclosingSchemaInfo())
}
}

data class AdditionalProperties(
Expand Down
18 changes: 18 additions & 0 deletions src/test/resources/examples/enumPolymorphicDiscriminator/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,24 @@ components:
properties:
some_enum:
$ref: '#/components/schemas/ChildDiscriminator'
inline_obj:
type: object
properties:
str:
type: string
inline_array:
type: array
items:
type: object
properties:
str:
type: string
inline_enum:
type: string
enum:
- one
- two
- three

ChildDiscriminator:
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,43 @@ import kotlin.collections.Map
),
JsonSubTypes.Type(value = DiscriminatedChild3::class, name = "obj_three"),
)
public sealed class ChildDefinition() {
public sealed class ChildDefinition(
public open val inlineObj: ChildDefinitionInlineObj? = null,
public open val inlineArray: List<ChildDefinitionInlineArray>? = null,
public open val inlineEnum: ChildDefinitionInlineEnum? = null,
) {
public abstract val someEnum: ChildDiscriminator
}

public data class ChildDefinitionInlineArray(
@param:JsonProperty("str")
@get:JsonProperty("str")
public val str: String? = null,
)

public enum class ChildDefinitionInlineEnum(
@JsonValue
public val `value`: String,
) {
ONE("one"),
TWO("two"),
THREE("three"),
;

public companion object {
private val mapping: Map<String, ChildDefinitionInlineEnum> =
values().associateBy(ChildDefinitionInlineEnum::value)

public fun fromValue(`value`: String): ChildDefinitionInlineEnum? = mapping[value]
}
}

public data class ChildDefinitionInlineObj(
@param:JsonProperty("str")
@get:JsonProperty("str")
public val str: String? = null,
)

public enum class ChildDiscriminator(
@JsonValue
public val `value`: String,
Expand All @@ -57,30 +90,63 @@ public enum class ChildDiscriminator(
}

public data class DiscriminatedChild1(
@param:JsonProperty("inline_obj")
@get:JsonProperty("inline_obj")
@get:Valid
override val inlineObj: ChildDefinitionInlineObj? = null,
@param:JsonProperty("inline_array")
@get:JsonProperty("inline_array")
@get:Valid
override val inlineArray: List<ChildDefinitionInlineArray>? = null,
@param:JsonProperty("inline_enum")
@get:JsonProperty("inline_enum")
override val inlineEnum: ChildDefinitionInlineEnum? = null,
@param:JsonProperty("some_prop")
@get:JsonProperty("some_prop")
public val someProp: String? = null,
@get:JsonProperty("some_enum")
@get:NotNull
@param:JsonProperty("some_enum")
override val someEnum: ChildDiscriminator = ChildDiscriminator.OBJ_ONE_ONLY,
) : ChildDefinition()
) : ChildDefinition(inlineObj, inlineArray, inlineEnum)

public data class DiscriminatedChild2(
@get:JsonProperty("some_enum")
@get:NotNull
override val someEnum: ChildDiscriminator,
@param:JsonProperty("inline_obj")
@get:JsonProperty("inline_obj")
@get:Valid
override val inlineObj: ChildDefinitionInlineObj? = null,
@param:JsonProperty("inline_array")
@get:JsonProperty("inline_array")
@get:Valid
override val inlineArray: List<ChildDefinitionInlineArray>? = null,
@param:JsonProperty("inline_enum")
@get:JsonProperty("inline_enum")
override val inlineEnum: ChildDefinitionInlineEnum? = null,
@param:JsonProperty("some_prop")
@get:JsonProperty("some_prop")
public val someProp: String? = null,
) : ChildDefinition()
) : ChildDefinition(inlineObj, inlineArray, inlineEnum)

public data class DiscriminatedChild3(
@param:JsonProperty("inline_obj")
@get:JsonProperty("inline_obj")
@get:Valid
override val inlineObj: ChildDefinitionInlineObj? = null,
@param:JsonProperty("inline_array")
@get:JsonProperty("inline_array")
@get:Valid
override val inlineArray: List<ChildDefinitionInlineArray>? = null,
@param:JsonProperty("inline_enum")
@get:JsonProperty("inline_enum")
override val inlineEnum: ChildDefinitionInlineEnum? = null,
@get:JsonProperty("some_enum")
@get:NotNull
@param:JsonProperty("some_enum")
override val someEnum: ChildDiscriminator = ChildDiscriminator.OBJ_THREE,
) : ChildDefinition()
) : ChildDefinition(inlineObj, inlineArray, inlineEnum)

public data class Responses(
@param:JsonProperty("entries")
Expand Down

0 comments on commit 1222719

Please sign in to comment.