From 666d7cc45e6eb7043b04acb91f7c047834f38cea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=A6=E5=A2=83=E8=BF=B7=E7=A6=BB?= Date: Thu, 6 Jul 2023 17:58:25 +0800 Subject: [PATCH] Modify annotation position for kotlin --- .../kotlin-lang/parametrized_input.ftl | 2 +- .../resources/templates/kotlin-lang/type.ftl | 4 +- .../kotlin/GraphQLCodegenAnnotationsTest.java | 127 ++++++++++++++++++ 3 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 src/test/java/com/kobylynskyi/graphql/codegen/kotlin/GraphQLCodegenAnnotationsTest.java diff --git a/src/main/resources/templates/kotlin-lang/parametrized_input.ftl b/src/main/resources/templates/kotlin-lang/parametrized_input.ftl index 6057672bd..39bcbbad6 100755 --- a/src/main/resources/templates/kotlin-lang/parametrized_input.ftl +++ b/src/main/resources/templates/kotlin-lang/parametrized_input.ftl @@ -32,7 +32,7 @@ data class ${className}( <#if field.deprecated?has_content> @${field.deprecated.annotation}(message = "${field.deprecated.reason}") - <#list field.annotations as annotation>@get:${annotation} + <#list field.annotations as annotation>@field:${annotation} val ${field.name}: ${field.type}<#if field.defaultValue?has_content> = ${field.defaultValue}<#if field_has_next>, diff --git a/src/main/resources/templates/kotlin-lang/type.ftl b/src/main/resources/templates/kotlin-lang/type.ftl index 3a332eddd..c2ec5a587 100755 --- a/src/main/resources/templates/kotlin-lang/type.ftl +++ b/src/main/resources/templates/kotlin-lang/type.ftl @@ -66,8 +66,8 @@ open class ${className}()<#if implements?has_content> : <#list implements as int @${field.deprecated.annotation}(message = "${field.deprecated.reason}") <#-- Properties of multiple interfaces should not have duplicate names --> <#if parentInterfaces?has_content><#list parentInterfaces as parent><#if parent == field.name>override - <#if !immutableModels><#list field.annotations as annotation>@get:${annotation} - var <#else><#list field.annotations as annotation>@get:${annotation} + <#if !immutableModels><#list field.annotations as annotation>@field:${annotation} + var <#else><#list field.annotations as annotation>@field:${annotation} val ${field.name}: ${field.type}<#if field.defaultValue?has_content> = ${field.defaultValue}<#elseif field.type?ends_with("?") && (initializeNullableTypes == true)> = null<#if field_has_next>, diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/kotlin/GraphQLCodegenAnnotationsTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/kotlin/GraphQLCodegenAnnotationsTest.java new file mode 100644 index 000000000..127abb4f7 --- /dev/null +++ b/src/test/java/com/kobylynskyi/graphql/codegen/kotlin/GraphQLCodegenAnnotationsTest.java @@ -0,0 +1,127 @@ +package com.kobylynskyi.graphql.codegen.kotlin; + +import com.kobylynskyi.graphql.codegen.MaxQueryTokensExtension; +import com.kobylynskyi.graphql.codegen.TestUtils; +import com.kobylynskyi.graphql.codegen.model.GeneratedLanguage; +import com.kobylynskyi.graphql.codegen.model.MappingConfig; +import com.kobylynskyi.graphql.codegen.utils.Utils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Objects; + +import static com.kobylynskyi.graphql.codegen.TestUtils.assertFileContainsElements; +import static java.lang.System.lineSeparator; +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; + +@ExtendWith(MaxQueryTokensExtension.class) +class GraphQLCodegenAnnotationsTest { + + private final File outputBuildDir = new File("build/generated"); + private final File outputJavaClassesDir = new File("build/generated/com/kobylynskyi/graphql/test1"); + + private MappingConfig mappingConfig; + + @BeforeEach + void init() { + mappingConfig = new MappingConfig(); + mappingConfig.setPackageName("com.kobylynskyi.graphql.test1"); + mappingConfig.setGenerateParameterizedFieldsResolvers(false); + mappingConfig.setGeneratedLanguage(GeneratedLanguage.KOTLIN); + } + + @AfterEach + void cleanup() { + Utils.deleteDir(outputBuildDir); + } + + @Test + void generate_CustomAnnotationMappings() throws Exception { + mappingConfig.setCustomTypesMapping(new HashMap<>( + singletonMap("Event.createdDateTime", "org.joda.time.DateTime"))); + mappingConfig.setCustomAnnotationsMapping(new HashMap<>(singletonMap("Event.createdDateTime", + singletonList("@com.fasterxml.jackson.databind.annotation.JsonDeserialize(" + + "using = com.example.json.DateTimeScalarDeserializer.class)")))); + + generate("src/test/resources/schemas/test.graphqls"); + + File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); + assertFileContainsElements(files, "Event.kt", + "@field:com.fasterxml.jackson.databind.annotation.JsonDeserialize(", + "using = com.example.json.DateTimeScalarDeserializer.class)", + " val createdDateTime: org.joda.time.DateTime?"); + } + + @Test + void generate_CustomAnnotationMappings_Type() throws Exception { + mappingConfig.setCustomTypesMapping(new HashMap<>(singletonMap("DateTime", "org.joda.time.DateTime"))); + mappingConfig.setCustomAnnotationsMapping(new HashMap<>(singletonMap("DateTime", + singletonList("com.fasterxml.jackson.databind.annotation.JsonDeserialize(" + + "using = com.example.json.DateTimeScalarDeserializer.class)")))); + + generate("src/test/resources/schemas/test.graphqls"); + + File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); + assertFileContainsElements(files, "Event.kt", + "@field:com.fasterxml.jackson.databind.annotation.JsonDeserialize(", + "using = com.example.json.DateTimeScalarDeserializer.class)", + " val createdDateTime: org.joda.time.DateTime?"); + } + + @Test + void generate_CustomAnnotationMappings_Input() throws Exception { + mappingConfig.setCustomAnnotationsMapping(new HashMap<>(singletonMap("ReproInput.reproField", + singletonList("@com.fasterxml.jackson.annotation.JsonProperty(\"reproField\")")))); + + generate("src/test/resources/schemas/input.graphqls"); + + File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); + assertFileContainsElements(files, "ReproInput.kt", + " @field:com.fasterxml.jackson.annotation.JsonProperty(\"reproField\")" + lineSeparator() + + " val reproField: List"); + } + + @Test + void generate_CustomAnnotationMappings_Regexp() throws Exception { + mappingConfig.setCustomTypesMapping(new HashMap<>(singletonMap("DateTime", "org.joda.time.DateTime"))); + mappingConfig.setCustomAnnotationsMapping(new HashMap<>(singletonMap("Date.*", + singletonList("com.fasterxml.jackson.databind.annotation.JsonDeserialize(" + + "using = com.example.json.DateTimeScalarDeserializer.class)")))); + + generate("src/test/resources/schemas/test.graphqls"); + + File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); + assertFileContainsElements(files, "Event.kt", + "@field:com.fasterxml.jackson.databind.annotation.JsonDeserialize(", + "using = com.example.json.DateTimeScalarDeserializer.class)", + " val createdDateTime: org.joda.time.DateTime?"); + } + + @Test + void generate_CustomAnnotationMappings_FieldType() throws Exception { + mappingConfig.setCustomTypesMapping(new HashMap<>(singletonMap("DateTime", "org.joda.time.DateTime"))); + mappingConfig.setCustomAnnotationsMapping(new HashMap<>(singletonMap("Event.createdDateTime", + singletonList("@com.fasterxml.jackson.databind.annotation.JsonDeserialize(" + + "using = com.example.json.DateTimeScalarDeserializer.class)")))); + + generate("src/test/resources/schemas/test.graphqls"); + + File[] files = Objects.requireNonNull(outputJavaClassesDir.listFiles()); + assertFileContainsElements(files, "Event.kt", + "@field:com.fasterxml.jackson.databind.annotation.JsonDeserialize(", + "using = com.example.json.DateTimeScalarDeserializer.class)", + " val createdDateTime: org.joda.time.DateTime?"); + } + + private void generate(String path) throws IOException { + new KotlinGraphQLCodegen(singletonList(path), outputBuildDir, mappingConfig, + TestUtils.getStaticGeneratedInfo(mappingConfig)).generate(); + } + +}