Skip to content

Commit ee67a5a

Browse files
sgebsmyrick
authored andcommitted
Support custom names via @GraphQLName (#211)
1 parent af9667d commit ee67a5a

File tree

11 files changed

+164
-2
lines changed

11 files changed

+164
-2
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.expedia.graphql.annotations
2+
3+
/**
4+
* Set the GraphQL name to be picked up by the schema generator.
5+
*/
6+
@Target(AnnotationTarget.CLASS)
7+
annotation class GraphQLName(val value: String)

src/main/kotlin/com/expedia/graphql/generator/extensions/annotationExtensions.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ package com.expedia.graphql.generator.extensions
33
import com.expedia.graphql.annotations.GraphQLDescription
44
import com.expedia.graphql.annotations.GraphQLID
55
import com.expedia.graphql.annotations.GraphQLIgnore
6+
import com.expedia.graphql.annotations.GraphQLName
67
import kotlin.reflect.KAnnotatedElement
78
import kotlin.reflect.full.findAnnotation
89

910
internal fun KAnnotatedElement.getGraphQLDescription(): String? = this.findAnnotation<GraphQLDescription>()?.value
1011

12+
internal fun KAnnotatedElement.getGraphQLName(): String? = this.findAnnotation<GraphQLName>()?.value
13+
1114
internal fun KAnnotatedElement.getDeprecationReason(): String? = this.findAnnotation<Deprecated>()?.getReason()
1215

1316
internal fun KAnnotatedElement.isGraphQLIgnored(): Boolean = this.findAnnotation<GraphQLIgnore>() != null

src/main/kotlin/com/expedia/graphql/generator/extensions/kClassExtensions.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ internal fun KClass<*>.isListType(): Boolean = this.isList() || this.isArray()
5454

5555
@Throws(CouldNotGetNameOfKClassException::class)
5656
internal fun KClass<*>.getSimpleName(isInputClass: Boolean = false): String {
57-
val name = this.simpleName ?: throw CouldNotGetNameOfKClassException(this)
57+
val name = this.getGraphQLName()
58+
?: this.simpleName
59+
?: throw CouldNotGetNameOfKClassException(this)
5860

5961
return when {
6062
isInputClass -> if (name.endsWith(INPUT_SUFFIX)) name else "$name$INPUT_SUFFIX"

src/test/kotlin/com/expedia/graphql/generator/SchemaGeneratorTest.kt

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.expedia.graphql.TopLevelObject
44
import com.expedia.graphql.annotations.GraphQLDescription
55
import com.expedia.graphql.annotations.GraphQLID
66
import com.expedia.graphql.annotations.GraphQLIgnore
7+
import com.expedia.graphql.annotations.GraphQLName
78
import com.expedia.graphql.exceptions.ConflictingTypesException
89
import com.expedia.graphql.exceptions.GraphQLKotlinException
910
import com.expedia.graphql.exceptions.InvalidIdTypeException
@@ -129,6 +130,27 @@ class SchemaGeneratorTest {
129130
assertEquals("SomeEnum!", topLevelQuery.getFieldDefinition("query").type.deepName)
130131
}
131132

133+
@Test
134+
fun `SchemaGenerator names types according to custom name in @GraphQLName`() {
135+
val schema = toSchema(queries = listOf(TopLevelObject(QueryWithCustomName())), config = testSchemaConfig)
136+
val topLevelQuery = schema.getObjectType("Query")
137+
138+
assertEquals("SomeInputObjectRenamedInput!", topLevelQuery.getFieldDefinition("query").getArgument("someInputObjectWithCustomName").type.deepName)
139+
assertEquals("SomeEnumRenamed!", topLevelQuery.getFieldDefinition("query").getArgument("someEnumWithCustomName").type.deepName)
140+
assertEquals("SomeObjectWithDefaultNameInput!", topLevelQuery.getFieldDefinition("query").getArgument("someObjectWithDefaultName").type.deepName)
141+
assertEquals("SomeOtherObjectRenamed!", topLevelQuery.getFieldDefinition("query").type.deepName)
142+
}
143+
144+
@Test
145+
fun `SchemaGenerator names self-referencing types according to custom name in @GraphQLName`() {
146+
val schema = toSchema(queries = listOf(TopLevelObject(QuerySelfReferencingWithCustomName())), config = testSchemaConfig)
147+
val topLevelQuery = schema.getObjectType("Query")
148+
val resultType = schema.getObjectType("ObjectSelfReferencingRenamed")
149+
150+
assertEquals("ObjectSelfReferencingRenamed!", topLevelQuery.getFieldDefinition("query").type.deepName)
151+
assertEquals("ObjectSelfReferencingRenamed", resultType.getFieldDefinition("self").type.deepName)
152+
}
153+
132154
@Test
133155
fun `SchemaGenerator documents types annotated with @Description`() {
134156
val schema = toSchema(
@@ -415,6 +437,46 @@ class SchemaGeneratorTest {
415437
fun query(): InvalidIds = InvalidIds(Person("person id not a valid type id"))
416438
}
417439

440+
data class SomeObjectWithDefaultName(val title: String)
441+
442+
@GraphQLName("SomeObjectRenamed")
443+
data class SomeObjectWithCustomName(val title: String)
444+
445+
@GraphQLName("SomeOtherObjectRenamed")
446+
data class SomeOtherObjectWithCustomName(
447+
val title: String,
448+
val someObject: SomeObjectWithCustomName,
449+
val someEnum: SomeEnumWithCustomName
450+
)
451+
452+
@GraphQLName("SomeInputObjectRenamed")
453+
data class SomeInputObjectWithCustomName(val title: String)
454+
455+
@GraphQLName("SomeEnumRenamed")
456+
enum class SomeEnumWithCustomName { ONE, TWO }
457+
458+
class QueryWithCustomName {
459+
fun query(
460+
someInputObjectWithCustomName: SomeInputObjectWithCustomName,
461+
someEnumWithCustomName: SomeEnumWithCustomName,
462+
someObjectWithDefaultName: SomeObjectWithDefaultName
463+
): SomeOtherObjectWithCustomName =
464+
SomeOtherObjectWithCustomName(
465+
title = someObjectWithDefaultName.title,
466+
someObject = SomeObjectWithCustomName("something"),
467+
someEnum = someEnumWithCustomName
468+
)
469+
}
470+
471+
@GraphQLName("ObjectSelfReferencingRenamed")
472+
data class ObjectSelfReferencingWithCustomName(
473+
val self: ObjectSelfReferencingWithCustomName? = null
474+
)
475+
476+
class QuerySelfReferencingWithCustomName {
477+
fun query(): ObjectSelfReferencingWithCustomName = ObjectSelfReferencingWithCustomName()
478+
}
479+
418480
class MutationWithId {
419481
fun mutate(furniture: Furniture): Furniture = furniture
420482
}

src/test/kotlin/com/expedia/graphql/generator/extensions/AnnotationExtensionsTest.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.expedia.graphql.generator.extensions
33
import com.expedia.graphql.annotations.GraphQLDescription
44
import com.expedia.graphql.annotations.GraphQLID
55
import com.expedia.graphql.annotations.GraphQLIgnore
6+
import com.expedia.graphql.annotations.GraphQLName
67
import org.junit.jupiter.api.Test
78
import kotlin.reflect.full.declaredMemberProperties
89
import kotlin.test.assertEquals
@@ -13,6 +14,7 @@ import kotlin.test.assertTrue
1314
@Suppress("Detekt.UnusedPrivateClass")
1415
internal class AnnotationExtensionsTest {
1516

17+
@GraphQLName("WithAnnotationsCustomName")
1618
@GraphQLDescription("class description")
1719
@Deprecated("class deprecated")
1820
@GraphQLIgnore
@@ -25,6 +27,12 @@ internal class AnnotationExtensionsTest {
2527

2628
private data class NoAnnotations(val id: String)
2729

30+
@Test
31+
fun `verify @GraphQLName on classes`() {
32+
assertEquals(expected = "WithAnnotationsCustomName", actual = WithAnnotations::class.getGraphQLName())
33+
assertNull(NoAnnotations::class.getGraphQLName())
34+
}
35+
2836
@Test
2937
fun `verify @GraphQLDescrption on classes`() {
3038
assertEquals(expected = "class description", actual = WithAnnotations::class.getGraphQLDescription())

src/test/kotlin/com/expedia/graphql/generator/extensions/KClassExtensionsTest.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.expedia.graphql.generator.extensions
22

3+
import com.expedia.graphql.annotations.GraphQLName
34
import com.expedia.graphql.exceptions.CouldNotGetNameOfKClassException
45
import com.expedia.graphql.hooks.NoopSchemaGeneratorHooks
56
import com.expedia.graphql.hooks.SchemaGeneratorHooks
@@ -48,10 +49,16 @@ open class KClassExtensionsTest {
4849
private fun privateTestFunction() = "private function"
4950
}
5051

52+
@GraphQLName("MyTestClassRenamed")
53+
private class MyTestClassCustomName
54+
5155
internal class MyInternalClass
5256

5357
class MyClassInput
5458

59+
@GraphQLName("MyClassRenamedInput")
60+
class MyClassCustomNameInput
61+
5562
protected class MyProtectedClass
5663

5764
class MyPublicClass
@@ -209,12 +216,23 @@ open class KClassExtensionsTest {
209216
}
210217
}
211218

219+
@Test
220+
fun `test class simple name with GraphQLName`() {
221+
assertEquals("MyTestClassRenamed", MyTestClassCustomName::class.getSimpleName())
222+
}
223+
212224
@Test
213225
fun `test input class name`() {
214226
assertEquals("MyTestClassInput", MyTestClass::class.getSimpleName(true))
215227
assertEquals("MyClassInput", MyClassInput::class.getSimpleName(true))
216228
}
217229

230+
@Test
231+
fun `test input class name with GraphQLName`() {
232+
assertEquals("MyTestClassRenamedInput", MyTestClassCustomName::class.getSimpleName(true))
233+
assertEquals("MyClassRenamedInput", MyClassCustomNameInput::class.getSimpleName(true))
234+
}
235+
218236
@Test
219237
fun getQualifiedName() {
220238
assertEquals("com.expedia.graphql.generator.extensions.KClassExtensionsTest.MyTestClass", MyTestClass::class.getQualifiedName())

src/test/kotlin/com/expedia/graphql/generator/types/EnumBuilderTest.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.expedia.graphql.generator.types
22

33
import com.expedia.graphql.annotations.GraphQLDescription
4+
import com.expedia.graphql.annotations.GraphQLName
45
import com.expedia.graphql.test.utils.CustomDirective
56
import com.expedia.graphql.test.utils.SimpleDirective
67
import org.junit.jupiter.api.Test
@@ -30,6 +31,10 @@ internal class EnumBuilderTest : TypeTestHelper() {
3031
THREE
3132
}
3233

34+
@Suppress("Detekt.UnusedPrivateClass")
35+
@GraphQLName("MyTestEnumRenamed")
36+
private enum class MyTestEnumCustomName
37+
3338
lateinit var builder: EnumBuilder
3439

3540
override fun beforeTest() {
@@ -47,6 +52,12 @@ internal class EnumBuilderTest : TypeTestHelper() {
4752
assertEquals(expected = "THREE", actual = actual.values[2].value)
4853
}
4954

55+
@Test
56+
fun `Custom name on enum class`() {
57+
val gqlEnum = assertNotNull(builder.enumType(MyTestEnumCustomName::class))
58+
assertEquals("MyTestEnumRenamed", gqlEnum.name)
59+
}
60+
5061
@Test
5162
fun `Description on enum class and values`() {
5263
val gqlEnum = assertNotNull(builder.enumType(MyTestEnum::class))

src/test/kotlin/com/expedia/graphql/generator/types/InputObjectBuilderTest.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.expedia.graphql.generator.types
22

33
import com.expedia.graphql.annotations.GraphQLDescription
4+
import com.expedia.graphql.annotations.GraphQLName
45
import com.expedia.graphql.test.utils.SimpleDirective
56
import org.junit.jupiter.api.Test
67
import kotlin.test.assertEquals
@@ -17,17 +18,28 @@ internal class InputObjectBuilderTest : TypeTestHelper() {
1718
@GraphQLDescription("The truth")
1819
@SimpleDirective
1920
private class InputClass {
20-
2121
@SimpleDirective
2222
val myField: String = "car"
2323
}
2424

25+
@Suppress("Detekt.UnusedPrivateClass")
26+
@GraphQLName("InputClassRenamed")
27+
private class InputClassCustomName {
28+
val myField: String = "car"
29+
}
30+
2531
@Test
2632
fun `Test naming`() {
2733
val result = builder.inputObjectType(InputClass::class)
2834
assertEquals("InputClassInput", result.name)
2935
}
3036

37+
@Test
38+
fun `Test custom naming`() {
39+
val result = builder.inputObjectType(InputClassCustomName::class)
40+
assertEquals("InputClassRenamedInput", result.name)
41+
}
42+
3143
@Test
3244
fun `Test description`() {
3345
val result = builder.inputObjectType(InputClass::class)

src/test/kotlin/com/expedia/graphql/generator/types/InterfaceBuilderTest.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.expedia.graphql.generator.types
22

33
import com.expedia.graphql.annotations.GraphQLDescription
4+
import com.expedia.graphql.annotations.GraphQLName
45
import com.expedia.graphql.test.utils.SimpleDirective
56
import graphql.schema.GraphQLInterfaceType
67
import org.junit.jupiter.api.Test
@@ -19,12 +20,22 @@ internal class InterfaceBuilderTest : TypeTestHelper() {
1920
@SimpleDirective
2021
private interface HappyInterface
2122

23+
@Suppress("Detekt.UnusedPrivateClass")
24+
@GraphQLName("HappyInterfaceRenamed")
25+
private interface HappyInterfaceCustomName
26+
2227
@Test
2328
fun `Test naming`() {
2429
val result = builder.interfaceType(HappyInterface::class) as? GraphQLInterfaceType
2530
assertEquals("HappyInterface", result?.name)
2631
}
2732

33+
@Test
34+
fun `Test custom naming`() {
35+
val result = builder.interfaceType(HappyInterfaceCustomName::class) as? GraphQLInterfaceType
36+
assertEquals("HappyInterfaceRenamed", result?.name)
37+
}
38+
2839
@Test
2940
fun `Test description`() {
3041
val result = builder.interfaceType(HappyInterface::class) as? GraphQLInterfaceType

src/test/kotlin/com/expedia/graphql/generator/types/ObjectBuilderTest.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.expedia.graphql.generator.types
22

33
import com.expedia.graphql.annotations.GraphQLDescription
44
import com.expedia.graphql.annotations.GraphQLDirective
5+
import com.expedia.graphql.annotations.GraphQLName
56
import graphql.Scalars
67
import graphql.introspection.Introspection
78
import graphql.schema.GraphQLNonNull
@@ -26,13 +27,23 @@ internal class ObjectBuilderTest : TypeTestHelper() {
2627
@ObjectDirective("Don't worry")
2728
private class BeHappy
2829

30+
@GraphQLName("BeHappyRenamed")
31+
private class BeHappyCustomName
32+
2933
@Test
3034
fun `Test naming`() {
3135
val result = builder.objectType(BeHappy::class) as? GraphQLObjectType
3236
assertNotNull(result)
3337
assertEquals("BeHappy", result.name)
3438
}
3539

40+
@Test
41+
fun `Test custom naming`() {
42+
val result = builder.objectType(BeHappyCustomName::class) as? GraphQLObjectType
43+
assertNotNull(result)
44+
assertEquals("BeHappyRenamed", result.name)
45+
}
46+
3647
@Test
3748
fun `Test description`() {
3849
val result = builder.objectType(BeHappy::class) as? GraphQLObjectType

0 commit comments

Comments
 (0)