[REQ] resolve #17544 Add x-field-extra-annotation and x-class-extra-annotation for kotlin generator (#19899)

Co-authored-by: Aliaksandr SEMIANKEVICH <aliaksandrsemian.epam@navan.tech>
This commit is contained in:
Aliaksandr SEMIANKEVICH 2024-10-22 12:05:38 +02:00 committed by GitHub
parent 071540f55a
commit e9c3c63732
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 84 additions and 38 deletions

View File

@ -51,6 +51,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useSettingsGradle|Whether the project uses settings.gradle.| |false| |useSettingsGradle|Whether the project uses settings.gradle.| |false|
|useSpringBoot3|Whether to use the Spring Boot 3 with the jvm-spring-webclient library.| |false| |useSpringBoot3|Whether to use the Spring Boot 3 with the jvm-spring-webclient library.| |false|
## SUPPORTED VENDOR EXTENSIONS
| Extension name | Description | Applicable for | Default value |
| -------------- | ----------- | -------------- | ------------- |
|x-class-extra-annotation|List of custom annotations to be added to model|MODEL|null
|x-field-extra-annotation|List of custom annotations to be added to property|FIELD, OPERATION_PARAMETER|null
## IMPORT MAPPING ## IMPORT MAPPING
| Type/Alias | Imports | | Type/Alias | Imports |

View File

@ -38,6 +38,7 @@ import org.openapitools.codegen.CodegenParameter;
import org.openapitools.codegen.CodegenProperty; import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.CodegenType; import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.SupportingFile; import org.openapitools.codegen.SupportingFile;
import org.openapitools.codegen.VendorExtension;
import org.openapitools.codegen.meta.features.ClientModificationFeature; import org.openapitools.codegen.meta.features.ClientModificationFeature;
import org.openapitools.codegen.meta.features.DocumentationFeature; import org.openapitools.codegen.meta.features.DocumentationFeature;
import org.openapitools.codegen.meta.features.GlobalFeature; import org.openapitools.codegen.meta.features.GlobalFeature;
@ -1049,4 +1050,12 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
System.out.println("# Please support his work directly via https://patreon.com/jimschubert \uD83D\uDE4F #"); System.out.println("# Please support his work directly via https://patreon.com/jimschubert \uD83D\uDE4F #");
System.out.println("################################################################################"); System.out.println("################################################################################");
} }
@Override
public List<VendorExtension> getSupportedVendorExtensions() {
var extensions = super.getSupportedVendorExtensions();
extensions.add(VendorExtension.X_CLASS_EXTRA_ANNOTATION);
extensions.add(VendorExtension.X_FIELD_EXTRA_ANNOTATION);
return extensions;
}
} }

View File

@ -74,6 +74,9 @@ import {{packageName}}.infrastructure.ITransformForStorage
@Deprecated(message = "This schema is deprecated.") @Deprecated(message = "This schema is deprecated.")
{{/isDeprecated}} {{/isDeprecated}}
{{>additionalModelTypeAnnotations}} {{>additionalModelTypeAnnotations}}
{{#vendorExtensions.x-class-extra-annotation}}
{{{vendorExtensions.x-class-extra-annotation}}}
{{/vendorExtensions.x-class-extra-annotation}}
{{#nonPublicApi}}internal {{/nonPublicApi}}{{#discriminator}}interface{{/discriminator}}{{^discriminator}}{{#hasVars}}data {{/hasVars}}class{{/discriminator}} {{classname}}{{^discriminator}} ( {{#nonPublicApi}}internal {{/nonPublicApi}}{{#discriminator}}interface{{/discriminator}}{{^discriminator}}{{#hasVars}}data {{/hasVars}}class{{/discriminator}} {{classname}}{{^discriminator}} (
{{#allVars}} {{#allVars}}

View File

@ -15,6 +15,9 @@
{{^isEnum}}{{^isArray}}{{^isPrimitiveType}}{{^isModel}}@Contextual {{/isModel}}{{/isPrimitiveType}}{{/isArray}}{{/isEnum}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") {{^isEnum}}{{^isArray}}{{^isPrimitiveType}}{{^isModel}}@Contextual {{/isModel}}{{/isPrimitiveType}}{{/isArray}}{{/isEnum}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}")
{{/kotlinx_serialization}} {{/kotlinx_serialization}}
{{/multiplatform}} {{/multiplatform}}
{{#vendorExtensions.x-field-extra-annotation}}
{{{vendorExtensions.x-field-extra-annotation}}}
{{/vendorExtensions.x-field-extra-annotation}}
{{#deprecated}} {{#deprecated}}
@Deprecated(message = "This property is deprecated.") @Deprecated(message = "This property is deprecated.")
{{/deprecated}} {{/deprecated}}

View File

@ -15,6 +15,9 @@
{{^isEnum}}{{^isArray}}{{^isPrimitiveType}}{{^isModel}}@Contextual {{/isModel}}{{/isPrimitiveType}}{{/isArray}}{{/isEnum}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") {{^isEnum}}{{^isArray}}{{^isPrimitiveType}}{{^isModel}}@Contextual {{/isModel}}{{/isPrimitiveType}}{{/isArray}}{{/isEnum}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}")
{{/kotlinx_serialization}} {{/kotlinx_serialization}}
{{/multiplatform}} {{/multiplatform}}
{{#vendorExtensions.x-field-extra-annotation}}
{{{vendorExtensions.x-field-extra-annotation}}}
{{/vendorExtensions.x-field-extra-annotation}}
{{#deprecated}} {{#deprecated}}
@Deprecated(message = "This property is deprecated.") @Deprecated(message = "This property is deprecated.")
{{/deprecated}} {{/deprecated}}

View File

@ -50,7 +50,7 @@ import java.util.Map;
@SuppressWarnings("static-method") @SuppressWarnings("static-method")
public class KotlinClientCodegenModelTest { public class KotlinClientCodegenModelTest {
private Schema getArrayTestSchema() { private Schema<?> getArrayTestSchema() {
return new ObjectSchema() return new ObjectSchema()
.description("a sample model") .description("a sample model")
.addProperties("id", new IntegerSchema().format("int64")) .addProperties("id", new IntegerSchema().format("int64"))
@ -58,7 +58,7 @@ public class KotlinClientCodegenModelTest {
.addRequiredItem("id"); .addRequiredItem("id");
} }
private Schema getSimpleSchema() { private Schema<?> getSimpleSchema() {
return new ObjectSchema() return new ObjectSchema()
.description("a sample model") .description("a sample model")
.addProperties("id", new IntegerSchema().format("int64")) .addProperties("id", new IntegerSchema().format("int64"))
@ -68,14 +68,14 @@ public class KotlinClientCodegenModelTest {
.addRequiredItem("name"); .addRequiredItem("name");
} }
private Schema getMapSchema() { private Schema<?> getMapSchema() {
return new ObjectSchema() return new ObjectSchema()
.description("a sample model") .description("a sample model")
.addProperties("mapping", new MapSchema() .addProperties("mapping", new MapSchema()
.additionalProperties(new StringSchema())); .additionalProperties(new StringSchema()));
} }
private Schema getComplexSchema() { private Schema<?> getComplexSchema() {
return new ObjectSchema() return new ObjectSchema()
.description("a sample model") .description("a sample model")
.addProperties("child", new ObjectSchema().$ref("#/components/schemas/Child")); .addProperties("child", new ObjectSchema().$ref("#/components/schemas/Child"));
@ -83,7 +83,7 @@ public class KotlinClientCodegenModelTest {
@Test(description = "convert a simple model") @Test(description = "convert a simple model")
public void simpleModelTest() { public void simpleModelTest() {
final Schema schema = getSimpleSchema(); final Schema<?> schema = getSimpleSchema();
final DefaultCodegen codegen = new KotlinClientCodegen(); final DefaultCodegen codegen = new KotlinClientCodegen();
codegen.processOpts(); codegen.processOpts();
@ -128,7 +128,7 @@ public class KotlinClientCodegenModelTest {
@Test(description = "convert a simple model: threetenbp") @Test(description = "convert a simple model: threetenbp")
public void selectDateLibraryAsThreetenbp() { public void selectDateLibraryAsThreetenbp() {
final Schema schema = getSimpleSchema(); final Schema<?> schema = getSimpleSchema();
final KotlinClientCodegen codegen = new KotlinClientCodegen(); final KotlinClientCodegen codegen = new KotlinClientCodegen();
codegen.setDateLibrary(KotlinClientCodegen.DateLibrary.THREETENBP.value); codegen.setDateLibrary(KotlinClientCodegen.DateLibrary.THREETENBP.value);
codegen.processOpts(); codegen.processOpts();
@ -149,7 +149,7 @@ public class KotlinClientCodegenModelTest {
@Test(description = "convert a simple model: threetenbp-localdatetime") @Test(description = "convert a simple model: threetenbp-localdatetime")
public void selectDateLibraryAsThreetenbpLocalDateTime() { public void selectDateLibraryAsThreetenbpLocalDateTime() {
final Schema schema = getSimpleSchema(); final Schema<?> schema = getSimpleSchema();
final KotlinClientCodegen codegen = new KotlinClientCodegen(); final KotlinClientCodegen codegen = new KotlinClientCodegen();
String value = KotlinClientCodegen.DateLibrary.THREETENBP_LOCALDATETIME.value; String value = KotlinClientCodegen.DateLibrary.THREETENBP_LOCALDATETIME.value;
Assert.assertEquals(value, "threetenbp-localdatetime"); Assert.assertEquals(value, "threetenbp-localdatetime");
@ -172,7 +172,7 @@ public class KotlinClientCodegenModelTest {
@Test(description = "convert a simple model: date string") @Test(description = "convert a simple model: date string")
public void selectDateLibraryAsString() { public void selectDateLibraryAsString() {
final Schema schema = getSimpleSchema(); final Schema<?> schema = getSimpleSchema();
final KotlinClientCodegen codegen = new KotlinClientCodegen(); final KotlinClientCodegen codegen = new KotlinClientCodegen();
codegen.setDateLibrary(KotlinClientCodegen.DateLibrary.STRING.value); codegen.setDateLibrary(KotlinClientCodegen.DateLibrary.STRING.value);
codegen.processOpts(); codegen.processOpts();
@ -193,7 +193,7 @@ public class KotlinClientCodegenModelTest {
@Test(description = "convert a simple model: date java8") @Test(description = "convert a simple model: date java8")
public void selectDateLibraryAsJava8() { public void selectDateLibraryAsJava8() {
final Schema schema = getSimpleSchema(); final Schema<?> schema = getSimpleSchema();
final KotlinClientCodegen codegen = new KotlinClientCodegen(); final KotlinClientCodegen codegen = new KotlinClientCodegen();
codegen.setDateLibrary(KotlinClientCodegen.DateLibrary.JAVA8.value); codegen.setDateLibrary(KotlinClientCodegen.DateLibrary.JAVA8.value);
codegen.processOpts(); codegen.processOpts();
@ -214,7 +214,7 @@ public class KotlinClientCodegenModelTest {
@Test(description = "convert a simple model: date java8-localdatetime") @Test(description = "convert a simple model: date java8-localdatetime")
public void selectDateLibraryAsJava8LocalDateTime() { public void selectDateLibraryAsJava8LocalDateTime() {
final Schema schema = getSimpleSchema(); final Schema<?> schema = getSimpleSchema();
final KotlinClientCodegen codegen = new KotlinClientCodegen(); final KotlinClientCodegen codegen = new KotlinClientCodegen();
String value = KotlinClientCodegen.DateLibrary.JAVA8_LOCALDATETIME.value; String value = KotlinClientCodegen.DateLibrary.JAVA8_LOCALDATETIME.value;
Assert.assertEquals(value, "java8-localdatetime"); Assert.assertEquals(value, "java8-localdatetime");
@ -237,7 +237,7 @@ public class KotlinClientCodegenModelTest {
@Test(description = "convert a model with array property to default kotlin.Array") @Test(description = "convert a model with array property to default kotlin.Array")
public void arrayPropertyTest() { public void arrayPropertyTest() {
final Schema model = getArrayTestSchema(); final Schema<?> model = getArrayTestSchema();
final DefaultCodegen codegen = new KotlinClientCodegen(); final DefaultCodegen codegen = new KotlinClientCodegen();
OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", model); OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", model);
@ -264,7 +264,7 @@ public class KotlinClientCodegenModelTest {
@Test(description = "convert a model with array property to a kotlin.collections.List") @Test(description = "convert a model with array property to a kotlin.collections.List")
public void listPropertyTest() { public void listPropertyTest() {
final Schema model = getArrayTestSchema(); final Schema<?> model = getArrayTestSchema();
final KotlinClientCodegen codegen = new KotlinClientCodegen(); final KotlinClientCodegen codegen = new KotlinClientCodegen();
codegen.setCollectionType(KotlinClientCodegen.CollectionType.LIST.value); codegen.setCollectionType(KotlinClientCodegen.CollectionType.LIST.value);
@ -293,7 +293,7 @@ public class KotlinClientCodegenModelTest {
@Test(description = "convert a model with a map property") @Test(description = "convert a model with a map property")
public void mapPropertyTest() { public void mapPropertyTest() {
final Schema schema = getMapSchema(); final Schema<?> schema = getMapSchema();
final DefaultCodegen codegen = new KotlinClientCodegen(); final DefaultCodegen codegen = new KotlinClientCodegen();
OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", schema); OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", schema);
codegen.setOpenAPI(openAPI); codegen.setOpenAPI(openAPI);
@ -317,7 +317,7 @@ public class KotlinClientCodegenModelTest {
@Test(description = "convert a model with complex property") @Test(description = "convert a model with complex property")
public void complexPropertyTest() { public void complexPropertyTest() {
final Schema schema = getComplexSchema(); final Schema<?> schema = getComplexSchema();
final DefaultCodegen codegen = new KotlinClientCodegen(); final DefaultCodegen codegen = new KotlinClientCodegen();
OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", schema); OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", schema);
codegen.setOpenAPI(openAPI); codegen.setOpenAPI(openAPI);
@ -351,7 +351,7 @@ public class KotlinClientCodegenModelTest {
@Test(dataProvider = "modelNames", description = "sanitize model names") @Test(dataProvider = "modelNames", description = "sanitize model names")
public void sanitizeModelNames(final String name, final ModelNameTest testCase) { public void sanitizeModelNames(final String name, final ModelNameTest testCase) {
final Schema schema = getComplexSchema(); final Schema<?> schema = getComplexSchema();
final DefaultCodegen codegen = new KotlinClientCodegen(); final DefaultCodegen codegen = new KotlinClientCodegen();
OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema(name, schema); OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema(name, schema);
codegen.setOpenAPI(openAPI); codegen.setOpenAPI(openAPI);
@ -448,4 +448,3 @@ public class KotlinClientCodegenModelTest {
} }
} }
} }

View File

@ -17,9 +17,14 @@ import org.testng.annotations.Test;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
import static org.openapitools.codegen.TestUtils.assertFileContains; import static org.openapitools.codegen.TestUtils.assertFileContains;
import static org.openapitools.codegen.VendorExtension.X_CLASS_EXTRA_ANNOTATION;
import static org.openapitools.codegen.VendorExtension.X_FIELD_EXTRA_ANNOTATION;
public class KotlinModelCodegenTest { public class KotlinModelCodegenTest {
@ -110,4 +115,20 @@ public class KotlinModelCodegenTest {
assertFileContains(Paths.get(outputPath + "/src/main/kotlin/models/UniqueArray.kt"), assertFileContains(Paths.get(outputPath + "/src/main/kotlin/models/UniqueArray.kt"),
"var array: kotlin.collections.MutableSet<kotlin.String>"); "var array: kotlin.collections.MutableSet<kotlin.String>");
} }
@Test(dataProvider = "generators")
public void xFieldExtraAnnotation(AbstractKotlinCodegen codegen) throws IOException {
assumeThat(codegen.getSupportedVendorExtensions().contains(X_FIELD_EXTRA_ANNOTATION)).isTrue();
String outputPath = generateModels(codegen, "src/test/resources/3_0/issue_11772.yml", true);
Path ktClassPath = Paths.get(outputPath + "/src/main/kotlin/models/Employee.kt");
assertThat(ktClassPath).content().contains("@javax.persistence.Id");
}
@Test(dataProvider = "generators")
public void xClassExtraAnnotation(AbstractKotlinCodegen codegen) throws IOException {
assumeThat(codegen.getSupportedVendorExtensions().contains(X_CLASS_EXTRA_ANNOTATION)).isTrue();
String outputPath = generateModels(codegen, "src/test/resources/3_0/issue_11772.yml", true);
Path ktClassPath = Paths.get(outputPath + "/src/main/kotlin/models/Employee.kt");
assertThat(ktClassPath).content().contains("@javax.persistence.MappedSuperclass");
}
} }