Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}

becomes

{{#explicitApi}}public {{/explicitApi}}

because if nonPublicApi is true, this is an internal interface, which can never have an internal subclass. This subclass is thus effectively always public

{{#explicitApi}}public {{/explicitApi}}value class {{#fnToValueClassName}}{{{dataType}}}{{/fnToValueClassName}}({{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}val value: {{{dataType}}}) : {{classname}}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second change is

val value

becoming

{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}val value

Adding the missing public in explicit API mode, and adding the missing internal in non-public mode


{{/vendorExtensions.x-duplicated-data-type}}
{{/anyOf}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, Object> extraProps) throws IOException {
File output = Files.createTempDirectory("test").toFile();
output.deleteOnExit();
Map<String, Object> 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();
Expand Down
Loading