diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java index 09b03e1a1f95..b9b49e95caa6 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java @@ -859,6 +859,28 @@ public CodegenModel fromModel(String name, Schema schema) { .collect(Collectors.toMap(CodegenProperty::getBaseName, Function.identity())); allVarsMap.keySet() .removeAll(m.vars.stream().map(CodegenProperty::getBaseName).collect(Collectors.toSet())); + + // if there is a parent, find the redefined vars + if (m.parent != null && m.parentSchema != null) { + + // get the parent schema + Schema parentSchema = ModelUtils.getSchemas(this.openAPI).get(m.parentSchema); + + // if parent schema has properties, find the intersection + if (parentSchema != null && parentSchema.getProperties() != null) { + Set varNames = parentSchema.getProperties().keySet(); + + // compute intersection of m.allVars and parent properties, this will give us the overridden properties + Map overriddenProperties = m.allVars.stream() + .filter(p -> varNames.contains(p.getBaseName())) + .collect(Collectors.toMap(CodegenProperty::getBaseName, Function.identity())); + + // overridden properties contain the properties that are redefined in the child model. + // add them to allVarsMap so that they are marked as inherited. + allVarsMap.putAll(overriddenProperties); + } + } + // Update the allVars allVarsMap.values().forEach(p -> p.isInherited = true); // Update any other vars (requiredVars, optionalVars) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java index a01c5e7b910d..fb9b928296d0 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java @@ -574,6 +574,32 @@ private void givenSchemaObjectPropertyNameContainsDollarSignWhenGenerateThenDoll Assert.assertEquals(customKotlinParseListener.getStringReferenceCount(), 0); } + @Test(description = "add override on reference specialisation") + public void polymorphicReferenceOverrides() throws IOException { + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); +// File output = Paths.get("/Users/sylvain_maillard/workspaces/openapi-generator/modules/openapi-generator/target/test").toFile(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("kotlin") + .setInputSpec("src/test/resources/3_1/issue_22216.yaml") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + final ClientOptInput clientOptInput = configurator.toClientOptInput(); + DefaultGenerator generator = new DefaultGenerator(); + List files = generator.opts(clientOptInput).generate(); + + Assert.assertEquals(files.size(), 36); + + final Path carFile = Paths.get(output + "/src/main/kotlin/org/openapitools/client/models/Car.kt"); + final Path vehicleFile = Paths.get(output + "/src/main/kotlin/org/openapitools/client/models/Vehicle.kt"); + // file should contain override keyword for inherited properties ref + TestUtils.assertFileContains(carFile, "override val requiredProperty: kotlin.String,"); + TestUtils.assertFileContains(carFile, "override val optionalProperty: kotlin.String? = null"); + // file should not contain override keyword for own properties + TestUtils.assertFileNotContains(carFile, "override val color: kotlin.String? = null"); + } + @Test(description = "generate polymorphic kotlinx_serialization model") public void polymorphicKotlinxSerialization() throws IOException { File output = Files.createTempDirectory("test").toFile(); diff --git a/modules/openapi-generator/src/test/resources/3_1/issue_22216.yaml b/modules/openapi-generator/src/test/resources/3_1/issue_22216.yaml new file mode 100644 index 000000000000..ca58a092b0e4 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_1/issue_22216.yaml @@ -0,0 +1,40 @@ +openapi: 3.1.0 + +info: + title: Title + description: Title + version: 1.0.0 + +paths: + /example: + get: + responses: + "200": + description: "A successful response" + content: + application/json: + schema: + $ref: '#/components/schemas/Vehicle' + +components: + schemas: + Vehicle: + type: object + additionalProperties: false + discriminator: { propertyName: objectType } + required: [ objectType, requiredProperty ] + properties: + objectType: { type: string } + requiredProperty: { type: object } + optionalProperty: { type: object } + + Car: + allOf: + - $ref: '#/components/schemas/Vehicle' + - type: object + additionalProperties: false + required: [ objectType, requiredProperty ] + properties: + color: { type: string } + requiredProperty: { type: string } + optionalProperty: { type: string } \ No newline at end of file