diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/anyof_class.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/anyof_class.mustache index dfc48ab336b0..a8fe1d77cae2 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/anyof_class.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/anyof_class.mustache @@ -107,7 +107,7 @@ import java.io.IOException {{#anyOf}} {{^vendorExtensions.x-duplicated-data-type}} @JvmInline - {{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}value class {{#fnToValueClassName}}{{{dataType}}}{{/fnToValueClassName}}(val value: {{{dataType}}}) : {{classname}} + {{#explicitApi}}public {{/explicitApi}}value class {{#fnToValueClassName}}{{{dataType}}}{{/fnToValueClassName}}({{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}val value: {{{dataType}}}) : {{classname}} {{/vendorExtensions.x-duplicated-data-type}} {{/anyOf}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/oneof_class.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/oneof_class.mustache index 80b3baa97f60..73ee7570ec86 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/oneof_class.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/oneof_class.mustache @@ -169,7 +169,7 @@ import java.io.IOException {{#oneOf}} {{^vendorExtensions.x-duplicated-data-type}} @JvmInline - {{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}value class {{#fnToValueClassName}}{{{dataType}}}{{/fnToValueClassName}}(val value: {{{dataType}}}) : {{classname}} + {{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}value class {{#fnToValueClassName}}{{{dataType}}}{{/fnToValueClassName}}({{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}val value: {{{dataType}}}) : {{classname}} {{/vendorExtensions.x-duplicated-data-type}} {{/oneOf}} 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 23f98e3c443e..e86ce4e069ac 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 @@ -685,6 +685,57 @@ public void anyOfPrimitiveKotlinxSerialization() throws IOException { TestUtils.assertFileContains(parentModelKt, "val id: ObjectWithComplexAnyOfId?"); } + @Test(description = "generate oneOf/anyOf wrappers with explicit API mode using kotlinx_serialization") + public void oneOfAnyOfKotlinxSerializationExplicitApi() throws IOException { + File output = generateKotlinxOneOfAnyOf(new HashMap<>() {{ put(KotlinClientCodegen.EXPLICIT_API, true); }}); + // value class nested inside sealed interface: public is valid, internal is not + TestUtils.assertFileContains(modelPath(output, "ObjectWithComplexOneOfId"), + "public value class StringValue(public val value: kotlin.String) : ObjectWithComplexOneOfId"); + TestUtils.assertFileContains(modelPath(output, "ObjectWithComplexAnyOfId"), + "public value class StringValue(public val value: kotlin.String) : ObjectWithComplexAnyOfId"); + } + + @Test(description = "generate oneOf/anyOf wrappers with non-public API mode using kotlinx_serialization") + public void oneOfAnyOfKotlinxSerializationNonPublicApi() throws IOException { + File output = generateKotlinxOneOfAnyOf(new HashMap<>() {{ put(CodegenConstants.NON_PUBLIC_API, true); }}); + // Kotlin doesn't allow internal subclasses of internal interfaces, make sure subclasses are generated correctly + TestUtils.assertFileContains(modelPath(output, "ObjectWithComplexOneOfId"), + "internal sealed interface ObjectWithComplexOneOfId"); + TestUtils.assertFileNotContains(modelPath(output, "ObjectWithComplexOneOfId"), + "internal value class StringValue"); + TestUtils.assertFileContains(modelPath(output, "ObjectWithComplexOneOfId"), + "value class StringValue(internal val value: kotlin.String) : ObjectWithComplexOneOfId"); + TestUtils.assertFileContains(modelPath(output, "ObjectWithComplexAnyOfId"), + "internal sealed interface ObjectWithComplexAnyOfId"); + TestUtils.assertFileNotContains(modelPath(output, "ObjectWithComplexAnyOfId"), + "internal value class StringValue"); + TestUtils.assertFileContains(modelPath(output, "ObjectWithComplexAnyOfId"), + "value class StringValue(internal val value: kotlin.String) : ObjectWithComplexAnyOfId"); + } + + private File generateKotlinxOneOfAnyOf(Map extraProps) throws IOException { + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + Map props = new HashMap<>(); + props.put(CodegenConstants.SERIALIZATION_LIBRARY, "kotlinx_serialization"); + props.put(GENERATE_ONEOF_ANYOF_WRAPPERS, true); + props.putAll(extraProps); + new DefaultGenerator() + .opts(new CodegenConfigurator() + .setGeneratorName("kotlin") + .setLibrary("jvm-retrofit2") + .setAdditionalProperties(props) + .setInputSpec("src/test/resources/3_0/issue_19942.json") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")) + .toClientOptInput()) + .generate(); + return output; + } + + private static Path modelPath(File output, String modelName) { + return Paths.get(output + "/src/main/kotlin/org/openapitools/client/models/" + modelName + ".kt"); + } + @Test(description = "generate polymorphic jackson model") public void polymorphicJacksonSerialization() throws IOException { File output = Files.createTempDirectory("test").toFile();