Skip to content

Commit 2b88d2d

Browse files
smyrickdariuszkuc
authored andcommitted
feat: standardize casting of GraphQLType (#167)
* feat: standardize casting of GraphQLType * test: use junit as test annotation * test: simplify unit tests * test: move unit tests * test: fix recursive types that had a self reference * feat: log casting class
1 parent 9f427ef commit 2b88d2d

26 files changed

+108
-35
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.expedia.graphql.exceptions
2+
3+
import graphql.schema.GraphQLType
4+
import kotlin.reflect.KClass
5+
6+
/**
7+
* Thrown when the casting a GraphQLType to some parent type is invalid
8+
*/
9+
class CouldNotCastGraphQLType(type: GraphQLType, kClass: KClass<*>)
10+
: GraphQLKotlinException("Could not cast GraphQLType $type to $kClass")

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

Lines changed: 7 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.exceptions.CouldNotCastGraphQLType
34
import com.expedia.graphql.exceptions.NestingNonNullTypeException
45
import graphql.schema.GraphQLArgument
56
import graphql.schema.GraphQLDirective
@@ -30,6 +31,12 @@ internal fun GraphQLType.wrapInNonNull(type: KType): GraphQLType = when {
3031
else -> GraphQLNonNull.nonNull(this)
3132
}
3233

34+
@Throws(CouldNotCastGraphQLType::class)
35+
internal inline fun <reified T : GraphQLType> GraphQLType.safeCast(): T {
36+
if (this !is T) throw CouldNotCastGraphQLType(this, T::class)
37+
return this
38+
}
39+
3340
internal fun GraphQLDirectiveContainer.getAllDirectives(): List<GraphQLDirective> {
3441
// A function without directives may still be rewired if the arguments have directives
3542
// see https://github.com/ExpediaDotCom/graphql-kotlin/wiki/Schema-Directives for details

src/main/kotlin/com/expedia/graphql/generator/types/DirectiveTypeBuilder.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import com.expedia.graphql.generator.SchemaGenerator
44
import com.expedia.graphql.generator.TypeBuilder
55
import com.expedia.graphql.generator.extensions.getSimpleName
66
import com.expedia.graphql.generator.extensions.getValidProperties
7+
import com.expedia.graphql.generator.extensions.safeCast
78
import com.google.common.base.CaseFormat
89
import graphql.schema.GraphQLArgument
910
import graphql.schema.GraphQLDirective
10-
import graphql.schema.GraphQLInputType
1111
import kotlin.reflect.KAnnotatedElement
1212
import com.expedia.graphql.annotations.GraphQLDirective as GraphQLDirectiveAnnotation
1313

@@ -39,7 +39,7 @@ internal class DirectiveTypeBuilder(generator: SchemaGenerator) : TypeBuilder(ge
3939
val argument = GraphQLArgument.newArgument()
4040
.name(propertyName)
4141
.value(value)
42-
.type(type as? GraphQLInputType)
42+
.type(type.safeCast())
4343
.build()
4444

4545
builder.argument(argument)

src/main/kotlin/com/expedia/graphql/generator/types/FunctionTypeBuilder.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import com.expedia.graphql.generator.extensions.getName
99
import com.expedia.graphql.generator.extensions.getTypeOfFirstArgument
1010
import com.expedia.graphql.generator.extensions.isGraphQLContext
1111
import com.expedia.graphql.generator.extensions.isInterface
12+
import com.expedia.graphql.generator.extensions.safeCast
1213
import graphql.schema.GraphQLArgument
1314
import graphql.schema.GraphQLFieldDefinition
14-
import graphql.schema.GraphQLInputType
1515
import graphql.schema.GraphQLOutputType
1616
import java.util.concurrent.CompletableFuture
1717
import kotlin.reflect.KFunction
@@ -48,10 +48,10 @@ internal class FunctionTypeBuilder(generator: SchemaGenerator) : TypeBuilder(gen
4848

4949
val typeFromHooks = config.hooks.willResolveMonad(fn.returnType)
5050
val returnType = getWrappedReturnType(typeFromHooks)
51-
builder.type(graphQLTypeOf(returnType) as GraphQLOutputType)
51+
builder.type(graphQLTypeOf(returnType).safeCast<GraphQLOutputType>())
5252
val graphQLType = builder.build()
5353

54-
return config.hooks.onRewireGraphQLType(returnType, graphQLType) as GraphQLFieldDefinition
54+
return config.hooks.onRewireGraphQLType(returnType, graphQLType).safeCast()
5555
}
5656

5757
private fun getWrappedReturnType(returnType: KType): KType =
@@ -70,12 +70,12 @@ internal class FunctionTypeBuilder(generator: SchemaGenerator) : TypeBuilder(gen
7070
val builder = GraphQLArgument.newArgument()
7171
.name(parameter.getName())
7272
.description(parameter.getGraphQLDescription())
73-
.type(graphQLTypeOf(parameter.type, true) as GraphQLInputType)
73+
.type(graphQLTypeOf(parameter.type, true).safeCast())
7474

7575
generator.directives(parameter).forEach {
7676
builder.withDirective(it)
7777
}
7878

79-
return config.hooks.onRewireGraphQLType(parameter.type, builder.build()) as GraphQLArgument
79+
return config.hooks.onRewireGraphQLType(parameter.type, builder.build()).safeCast()
8080
}
8181
}

src/main/kotlin/com/expedia/graphql/generator/types/InputObjectTypeBuilder.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import com.expedia.graphql.generator.extensions.getPropertyDescription
77
import com.expedia.graphql.generator.extensions.getSimpleName
88
import com.expedia.graphql.generator.extensions.getValidProperties
99
import com.expedia.graphql.generator.extensions.isPropertyGraphQLID
10+
import com.expedia.graphql.generator.extensions.safeCast
1011
import graphql.schema.GraphQLInputObjectField
1112
import graphql.schema.GraphQLInputObjectType
1213
import graphql.schema.GraphQLInputType
@@ -32,7 +33,7 @@ internal class InputObjectTypeBuilder(generator: SchemaGenerator) : TypeBuilder(
3233

3334
builder.description(prop.getPropertyDescription(parentClass))
3435
builder.name(prop.name)
35-
builder.type(graphQLTypeOf(prop.returnType, true, prop.isPropertyGraphQLID(parentClass)) as? GraphQLInputType)
36+
builder.type(graphQLTypeOf(prop.returnType, true, prop.isPropertyGraphQLID(parentClass)).safeCast<GraphQLInputType>())
3637

3738
return builder.build()
3839
}

src/main/kotlin/com/expedia/graphql/generator/types/InterfaceTypeBuilder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import kotlin.reflect.KClass
1414

1515
internal class InterfaceTypeBuilder(generator: SchemaGenerator) : TypeBuilder(generator) {
1616
internal fun interfaceType(kClass: KClass<*>): GraphQLType {
17-
return state.cache.buildIfNotUnderConstruction(kClass) { _ ->
17+
return state.cache.buildIfNotUnderConstruction(kClass) {
1818
val builder = GraphQLInterfaceType.newInterface()
1919

2020
builder.name(kClass.getSimpleName())

src/main/kotlin/com/expedia/graphql/generator/types/ObjectTypeBuilder.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import kotlin.reflect.full.createType
1616
internal class ObjectTypeBuilder(generator: SchemaGenerator) : TypeBuilder(generator) {
1717

1818
internal fun objectType(kClass: KClass<*>, interfaceType: GraphQLInterfaceType? = null): GraphQLType {
19-
return state.cache.buildIfNotUnderConstruction(kClass) { _ ->
19+
return state.cache.buildIfNotUnderConstruction(kClass) {
2020
val builder = GraphQLObjectType.newObject()
2121

2222
builder.name(kClass.getSimpleName())
@@ -30,8 +30,12 @@ internal class ObjectTypeBuilder(generator: SchemaGenerator) : TypeBuilder(gener
3030
builder.withInterface(interfaceType)
3131
} else {
3232
kClass.getValidSuperclasses(config.hooks)
33-
.mapNotNull { objectFromReflection(it.createType(), false) as? GraphQLInterfaceType }
34-
.forEach { builder.withInterface(it) }
33+
.map { objectFromReflection(it.createType(), false) }
34+
.forEach {
35+
when (it) {
36+
is GraphQLInterfaceType -> builder.withInterface(it)
37+
}
38+
}
3539
}
3640

3741
kClass.getValidProperties(config.hooks)

src/main/kotlin/com/expedia/graphql/generator/types/PropertyTypeBuilder.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.expedia.graphql.generator.TypeBuilder
55
import com.expedia.graphql.generator.extensions.getPropertyDeprecationReason
66
import com.expedia.graphql.generator.extensions.getPropertyDescription
77
import com.expedia.graphql.generator.extensions.isPropertyGraphQLID
8+
import com.expedia.graphql.generator.extensions.safeCast
89
import graphql.schema.GraphQLFieldDefinition
910
import graphql.schema.GraphQLOutputType
1011
import kotlin.reflect.KClass
@@ -13,7 +14,8 @@ import kotlin.reflect.KProperty
1314
@Suppress("Detekt.UnsafeCast")
1415
internal class PropertyTypeBuilder(generator: SchemaGenerator) : TypeBuilder(generator) {
1516
internal fun property(prop: KProperty<*>, parentClass: KClass<*>): GraphQLFieldDefinition {
16-
val propertyType = graphQLTypeOf(type = prop.returnType, annotatedAsID = prop.isPropertyGraphQLID(parentClass)) as GraphQLOutputType
17+
val propertyType = graphQLTypeOf(type = prop.returnType, annotatedAsID = prop.isPropertyGraphQLID(parentClass))
18+
.safeCast<GraphQLOutputType>()
1719

1820
val fieldBuilder = GraphQLFieldDefinition.newFieldDefinition()
1921
.description(prop.getPropertyDescription(parentClass))
@@ -27,6 +29,7 @@ internal class PropertyTypeBuilder(generator: SchemaGenerator) : TypeBuilder(gen
2729
}
2830

2931
val field = fieldBuilder.build()
30-
return config.hooks.onRewireGraphQLType(prop.returnType, field) as GraphQLFieldDefinition
32+
33+
return config.hooks.onRewireGraphQLType(prop.returnType, field).safeCast()
3134
}
3235
}

src/main/kotlin/com/expedia/graphql/generator/types/UnionTypeBuilder.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import kotlin.reflect.full.createType
1616

1717
internal class UnionTypeBuilder(generator: SchemaGenerator) : TypeBuilder(generator) {
1818
internal fun unionType(kClass: KClass<*>): GraphQLType {
19-
return state.cache.buildIfNotUnderConstruction(kClass) { _ ->
19+
return state.cache.buildIfNotUnderConstruction(kClass) {
2020
val builder = GraphQLUnionType.newUnionType()
2121

2222
builder.name(kClass.getSimpleName())
@@ -30,10 +30,9 @@ internal class UnionTypeBuilder(generator: SchemaGenerator) : TypeBuilder(genera
3030

3131
val key = TypesCacheKey(it.kotlin.createType(), false)
3232

33-
if (objectType is GraphQLTypeReference) {
34-
builder.possibleType(objectType)
35-
} else {
36-
builder.possibleType(objectType as? GraphQLObjectType)
33+
when (objectType) {
34+
is GraphQLTypeReference -> builder.possibleType(objectType)
35+
is GraphQLObjectType -> builder.possibleType(objectType)
3736
}
3837

3938
if (state.cache.doesNotContain(it.kotlin)) {

src/test/kotlin/com/expedia/graphql/DirectiveWiringHelperTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import graphql.schema.idl.SchemaDirectiveWiringEnvironment
1515
import graphql.schema.idl.WiringFactory
1616
import graphql.util.TraversalControl
1717
import graphql.util.TraverserContext
18-
import kotlin.test.Test
18+
import org.junit.jupiter.api.Test
1919
import kotlin.test.assertEquals
2020
import kotlin.test.assertFailsWith
2121
import kotlin.test.assertNotEquals

0 commit comments

Comments
 (0)