From 38185d8558c45b52fbe076c444c341fcb95304eb Mon Sep 17 00:00:00 2001 From: Matt Traynham Date: Sun, 5 Jan 2020 10:10:03 -0500 Subject: [PATCH] [Kotlin] Correct isInherited flag for Kotlin generators (#4254) * Correct isInherited flag for Kotlin generators * Update Kotlin Client inheritance test to check variables --- .../languages/AbstractKotlinCodegen.java | 19 ++++++- .../languages/KotlinSpringServerCodegen.java | 12 ---- .../kotlin/AbstractKotlinCodegenTest.java | 56 ++++++++++++++++++- 3 files changed, 73 insertions(+), 14 deletions(-) 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 9c8eb435e56..9c6610a3506 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 @@ -33,7 +33,9 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.openapitools.codegen.utils.StringUtils.*; @@ -771,7 +773,22 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co public CodegenModel fromModel(String name, Schema schema) { CodegenModel m = super.fromModel(name, schema); m.optionalVars = m.optionalVars.stream().distinct().collect(Collectors.toList()); - m.allVars.stream().filter(p -> !m.vars.contains(p)).forEach(p -> p.isInherited = true); + // Update allVars/requiredVars/optionalVars with isInherited + // Each of these lists contains elements that are similar, but they are all cloned + // via CodegenModel.removeAllDuplicatedProperty and therefore need to be updated + // separately. + // First find only the parent vars via baseName matching + Map allVarsMap = m.allVars.stream() + .collect(Collectors.toMap(CodegenProperty::getBaseName, Function.identity())); + allVarsMap.keySet() + .removeAll(m.vars.stream().map(CodegenProperty::getBaseName).collect(Collectors.toSet())); + // Update the allVars + allVarsMap.values().forEach(p -> p.isInherited = true); + // Update any other vars (requiredVars, optionalVars) + Stream.of(m.requiredVars, m.optionalVars) + .flatMap(List::stream) + .filter(p -> allVarsMap.containsKey(p.baseName)) + .forEach(p -> p.isInherited = true); return m; } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java index fa884f1bd23..f5ca516d504 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java @@ -617,18 +617,6 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen } } - // Can't figure out the logic in DefaultCodegen but optional vars are getting duplicated when there's - // inheritance involved. Also, isInherited doesn't seem to be getting set properly ¯\_(ツ)_/¯ - @Override - public CodegenModel fromModel(String name, Schema schema) { - CodegenModel m = super.fromModel(name, schema); - - m.optionalVars = m.optionalVars.stream().distinct().collect(Collectors.toList()); - m.allVars.stream().filter(p -> !m.vars.contains(p)).forEach(p -> p.isInherited = true); - - return m; - } - /** * Output the proper model name (capitalized). * In case the name belongs to the TypeSystem it won't be renamed. diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/AbstractKotlinCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/AbstractKotlinCodegenTest.java index 90c8acff528..453409dc3af 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/AbstractKotlinCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/AbstractKotlinCodegenTest.java @@ -1,12 +1,25 @@ package org.openapitools.codegen.kotlin; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.ComposedSchema; +import io.swagger.v3.oas.models.media.ObjectSchema; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.media.StringSchema; import org.openapitools.codegen.CodegenConstants; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenProperty; import org.openapitools.codegen.CodegenType; +import org.openapitools.codegen.DefaultCodegen; +import org.openapitools.codegen.TestUtils; import org.openapitools.codegen.languages.AbstractKotlinCodegen; import org.testng.Assert; import org.testng.annotations.Test; import java.io.File; +import java.util.HashSet; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; import static org.openapitools.codegen.CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.*; import static org.testng.Assert.*; @@ -197,4 +210,45 @@ public class AbstractKotlinCodegenTest { codegen.processOpts(); Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL)); } -} \ No newline at end of file + + @Test + public void handleInheritance() { + Schema parent = new ObjectSchema() + .addProperties("a", new StringSchema()) + .addProperties("b", new StringSchema()) + .addRequiredItem("a") + .name("Parent"); + Schema child = new ComposedSchema() + .addAllOfItem(new Schema().$ref("Parent")) + .addAllOfItem(new ObjectSchema() + .addProperties("c", new StringSchema()) + .addProperties("d", new StringSchema()) + .addRequiredItem("c")) + .name("Child"); + OpenAPI openAPI = TestUtils.createOpenAPI(); + openAPI.getComponents().addSchemas(parent.getName(), parent); + openAPI.getComponents().addSchemas(child.getName(), child); + + final DefaultCodegen codegen = new P_AbstractKotlinCodegen(); + codegen.setOpenAPI(openAPI); + + final CodegenModel pm = codegen + .fromModel("Child", child); + Map allVarsMap = pm.allVars.stream() + .collect(Collectors.toMap(CodegenProperty::getBaseName, Function.identity())); + for (CodegenProperty p : pm.requiredVars) { + Assert.assertEquals(allVarsMap.get(p.baseName).isInherited, p.isInherited); + } + Assert.assertEqualsNoOrder( + pm.requiredVars.stream().map(CodegenProperty::getBaseName).toArray(), + new String[] {"a", "c"} + ); + for (CodegenProperty p : pm.optionalVars) { + Assert.assertEquals(allVarsMap.get(p.baseName).isInherited, p.isInherited); + } + Assert.assertEqualsNoOrder( + pm.optionalVars.stream().map(CodegenProperty::getBaseName).toArray(), + new String[] {"b", "d"} + ); + } +}