Skip to content

Commit 117c5e8

Browse files
authored
[Kotlin] Fix explicitApi/nonPublicApi/generateOneOfAnyOfWrappers generation for kotlinx_serialization (#23796)
* Fix explicitApi & nonPublicApi generation for kotlinx_serialization * Add missing explicitApi templates
1 parent f085d85 commit 117c5e8

5 files changed

Lines changed: 58 additions & 7 deletions

File tree

modules/openapi-generator/src/main/resources/kotlin-client/anyof_class.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ import java.io.IOException
107107
{{#anyOf}}
108108
{{^vendorExtensions.x-duplicated-data-type}}
109109
@JvmInline
110-
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}value class {{#fnToValueClassName}}{{{dataType}}}{{/fnToValueClassName}}(val value: {{{dataType}}}) : {{classname}}
110+
{{#explicitApi}}public {{/explicitApi}}value class {{#fnToValueClassName}}{{{dataType}}}{{/fnToValueClassName}}({{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}val value: {{{dataType}}}) : {{classname}}
111111

112112
{{/vendorExtensions.x-duplicated-data-type}}
113113
{{/anyOf}}

modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigDecimalAdapter.kt.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import java.math.BigDecimal
1818
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}object BigDecimalAdapter : KSerializer<BigDecimal> {
1919
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigDecimal", PrimitiveKind.STRING)
2020
override fun deserialize(decoder: Decoder): BigDecimal = BigDecimal(decoder.decodeString())
21-
override fun serialize(encoder: Encoder, value: BigDecimal) = encoder.encodeString(value.toPlainString())
21+
override fun serialize(encoder: Encoder, value: BigDecimal){{#explicitApi}}: Unit{{/explicitApi}} = encoder.encodeString(value.toPlainString())
2222
}
2323
{{/kotlinx_serialization}}
2424
{{#moshi}}

modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/Serializer.kt.mustache

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ import java.util.concurrent.atomic.AtomicLong
134134
private var isAdaptersInitialized = false
135135

136136
@JvmStatic
137-
val kotlinxSerializationAdapters: SerializersModule by lazy {
137+
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}val kotlinxSerializationAdapters: SerializersModule by lazy {
138138
isAdaptersInitialized = true
139139
SerializersModule {
140140
contextual(BigDecimal::class, BigDecimalAdapter)
@@ -156,7 +156,7 @@ import java.util.concurrent.atomic.AtomicLong
156156
}
157157
}
158158

159-
var kotlinxSerializationAdaptersConfiguration: SerializersModuleBuilder.() -> Unit = {}
159+
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}var kotlinxSerializationAdaptersConfiguration: SerializersModuleBuilder.() -> Unit = {}
160160
set(value) {
161161
check(!isAdaptersInitialized) {
162162
"Cannot configure kotlinxSerializationAdaptersConfiguration after kotlinxSerializationAdapters has been initialized."
@@ -167,7 +167,7 @@ import java.util.concurrent.atomic.AtomicLong
167167
private var isJsonInitialized = false
168168

169169
@JvmStatic
170-
val kotlinxSerializationJson: Json by lazy {
170+
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}val kotlinxSerializationJson: Json by lazy {
171171
isJsonInitialized = true
172172
Json {
173173
serializersModule = kotlinxSerializationAdapters
@@ -179,7 +179,7 @@ import java.util.concurrent.atomic.AtomicLong
179179
}
180180
}
181181

182-
var kotlinxSerializationJsonConfiguration: JsonBuilder.() -> Unit = {}
182+
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}var kotlinxSerializationJsonConfiguration: JsonBuilder.() -> Unit = {}
183183
set(value) {
184184
check(!isJsonInitialized) {
185185
"Cannot configure kotlinxSerializationJsonConfiguration after kotlinxSerializationJson has been initialized."

modules/openapi-generator/src/main/resources/kotlin-client/oneof_class.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ import java.io.IOException
169169
{{#oneOf}}
170170
{{^vendorExtensions.x-duplicated-data-type}}
171171
@JvmInline
172-
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}value class {{#fnToValueClassName}}{{{dataType}}}{{/fnToValueClassName}}(val value: {{{dataType}}}) : {{classname}}
172+
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}value class {{#fnToValueClassName}}{{{dataType}}}{{/fnToValueClassName}}({{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}val value: {{{dataType}}}) : {{classname}}
173173

174174
{{/vendorExtensions.x-duplicated-data-type}}
175175
{{/oneOf}}

modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,57 @@ public void anyOfPrimitiveKotlinxSerialization() throws IOException {
685685
TestUtils.assertFileContains(parentModelKt, "val id: ObjectWithComplexAnyOfId?");
686686
}
687687

688+
@Test(description = "generate oneOf/anyOf wrappers with explicit API mode using kotlinx_serialization")
689+
public void oneOfAnyOfKotlinxSerializationExplicitApi() throws IOException {
690+
File output = generateKotlinxOneOfAnyOf(new HashMap<>() {{ put(KotlinClientCodegen.EXPLICIT_API, true); }});
691+
// value class nested inside sealed interface: public is valid, internal is not
692+
TestUtils.assertFileContains(modelPath(output, "ObjectWithComplexOneOfId"),
693+
"public value class StringValue(public val value: kotlin.String) : ObjectWithComplexOneOfId");
694+
TestUtils.assertFileContains(modelPath(output, "ObjectWithComplexAnyOfId"),
695+
"public value class StringValue(public val value: kotlin.String) : ObjectWithComplexAnyOfId");
696+
}
697+
698+
@Test(description = "generate oneOf/anyOf wrappers with non-public API mode using kotlinx_serialization")
699+
public void oneOfAnyOfKotlinxSerializationNonPublicApi() throws IOException {
700+
File output = generateKotlinxOneOfAnyOf(new HashMap<>() {{ put(CodegenConstants.NON_PUBLIC_API, true); }});
701+
// Kotlin doesn't allow internal subclasses of internal interfaces, make sure subclasses are generated correctly
702+
TestUtils.assertFileContains(modelPath(output, "ObjectWithComplexOneOfId"),
703+
"internal sealed interface ObjectWithComplexOneOfId");
704+
TestUtils.assertFileNotContains(modelPath(output, "ObjectWithComplexOneOfId"),
705+
"internal value class StringValue");
706+
TestUtils.assertFileContains(modelPath(output, "ObjectWithComplexOneOfId"),
707+
"value class StringValue(internal val value: kotlin.String) : ObjectWithComplexOneOfId");
708+
TestUtils.assertFileContains(modelPath(output, "ObjectWithComplexAnyOfId"),
709+
"internal sealed interface ObjectWithComplexAnyOfId");
710+
TestUtils.assertFileNotContains(modelPath(output, "ObjectWithComplexAnyOfId"),
711+
"internal value class StringValue");
712+
TestUtils.assertFileContains(modelPath(output, "ObjectWithComplexAnyOfId"),
713+
"value class StringValue(internal val value: kotlin.String) : ObjectWithComplexAnyOfId");
714+
}
715+
716+
private File generateKotlinxOneOfAnyOf(Map<String, Object> extraProps) throws IOException {
717+
File output = Files.createTempDirectory("test").toFile();
718+
output.deleteOnExit();
719+
Map<String, Object> props = new HashMap<>();
720+
props.put(CodegenConstants.SERIALIZATION_LIBRARY, "kotlinx_serialization");
721+
props.put(GENERATE_ONEOF_ANYOF_WRAPPERS, true);
722+
props.putAll(extraProps);
723+
new DefaultGenerator()
724+
.opts(new CodegenConfigurator()
725+
.setGeneratorName("kotlin")
726+
.setLibrary("jvm-retrofit2")
727+
.setAdditionalProperties(props)
728+
.setInputSpec("src/test/resources/3_0/issue_19942.json")
729+
.setOutputDir(output.getAbsolutePath().replace("\\", "/"))
730+
.toClientOptInput())
731+
.generate();
732+
return output;
733+
}
734+
735+
private static Path modelPath(File output, String modelName) {
736+
return Paths.get(output + "/src/main/kotlin/org/openapitools/client/models/" + modelName + ".kt");
737+
}
738+
688739
@Test(description = "generate polymorphic jackson model")
689740
public void polymorphicJacksonSerialization() throws IOException {
690741
File output = Files.createTempDirectory("test").toFile();

0 commit comments

Comments
 (0)