Repository: cjbooms/fabrikt
Pull request #152 (2022-11-08 17:01:11)

Move additional properties map to data class constructor.
This will ensure that additional properties are taken into account with equality check. Previously data classes containing different additional properties were being reported as equal if all constructor parameters matched

cjbooms: 👍 

Patch:
diff --git a/src/main/kotlin/com/cjbooms/fabrikt/generators/PropertyUtils.kt b/src/main/kotlin/com/cjbooms/fabrikt/generators/PropertyUtils.kt
index a4633b7..bee390c 100644
--- a/src/main/kotlin/com/cjbooms/fabrikt/generators/PropertyUtils.kt
+++ b/src/main/kotlin/com/cjbooms/fabrikt/generators/PropertyUtils.kt
@@ -32,8 +32,12 @@ object PropertyUtils {
         val property = PropertySpec.builder(name, type)
 
         if (this is PropertyInfo.AdditionalProperties) {
-            property.initializer("mutableMapOf()")
+            property.initializer(name)
             property.addAnnotation(JacksonMetadata.ignore)
+            val constructorParameter: ParameterSpec.Builder = ParameterSpec.builder(name, type)
+            constructorParameter.defaultValue("mutableMapOf()")
+            constructorBuilder.addParameter(constructorParameter.build())
+
             val value =
                 if (typeInfo is KotlinTypeInfo.MapTypeAdditionalProperties) {
                     Map::class.asTypeName().parameterizedBy(String::class.asTypeName(), parameterizedType)
@@ -59,14 +63,17 @@ object PropertyUtils {
                     if (this is PropertyInfo.Field && isPolymorphicDiscriminator) property.addModifiers(KModifier.ABSTRACT)
                     else property.addModifiers(KModifier.OPEN)
                 }
+
                 ClassType.SUB_MODEL -> {
                     if (this is PropertyInfo.Field && isPolymorphicDiscriminator) {
                         property.addModifiers(KModifier.OVERRIDE)
                         when (maybeDiscriminator) {
                             is PropertyInfo.DiscriminatorKey.EnumKey ->
                                 property.initializer("%T.%L", type, maybeDiscriminator.enumKey)
+
                             is PropertyInfo.DiscriminatorKey.StringKey ->
                                 property.initializer("%S", maybeDiscriminator.stringValue)
+
                             else -> {
                                 property.addAnnotation(JacksonMetadata.jacksonParameterAnnotation(oasKey))
                             }
@@ -81,6 +88,7 @@ object PropertyUtils {
                     property.addAnnotation(JacksonMetadata.jacksonPropertyAnnotation(oasKey))
                     property.addValidationAnnotations(this)
                 }
+
                 ClassType.VANILLA_MODEL -> {
                     property.addAnnotation(JacksonMetadata.jacksonParameterAnnotation(oasKey))
                     property.addAnnotation(JacksonMetadata.jacksonPropertyAnnotation(oasKey))
@@ -88,9 +96,9 @@ object PropertyUtils {
                 }
             }
 
-            if (this !is PropertyInfo.Field || !isPolymorphicDiscriminator || isSubTypeDiscriminatorWithNoValue(
-                    classType
-                )
+            if (this !is PropertyInfo.Field ||
+                !isPolymorphicDiscriminator ||
+                isSubTypeDiscriminatorWithNoValue(classType)
             ) {
                 property.initializer(name)
                 val constructorParameter: ParameterSpec.Builder = ParameterSpec.builder(name, type)
@@ -112,6 +120,7 @@ object PropertyUtils {
                 val className = parameterizedType as? ClassName
                 OasDefault.from(propTypeInfo.typeInfo, className, it)
             }
+
             else -> null
         }
     }
@@ -164,6 +173,7 @@ object PropertyUtils {
                     )
                 }
             }
+
             is PropertyInfo.CollectionValidation -> {
                 // Size Restrictions for collections
                 val (minCollLen, maxCollLen) = Pair(info.minItems, info.maxItems)
@@ -182,11 +192,13 @@ object PropertyUtils {
                     addAnnotation(fieldValid())
                 }
             }
+
             is KotlinTypeInfo.Array -> {
                 if (typeInfo.parameterizedType.isComplexType) {
                     addAnnotation(fieldValid())
                 }
             }
+
             else -> {
                 if (typeInfo.isComplexType) {
                     addAnnotation(fieldValid())


Test patch:
diff --git a/src/test/resources/examples/anyOfOneOfAllOf/models/Models.kt b/src/test/resources/examples/anyOfOneOfAllOf/models/Models.kt
index 03dcb51..2c8e640 100644
--- a/src/test/resources/examples/anyOfOneOfAllOf/models/Models.kt
+++ b/src/test/resources/examples/anyOfOneOfAllOf/models/Models.kt
@@ -80,11 +80,10 @@ data class MoreNesting(
 data class OneOfAdditionalProps(
     @param:JsonProperty("second_nested_any_of_prop")
     @get:JsonProperty("second_nested_any_of_prop")
-    val secondNestedAnyOfProp: String? = null
-) {
+    val secondNestedAnyOfProp: String? = null,
     @get:JsonIgnore
     val properties: MutableMap<String, Any> = mutableMapOf()
-
+) {
     @JsonAnyGetter
     fun get(): Map<String, Any> = properties
 
diff --git a/src/test/resources/examples/externalReferences/models/Models.kt b/src/test/resources/examples/externalReferences/models/Models.kt
index d47863d..2d7c44d 100644
--- a/src/test/resources/examples/externalReferences/models/Models.kt
+++ b/src/test/resources/examples/externalReferences/models/Models.kt
@@ -71,11 +71,10 @@ data class ExternalObjectTwo(
     @param:JsonProperty("list-others")
     @get:JsonProperty("list-others")
     @get:Valid
-    val listOthers: List<ExternalObjectThree>? = null
-) {
+    val listOthers: List<ExternalObjectThree>? = null,
     @get:JsonIgnore
     val properties: MutableMap<String, Map<String, ExternalObjectFour>> = mutableMapOf()
-
+) {
     @JsonAnyGetter
     fun get(): Map<String, Map<String, ExternalObjectFour>> = properties
 
diff --git a/src/test/resources/examples/githubApi/models/Models.kt b/src/test/resources/examples/githubApi/models/Models.kt
index 995d8b0..df43bde 100644
--- a/src/test/resources/examples/githubApi/models/Models.kt
+++ b/src/test/resources/examples/githubApi/models/Models.kt
@@ -30,11 +30,10 @@ data class BulkEntityDetails(
     @get:JsonProperty("entities")
     @get:NotNull
     @get:Valid
-    val entities: List<EntityDetails>
-) {
+    val entities: List<EntityDetails>,
     @get:JsonIgnore
     val properties: MutableMap<String, Any> = mutableMapOf()
-
+) {
     @JsonAnyGetter
     fun get(): Map<String, Any> = properties
 
@@ -120,11 +119,10 @@ data class EntityDetails(
     @param:JsonProperty("id")
     @get:JsonProperty("id")
     @get:NotNull
-    val id: String
-) {
+    val id: String,
     @get:JsonIgnore
     val properties: MutableMap<String, Any> = mutableMapOf()
-
+) {
     @JsonAnyGetter
     fun get(): Map<String, Any> = properties
 
@@ -142,11 +140,10 @@ data class Event(
     @param:JsonProperty("data")
     @get:JsonProperty("data")
     @get:NotNull
-    val data: Map<String, Any>
-) {
+    val data: Map<String, Any>,
     @get:JsonIgnore
     val properties: MutableMap<String, Any> = mutableMapOf()
-
+) {
     @JsonAnyGetter
     fun get(): Map<String, Any> = properties
 
@@ -162,11 +159,10 @@ data class EventResults(
     @get:NotNull
     @get:Size(min = 0)
     @get:Valid
-    val changeEvents: List<Event>
-) {
+    val changeEvents: List<Event>,
     @get:JsonIgnore
     val properties: MutableMap<String, Any> = mutableMapOf()
-
+) {
     @JsonAnyGetter
     fun get(): Map<String, Any> = properties
 
diff --git a/src/test/resources/examples/mapExamples/models/Models.kt b/src/test/resources/examples/mapExamples/models/Models.kt
index cc19120..a73018c 100644
--- a/src/test/resources/examples/mapExamples/models/Models.kt
+++ b/src/test/resources/examples/mapExamples/models/Models.kt
@@ -35,11 +35,10 @@ data class ComplexObjectWithRefTypedMap(
     val text: String? = null,
     @param:JsonProperty("code")
     @get:JsonProperty("code")
-    val code: Int? = null
-) {
+    val code: Int? = null,
     @get:JsonIgnore
     val properties: MutableMap<String, SomeRef> = mutableMapOf()
-
+) {
     @JsonAnyGetter
     fun get(): Map<String, SomeRef> = properties
 
@@ -55,11 +54,10 @@ data class ComplexObjectWithTypedMap(
     val text: String? = null,
     @param:JsonProperty("code")
     @get:JsonProperty("code")
-    val code: Int? = null
-) {
+    val code: Int? = null,
     @get:JsonIgnore
     val properties: MutableMap<String, ComplexObjectWithTypedMapValue> = mutableMapOf()
-
+) {
     @JsonAnyGetter
     fun get(): Map<String, ComplexObjectWithTypedMapValue> = properties
 
@@ -84,11 +82,10 @@ data class ComplexObjectWithUntypedMap(
     val text: String? = null,
     @param:JsonProperty("code")
     @get:JsonProperty("code")
-    val code: Int? = null
-) {
+    val code: Int? = null,
     @get:JsonIgnore
     val properties: MutableMap<String, Any> = mutableMapOf()
-
+) {
     @JsonAnyGetter
     fun get(): Map<String, Any> = properties
 
@@ -164,11 +161,10 @@ data class MapHolder(
     @param:JsonProperty("inlined_complex_object_with_typed_map")
     @get:JsonProperty("inlined_complex_object_with_typed_map")
     @get:Valid
-    val inlinedComplexObjectWithTypedMap: MapHolderInlinedComplexObjectWithTypedMap? = null
-) {
+    val inlinedComplexObjectWithTypedMap: MapHolderInlinedComplexObjectWithTypedMap? = null,
     @get:JsonIgnore
     val properties: MutableMap<String, Map<String, ExternalObjectFour>> = mutableMapOf()
-
+) {
     @JsonAnyGetter
     fun get(): Map<String, Map<String, ExternalObjectFour>> = properties
 
@@ -184,11 +180,10 @@ data class MapHolderInlinedComplexObjectWithTypedMap(
     val text: String? = null,
     @param:JsonProperty("code")
     @get:JsonProperty("code")
-    val code: Int? = null
-) {
+    val code: Int? = null,
     @get:JsonIgnore
     val properties: MutableMap<String, InlinedComplexObjectWithTypedMapValue> = mutableMapOf()
-
+) {
     @JsonAnyGetter
     fun get(): Map<String, InlinedComplexObjectWithTypedMapValue> = properties
 
@@ -204,11 +199,10 @@ data class MapHolderInlinedComplexObjectWithUntypedMap(
     val text: String? = null,
     @param:JsonProperty("code")
     @get:JsonProperty("code")
-    val code: Int? = null
-) {
+    val code: Int? = null,
     @get:JsonIgnore
     val properties: MutableMap<String, Any> = mutableMapOf()
-
+) {
     @JsonAnyGetter
     fun get(): Map<String, Any> = properties