Skip to content

Commit e2121a5

Browse files
smyrickdariuszkuc
authored andcommitted
feat: allow renaming of properties and functions (ExpediaGroup#272)
Use @GraphQLName to set the name of fields in the schema, not just type names
1 parent f0a34b3 commit e2121a5

File tree

11 files changed

+65
-10
lines changed

11 files changed

+65
-10
lines changed

graphql-kotlin-schema-generator/src/main/kotlin/com/expedia/graphql/annotations/GraphQLName.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ package com.expedia.graphql.annotations
33
/**
44
* Set the GraphQL name to be picked up by the schema generator.
55
*/
6-
@Target(AnnotationTarget.CLASS)
6+
@Target(AnnotationTarget.CLASS, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
77
annotation class GraphQLName(val value: String)

graphql-kotlin-schema-generator/src/main/kotlin/com/expedia/graphql/generator/extensions/kCallableExtensions.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ import kotlin.reflect.KCallable
44
import kotlin.reflect.KVisibility
55

66
internal fun KCallable<*>.isPublic(): Boolean = this.visibility == KVisibility.PUBLIC
7+
8+
internal fun KCallable<*>.getFunctionName(): String = this.getGraphQLName() ?: this.name

graphql-kotlin-schema-generator/src/main/kotlin/com/expedia/graphql/generator/extensions/kPropertyExtensions.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,7 @@ internal fun KProperty<*>.getPropertyDeprecationReason(parentClass: KClass<*>):
2121
internal fun KProperty<*>.getPropertyDescription(parentClass: KClass<*>): String? =
2222
this.getGraphQLDescription() ?: getConstructorParameter(parentClass)?.getGraphQLDescription()
2323

24+
internal fun KProperty<*>.getPropertyName(parentClass: KClass<*>): String? =
25+
this.getGraphQLName() ?: getConstructorParameter(parentClass)?.getGraphQLName() ?: this.name
26+
2427
private fun KProperty<*>.getConstructorParameter(parentClass: KClass<*>) = parentClass.findConstructorParamter(this.name)

graphql-kotlin-schema-generator/src/main/kotlin/com/expedia/graphql/generator/types/FunctionBuilder.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.expedia.graphql.exceptions.InvalidInputFieldTypeException
55
import com.expedia.graphql.generator.SchemaGenerator
66
import com.expedia.graphql.generator.TypeBuilder
77
import com.expedia.graphql.generator.extensions.getDeprecationReason
8+
import com.expedia.graphql.generator.extensions.getFunctionName
89
import com.expedia.graphql.generator.extensions.getGraphQLDescription
910
import com.expedia.graphql.generator.extensions.getKClass
1011
import com.expedia.graphql.generator.extensions.getName
@@ -30,7 +31,8 @@ internal class FunctionBuilder(generator: SchemaGenerator) : TypeBuilder(generat
3031

3132
internal fun function(fn: KFunction<*>, parentName: String, target: Any? = null, abstract: Boolean = false): GraphQLFieldDefinition {
3233
val builder = GraphQLFieldDefinition.newFieldDefinition()
33-
builder.name(fn.name)
34+
val functionName = fn.getFunctionName()
35+
builder.name(functionName)
3436
builder.description(fn.getGraphQLDescription())
3537

3638
fn.getDeprecationReason()?.let {
@@ -56,7 +58,7 @@ internal class FunctionBuilder(generator: SchemaGenerator) : TypeBuilder(generat
5658
builder.type(graphQLTypeOf(returnType).safeCast<GraphQLOutputType>())
5759
val graphQLType = builder.build()
5860

59-
val coordinates = FieldCoordinates.coordinates(parentName, fn.name)
61+
val coordinates = FieldCoordinates.coordinates(parentName, functionName)
6062
if (!abstract) {
6163
val dataFetcherFactory = config.dataFetcherFactoryProvider.functionDataFetcherFactory(target = target, kFunction = fn)
6264
generator.codeRegistry.dataFetcher(coordinates, dataFetcherFactory)

graphql-kotlin-schema-generator/src/main/kotlin/com/expedia/graphql/generator/types/InputObjectBuilder.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.expedia.graphql.generator.SchemaGenerator
44
import com.expedia.graphql.generator.TypeBuilder
55
import com.expedia.graphql.generator.extensions.getGraphQLDescription
66
import com.expedia.graphql.generator.extensions.getPropertyDescription
7+
import com.expedia.graphql.generator.extensions.getPropertyName
78
import com.expedia.graphql.generator.extensions.getSimpleName
89
import com.expedia.graphql.generator.extensions.getValidProperties
910
import com.expedia.graphql.generator.extensions.isPropertyGraphQLID
@@ -36,7 +37,7 @@ internal class InputObjectBuilder(generator: SchemaGenerator) : TypeBuilder(gene
3637
val builder = GraphQLInputObjectField.newInputObjectField()
3738

3839
builder.description(prop.getPropertyDescription(parentClass))
39-
builder.name(prop.name)
40+
builder.name(prop.getPropertyName(parentClass))
4041
builder.type(graphQLTypeOf(prop.returnType, true, prop.isPropertyGraphQLID(parentClass)).safeCast<GraphQLInputType>())
4142

4243
generator.directives(prop).forEach {

graphql-kotlin-schema-generator/src/main/kotlin/com/expedia/graphql/generator/types/PropertyBuilder.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.expedia.graphql.generator.SchemaGenerator
55
import com.expedia.graphql.generator.TypeBuilder
66
import com.expedia.graphql.generator.extensions.getPropertyDeprecationReason
77
import com.expedia.graphql.generator.extensions.getPropertyDescription
8+
import com.expedia.graphql.generator.extensions.getPropertyName
89
import com.expedia.graphql.generator.extensions.getSimpleName
910
import com.expedia.graphql.generator.extensions.isPropertyGraphQLID
1011
import com.expedia.graphql.generator.extensions.safeCast
@@ -21,7 +22,7 @@ internal class PropertyBuilder(generator: SchemaGenerator) : TypeBuilder(generat
2122

2223
val fieldBuilder = GraphQLFieldDefinition.newFieldDefinition()
2324
.description(prop.getPropertyDescription(parentClass))
24-
.name(prop.name)
25+
.name(prop.getPropertyName(parentClass))
2526
.type(propertyType)
2627

2728
prop.getPropertyDeprecationReason(parentClass)?.let {

graphql-kotlin-schema-generator/src/test/kotlin/com/expedia/graphql/extensions/GraphQLSchemaExtensionsTest.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,13 @@ class GraphQLSchemaExtensionsTest {
4343
}
4444

4545
class RenamedQuery {
46+
@GraphQLName("renamedFunction")
4647
fun original(id: Int) = OriginalType(id)
4748
}
4849

4950
@GraphQLName("RenamedType")
5051
class OriginalType(
52+
@GraphQLName("renamedProperty")
5153
val originalProperty: Int
5254
)
5355

@@ -58,11 +60,11 @@ class GraphQLSchemaExtensionsTest {
5860
val sdl = schema.print(includeDefaultSchemaDefinition = false, includeDirectives = false).trim()
5961
val expected = """
6062
type Query {
61-
original(id: Int!): RenamedType!
63+
renamedFunction(id: Int!): RenamedType!
6264
}
6365
6466
type RenamedType {
65-
originalProperty: Int!
67+
renamedProperty: Int!
6668
}
6769
""".trimIndent()
6870
assertEquals(expected, sdl)

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.expedia.graphql.annotations.GraphQLID
55
import com.expedia.graphql.annotations.GraphQLIgnore
66
import com.expedia.graphql.annotations.GraphQLName
77
import org.junit.jupiter.api.Test
8+
import kotlin.reflect.KClass
89
import kotlin.reflect.full.declaredMemberProperties
910
import kotlin.test.assertEquals
1011
import kotlin.test.assertFalse
@@ -22,6 +23,7 @@ internal class AnnotationExtensionsTest {
2223
@property:Deprecated("property deprecated")
2324
@property:GraphQLDescription("property description")
2425
@property:GraphQLID
26+
@property:GraphQLName("newName")
2527
val id: String
2628
)
2729

@@ -33,6 +35,13 @@ internal class AnnotationExtensionsTest {
3335
assertNull(NoAnnotations::class.getGraphQLName())
3436
}
3537

38+
@Test
39+
fun `verify @GraphQLName on fields`() {
40+
val fieldName = WithAnnotations::class.findMemberProperty("id")?.getGraphQLName()
41+
assertEquals(expected = "newName", actual = fieldName)
42+
assertNull(NoAnnotations::class.findMemberProperty("id")?.getGraphQLName())
43+
}
44+
3645
@Test
3746
fun `verify @GraphQLDescrption on classes`() {
3847
assertEquals(expected = "class description", actual = WithAnnotations::class.getGraphQLDescription())
@@ -42,11 +51,12 @@ internal class AnnotationExtensionsTest {
4251
@Test
4352
fun `verify @Deprecated`() {
4453
val classDeprecation = WithAnnotations::class.getDeprecationReason()
45-
val classPropertyDeprecation = WithAnnotations::class.declaredMemberProperties.find { it.name == "id" }?.getDeprecationReason()
54+
val classPropertyDeprecation = WithAnnotations::class.findMemberProperty("id")?.getDeprecationReason()
4655

4756
assertEquals(expected = "class deprecated", actual = classDeprecation)
4857
assertEquals(expected = "property deprecated", actual = classPropertyDeprecation)
4958
assertNull(NoAnnotations::class.getDeprecationReason())
59+
assertNull(NoAnnotations::class.findMemberProperty("id")?.getDeprecationReason())
5060
}
5161

5262
@Test
@@ -57,9 +67,11 @@ internal class AnnotationExtensionsTest {
5767

5868
@Test
5969
fun `verify @GraphQLID`() {
60-
val id = WithAnnotations::class.declaredMemberProperties.find { it.name == "id" }
61-
val notId = NoAnnotations::class.declaredMemberProperties.find { it.name == "id" }
70+
val id = WithAnnotations::class.findMemberProperty("id")
71+
val notId = NoAnnotations::class.findMemberProperty("id")
6272
assertTrue { id?.isGraphQLID().isTrue() }
6373
assertFalse { notId?.isGraphQLID().isTrue() }
6474
}
75+
76+
private fun KClass<*>.findMemberProperty(name: String) = this.declaredMemberProperties.find { it.name == name }
6577
}

graphql-kotlin-schema-generator/src/test/kotlin/com/expedia/graphql/generator/extensions/KCallableExtensionsKtTest.kt

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

3+
import com.expedia.graphql.annotations.GraphQLName
34
import org.junit.jupiter.api.Test
45
import kotlin.reflect.full.functions
6+
import kotlin.test.assertEquals
57
import kotlin.test.assertFalse
68
import kotlin.test.assertTrue
79

@@ -16,6 +18,9 @@ internal class KCallableExtensionsKtTest {
1618
internal fun internal() = 3
1719

1820
private fun private() = 4
21+
22+
@GraphQLName("renamedFunction")
23+
fun originalName() = 1
1924
}
2025

2126
@Test
@@ -25,4 +30,10 @@ internal class KCallableExtensionsKtTest {
2530
assertFalse(MyTestClass::class.functions.find { it.name == "protected" }?.isPublic().isTrue())
2631
assertFalse(MyTestClass::class.functions.find { it.name == "private" }?.isPublic().isTrue())
2732
}
33+
34+
@Test
35+
fun graphQLName() {
36+
assertEquals(expected = "renamedFunction", actual = MyTestClass::originalName.getFunctionName())
37+
assertEquals(expected = "public", actual = MyTestClass::public.getFunctionName())
38+
}
2839
}

graphql-kotlin-schema-generator/src/test/kotlin/com/expedia/graphql/generator/extensions/KPropertyExtensionsKtTest.kt

Lines changed: 10 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.test.assertEquals
89
import kotlin.test.assertFalse
@@ -18,12 +19,14 @@ internal class KPropertyExtensionsKtTest {
1819
@property:GraphQLDescription("property description")
1920
@property:GraphQLID
2021
@property:GraphQLIgnore
22+
@property:GraphQLName("nameOnProperty")
2123
val propertyAnnotation: String,
2224

2325
@Deprecated("constructor deprecated")
2426
@GraphQLDescription("constructor description")
2527
@GraphQLID
2628
@GraphQLIgnore
29+
@GraphQLName("nameOnConstructor")
2730
val constructorAnnotation: String,
2831

2932
val noAnnotations: String
@@ -56,4 +59,11 @@ internal class KPropertyExtensionsKtTest {
5659
assertEquals("constructor description", MyDataClass::constructorAnnotation.getPropertyDescription(MyDataClass::class))
5760
assertEquals(null, MyDataClass::noAnnotations.getPropertyDescription(MyDataClass::class))
5861
}
62+
63+
@Test
64+
fun getPropertyName() {
65+
assertEquals("nameOnProperty", MyDataClass::propertyAnnotation.getPropertyName(MyDataClass::class))
66+
assertEquals("nameOnConstructor", MyDataClass::constructorAnnotation.getPropertyName(MyDataClass::class))
67+
assertEquals("noAnnotations", MyDataClass::noAnnotations.getPropertyName(MyDataClass::class))
68+
}
5969
}

graphql-kotlin-schema-generator/src/test/kotlin/com/expedia/graphql/generator/types/FunctionBuilderTest.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.expedia.graphql.annotations.GraphQLContext
44
import com.expedia.graphql.annotations.GraphQLDescription
55
import com.expedia.graphql.annotations.GraphQLDirective
66
import com.expedia.graphql.annotations.GraphQLIgnore
7+
import com.expedia.graphql.annotations.GraphQLName
78
import com.expedia.graphql.execution.FunctionDataFetcher
89
import graphql.Scalars
910
import graphql.introspection.Introspection
@@ -52,6 +53,9 @@ internal class FunctionBuilderTest : TypeTestHelper() {
5253
@Deprecated("Should paint instead")
5354
fun sketch(tree: String) = tree
5455

56+
@GraphQLName("renamedFunction")
57+
fun originalName(input: String) = input
58+
5559
@Deprecated("No saw, just paint", replaceWith = ReplaceWith("paint"))
5660
fun saw(tree: String) = tree
5761

@@ -94,6 +98,13 @@ internal class FunctionBuilderTest : TypeTestHelper() {
9498
assertEquals("deprecated", fieldDirectives.first().name)
9599
}
96100

101+
@Test
102+
fun `test changing the name of a function`() {
103+
val kFunction = Happy::originalName
104+
val result = builder.function(kFunction, "Query")
105+
assertEquals("renamedFunction", result.name)
106+
}
107+
97108
@Test
98109
fun `test deprecation with replacement`() {
99110
val kFunction = Happy::saw

0 commit comments

Comments
 (0)