diff --git a/generator/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/internal/extensions/kClassExtensions.kt b/generator/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/internal/extensions/kClassExtensions.kt index e8280831da..122d8c7d72 100644 --- a/generator/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/internal/extensions/kClassExtensions.kt +++ b/generator/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/internal/extensions/kClassExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 Expedia, Inc + * Copyright 2024 Expedia, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.expediagroup.graphql.generator.internal.extensions +import com.expediagroup.graphql.generator.annotations.GraphQLValidObjectLocations import com.expediagroup.graphql.generator.exceptions.CouldNotGetNameOfKClassException import com.expediagroup.graphql.generator.hooks.SchemaGeneratorHooks import com.expediagroup.graphql.generator.internal.filters.functionFilters @@ -28,6 +29,7 @@ import kotlin.reflect.KProperty import kotlin.reflect.KVisibility import kotlin.reflect.full.declaredMemberFunctions import kotlin.reflect.full.declaredMemberProperties +import kotlin.reflect.full.findAnnotation import kotlin.reflect.full.findParameterByName import kotlin.reflect.full.isSubclassOf import kotlin.reflect.full.memberFunctions @@ -84,12 +86,16 @@ internal fun KClass<*>.isListType(isDirective: Boolean = false): Boolean = this. @Throws(CouldNotGetNameOfKClassException::class) internal fun KClass<*>.getSimpleName(isInputClass: Boolean = false): String { + val isInputOnlyLocation = this.findAnnotation().let { + it != null && it.locations.size == 1 && it.locations.contains(GraphQLValidObjectLocations.Locations.INPUT_OBJECT) + } + val name = this.getGraphQLName() ?: this.simpleName ?: throw CouldNotGetNameOfKClassException(this) return when { - isInputClass -> if (name.endsWith(INPUT_SUFFIX, true)) name else "$name$INPUT_SUFFIX" + isInputClass -> if (name.endsWith(INPUT_SUFFIX, true) || isInputOnlyLocation) name else "$name$INPUT_SUFFIX" else -> name } } diff --git a/generator/graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/internal/extensions/KClassExtensionsTest.kt b/generator/graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/internal/extensions/KClassExtensionsTest.kt index d1b70be74c..64593acc73 100644 --- a/generator/graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/internal/extensions/KClassExtensionsTest.kt +++ b/generator/graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/internal/extensions/KClassExtensionsTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 Expedia, Inc + * Copyright 2024 Expedia, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ package com.expediagroup.graphql.generator.internal.extensions import com.expediagroup.graphql.generator.annotations.GraphQLIgnore import com.expediagroup.graphql.generator.annotations.GraphQLName import com.expediagroup.graphql.generator.annotations.GraphQLUnion +import com.expediagroup.graphql.generator.annotations.GraphQLValidObjectLocations import com.expediagroup.graphql.generator.exceptions.CouldNotGetNameOfKClassException import com.expediagroup.graphql.generator.hooks.NoopSchemaGeneratorHooks import com.expediagroup.graphql.generator.hooks.SchemaGeneratorHooks @@ -77,6 +78,13 @@ open class KClassExtensionsTest { @GraphQLName("MyClassRenamedInput") class MyClassCustomNameInput + @GraphQLValidObjectLocations([GraphQLValidObjectLocations.Locations.INPUT_OBJECT]) + class MyInputClassWithoutSuffix + + @GraphQLValidObjectLocations([GraphQLValidObjectLocations.Locations.INPUT_OBJECT]) + @GraphQLName("MyClass") + class MyInputClassWithoutSuffixUsingCustomName + protected class MyProtectedClass class MyPublicClass @@ -378,4 +386,10 @@ open class KClassExtensionsTest { assertFalse(IgnoredClass::class.isValidAdditionalType(true)) assertFalse(IgnoredClass::class.isValidAdditionalType(false)) } + + @Test + fun `@GraphQLName does not apply input suffix on input only classes`() { + assertEquals("MyInputClassWithoutSuffix", MyInputClassWithoutSuffix::class.getSimpleName(isInputClass = true)) + assertEquals("MyClass", MyInputClassWithoutSuffixUsingCustomName::class.getSimpleName(isInputClass = true)) + } } diff --git a/website/docs/schema-generator/customizing-schemas/renaming-fields.md b/website/docs/schema-generator/customizing-schemas/renaming-fields.md index 2a1e1c5309..1fa2b9cf36 100644 --- a/website/docs/schema-generator/customizing-schemas/renaming-fields.md +++ b/website/docs/schema-generator/customizing-schemas/renaming-fields.md @@ -20,6 +20,27 @@ type MyCustomName { } ``` +:::info +By default, in order to differentiate between input and output types, all input type names are auto generated with additional +`Input` suffix. Suffix is appended only if input type name does not already end with `Input`. If you would like to change this +behavior and avoid extra suffix, you need to explicitly specify that this is an input only type. + +```kotlin +// GraphQL input object type name: MyInputType +@GraphQLValidObjectLocations([GraphQLValidObjectLocations.Locations.INPUT_OBJECT]) +data class MyInputType(val id: ID) +``` + +You can also rename input types + +```kotlin +// GraphQL input object type name: MyCustomInputType +@GraphQLValidObjectLocations([GraphQLValidObjectLocations.Locations.INPUT_OBJECT]) +@GraphQLName("MyCustomInputType") +data class MyInputType(val id: ID) +``` +::: + ## Known Issues Due to how we deserialize input classes, if you rename a field of an input class or an enum value you must also annotate