Skip to content

Commit c9f83c9

Browse files
smyrickbrennantaylor
authored andcommitted
refactor: move more functions out of SchemaGenerator (#48)
1 parent 542f6db commit c9f83c9

File tree

8 files changed

+72
-39
lines changed

8 files changed

+72
-39
lines changed

detekt_baseline.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22
<SmellBaseline>
33
<Blacklist timestamp="1538767296980"></Blacklist>
44
<Whitelist timestamp="1538768092037">
5-
<ID>FunctionMaxLength:SchemaGenerator.kt$SchemaGenerator$@Throws(InvalidInputFieldTypeException::class) private fun throwIfInterfaceIsNotAuthorized(parameter: KParameter)</ID>
65
<ID>FunctionOnlyReturningConstant:DirectiveTests.kt$Geography$@DirectiveOnFunction fun somethingCool(): String</ID>
76
<ID>LargeClass:SchemaGenerator.kt$SchemaGenerator</ID>
87
<ID>MethodOverloading:SchemaGeneratorTest.kt$SchemaGeneratorTest</ID>
98
<ID>SpreadOperator:annotationExtensions.kt$(*directiveInfo.locations)</ID>
109
<ID>TooManyFunctions:SchemaGenerator.kt$SchemaGenerator</ID>
1110
<ID>UnsafeCallOnNullableType:SchemaGenerator.kt$SchemaGenerator$name!!</ID>
12-
<ID>UnsafeCallOnNullableType:SchemaGenerator.kt$SchemaGenerator$type.arguments.first().type!!</ID>
1311
<ID>UnsafeCast:SchemaGeneratorAsyncTests.kt$SchemaGeneratorAsyncTests$schema.getObjectType("TopLevelQuery").getFieldDefinition("asynchronouslyDo").type as GraphQLNonNull</ID>
1412
<ID>UnsafeCast:SchemaGeneratorAsyncTests.kt$SchemaGeneratorAsyncTests$schema.getObjectType("TopLevelQuery").getFieldDefinition("asynchronouslyDoSingle").type as GraphQLNonNull</ID>
1513
<ID>UnsafeCast:SchemaGeneratorAsyncTests.kt$SchemaGeneratorAsyncTests$schema.getObjectType("TopLevelQuery").getFieldDefinition("maybe").type as GraphQLNonNull</ID>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.expedia.graphql.schema.exceptions
2+
3+
import kotlin.reflect.KType
4+
5+
/**
6+
* Thrown on mapping an invalid list type
7+
*/
8+
class InvalidListTypeException(type: KType)
9+
: RuntimeException("Could not get the type of the first argument for the list $type")

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

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

3-
import com.expedia.graphql.annotations.GraphQLContext
43
import com.expedia.graphql.annotations.GraphQLDescription
54
import com.expedia.graphql.annotations.GraphQLIgnore
65
import com.expedia.graphql.schema.exceptions.CouldNotGetNameOfAnnotationException
@@ -12,8 +11,6 @@ import graphql.schema.GraphQLDirective
1211
import graphql.schema.GraphQLInputType
1312
import kotlin.reflect.KAnnotatedElement
1413
import kotlin.reflect.KClass
15-
import kotlin.reflect.KParameter
16-
import kotlin.reflect.KType
1714
import kotlin.reflect.full.declaredMemberFunctions
1815
import kotlin.reflect.full.findAnnotation
1916
import com.expedia.graphql.annotations.GraphQLDirective as DirectiveAnnotation
@@ -50,8 +47,6 @@ private fun KAnnotatedElement.listOfDirectives(): List<String> {
5047
return directiveNames.filterNotNull()
5148
}
5249

53-
internal fun KType.graphQLDescription(): String? = (classifier as? KClass<*>)?.graphQLDescription()
54-
5550
internal fun KAnnotatedElement.getDeprecationReason(): String? {
5651
val annotation = this.findAnnotation<Deprecated>() ?: return null
5752
val builder = StringBuilder()
@@ -95,6 +90,4 @@ internal fun KAnnotatedElement.directives() =
9590
}
9691
}
9792

98-
internal fun KParameter.isGraphQLContext() = this.findAnnotation<GraphQLContext>() != null
99-
10093
private fun String.normalizeDirectiveName() = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, this)

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,8 @@ internal fun KClass<*>.getValidProperties(hooks: SchemaGeneratorHooks) = this.de
1414
internal fun KClass<*>.getValidFunctions(hooks: SchemaGeneratorHooks) = this.declaredMemberFunctions
1515
.filter { hooks.isValidFunction(it) }
1616
.filter { func -> functionFilters.all { it.invoke(func) } }
17+
18+
internal fun KClass<*>.canBeGraphQLInterface(): Boolean = this.java.isInterface
19+
20+
internal fun KClass<*>.canBeGraphQLUnion(): Boolean =
21+
this.canBeGraphQLInterface() && this.declaredMemberProperties.isEmpty() && this.declaredMemberFunctions.isEmpty()
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.expedia.graphql.schema.extensions
2+
3+
import com.expedia.graphql.annotations.GraphQLContext
4+
import com.expedia.graphql.schema.exceptions.InvalidInputFieldTypeException
5+
import kotlin.reflect.KParameter
6+
import kotlin.reflect.full.findAnnotation
7+
import kotlin.reflect.jvm.jvmErasure
8+
9+
@Throws(InvalidInputFieldTypeException::class)
10+
internal fun KParameter.throwIfUnathorizedInterface() {
11+
if (this.type.jvmErasure.java.isInterface) throw InvalidInputFieldTypeException()
12+
}
13+
14+
internal fun KParameter.isGraphQLContext() = this.findAnnotation<GraphQLContext>() != null
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.expedia.graphql.schema.extensions
2+
3+
import com.expedia.graphql.schema.exceptions.InvalidListTypeException
4+
import kotlin.reflect.KClass
5+
import kotlin.reflect.KType
6+
7+
internal fun KType.graphQLDescription(): String? = (classifier as? KClass<*>)?.graphQLDescription()
8+
9+
@Throws(InvalidListTypeException::class)
10+
internal fun KType.getTypeOfFirstArgument(): KType =
11+
this.arguments.first().type ?: throw InvalidListTypeException(this)

src/main/kotlin/com/expedia/graphql/schema/generator/SchemaGenerator.kt

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@ import com.expedia.graphql.TopLevelObjectDef
44
import com.expedia.graphql.schema.KotlinDataFetcher
55
import com.expedia.graphql.schema.Parameter
66
import com.expedia.graphql.schema.SchemaGeneratorConfig
7-
import com.expedia.graphql.schema.exceptions.InvalidInputFieldTypeException
7+
import com.expedia.graphql.schema.extensions.canBeGraphQLInterface
8+
import com.expedia.graphql.schema.extensions.canBeGraphQLUnion
89
import com.expedia.graphql.schema.extensions.directives
910
import com.expedia.graphql.schema.extensions.getDeprecationReason
11+
import com.expedia.graphql.schema.extensions.getTypeOfFirstArgument
1012
import com.expedia.graphql.schema.extensions.getValidFunctions
1113
import com.expedia.graphql.schema.extensions.getValidProperties
1214
import com.expedia.graphql.schema.extensions.graphQLDescription
1315
import com.expedia.graphql.schema.extensions.isGraphQLContext
16+
import com.expedia.graphql.schema.extensions.throwIfUnathorizedInterface
1417
import com.expedia.graphql.schema.extensions.wrapInNonNull
1518
import com.expedia.graphql.schema.generator.types.defaultGraphQLScalars
1619
import com.expedia.graphql.schema.generator.types.enumType
@@ -26,7 +29,6 @@ import graphql.schema.GraphQLInputObjectType
2629
import graphql.schema.GraphQLInputType
2730
import graphql.schema.GraphQLInterfaceType
2831
import graphql.schema.GraphQLList
29-
import graphql.schema.GraphQLNonNull
3032
import graphql.schema.GraphQLObjectType
3133
import graphql.schema.GraphQLOutputType
3234
import graphql.schema.GraphQLSchema
@@ -39,13 +41,10 @@ import kotlin.reflect.KParameter
3941
import kotlin.reflect.KProperty
4042
import kotlin.reflect.KType
4143
import kotlin.reflect.full.createType
42-
import kotlin.reflect.full.declaredMemberFunctions
43-
import kotlin.reflect.full.declaredMemberProperties
4444
import kotlin.reflect.full.isSubclassOf
4545
import kotlin.reflect.full.superclasses
4646
import kotlin.reflect.full.valueParameters
4747
import kotlin.reflect.jvm.javaType
48-
import kotlin.reflect.jvm.jvmErasure
4948

5049
@Suppress("Detekt.UnsafeCast")
5150
internal class SchemaGenerator(
@@ -84,6 +83,7 @@ internal class SchemaGenerator(
8483
private fun addQueries(builder: GraphQLSchema.Builder) {
8584
val queryBuilder = GraphQLObjectType.Builder()
8685
queryBuilder.name(config.topLevelQueryName)
86+
8787
for (query in queries) {
8888
query.klazz.getValidFunctions(config.hooks)
8989
.forEach {
@@ -92,6 +92,7 @@ internal class SchemaGenerator(
9292
queryBuilder.field(functionFromHook)
9393
}
9494
}
95+
9596
builder.query(queryBuilder.build())
9697
}
9798

@@ -117,6 +118,7 @@ internal class SchemaGenerator(
117118
val builder = GraphQLFieldDefinition.newFieldDefinition()
118119
builder.name(fn.name)
119120
builder.description(fn.graphQLDescription())
121+
120122
fn.getDeprecationReason()?.let {
121123
builder.deprecate(it)
122124
}
@@ -163,23 +165,14 @@ internal class SchemaGenerator(
163165
.deprecate(prop.getDeprecationReason())
164166

165167
return if (config.dataFetcherFactory != null && prop.isLateinit) {
166-
updatePropertyFieldBuilder(propertyType, fieldBuilder)
168+
updatePropertyFieldBuilder(propertyType, fieldBuilder, config.dataFetcherFactory)
167169
} else {
168170
fieldBuilder
169171
}.build()
170172
}
171173

172-
private fun updatePropertyFieldBuilder(propertyType: GraphQLOutputType, fieldBuilder: GraphQLFieldDefinition.Builder): GraphQLFieldDefinition.Builder {
173-
val updatedFieldBuilder = if (propertyType is GraphQLNonNull) {
174-
fieldBuilder.type(propertyType.wrappedType as GraphQLOutputType)
175-
} else {
176-
fieldBuilder
177-
}
178-
return updatedFieldBuilder.dataFetcherFactory(config.dataFetcherFactory)
179-
}
180-
181174
private fun argument(parameter: KParameter): GraphQLArgument {
182-
throwIfInterfaceIsNotAuthorized(parameter)
175+
parameter.throwIfUnathorizedInterface()
183176
return GraphQLArgument.newArgument()
184177
.name(parameter.name)
185178
.description(parameter.graphQLDescription() ?: parameter.type.graphQLDescription())
@@ -220,21 +213,11 @@ internal class SchemaGenerator(
220213
else -> if (inputType) inputObjectType(kClass) else objectType(kClass)
221214
}
222215

223-
private fun KClass<*>.canBeGraphQLInterface(): Boolean = this.java.isInterface
224-
225-
private fun KClass<*>.canBeGraphQLUnion(): Boolean =
226-
this.canBeGraphQLInterface() && this.declaredMemberProperties.isEmpty() && this.declaredMemberFunctions.isEmpty()
227-
228-
@Throws(InvalidInputFieldTypeException::class)
229-
private fun throwIfInterfaceIsNotAuthorized(parameter: KParameter) {
230-
if (parameter.type.jvmErasure.java.isInterface) throw InvalidInputFieldTypeException()
231-
}
232-
233216
private fun listType(type: KType, inputType: Boolean): GraphQLList =
234-
GraphQLList.list(graphQLTypeOf(type.arguments.first().type!!, inputType))
217+
GraphQLList.list(graphQLTypeOf(type.getTypeOfFirstArgument(), inputType))
235218

236219
private fun objectType(kClass: KClass<*>, interfaceType: GraphQLInterfaceType? = null): GraphQLType {
237-
return cache.buildIfNotUnderConstruction(kClass) {
220+
return cache.buildIfNotUnderConstruction(kClass) { _ ->
238221
val builder = GraphQLObjectType.newObject()
239222

240223
builder.name(kClass.simpleName)
@@ -290,7 +273,7 @@ internal class SchemaGenerator(
290273
}
291274

292275
private fun interfaceType(kClass: KClass<*>): GraphQLType {
293-
return cache.buildIfNotUnderConstruction(kClass) {
276+
return cache.buildIfNotUnderConstruction(kClass) { _ ->
294277
val builder = GraphQLInterfaceType.newInterface()
295278

296279
builder.name(kClass.simpleName)
@@ -311,6 +294,7 @@ internal class SchemaGenerator(
311294
.forEach {
312295
val objectType = objectType(it.kotlin, interfaceType)
313296
val key = TypesCacheKey(it.kotlin.createType(), false)
297+
314298
additionTypes.add(objectType)
315299
cache.put(key, KGraphQLType(it.kotlin, objectType))
316300
}
@@ -320,7 +304,7 @@ internal class SchemaGenerator(
320304
}
321305

322306
private fun unionType(kClass: KClass<*>): GraphQLType {
323-
return cache.buildIfNotUnderConstruction(kClass) {
307+
return cache.buildIfNotUnderConstruction(kClass) { _ ->
324308
val builder = GraphQLUnionType.newUnionType()
325309

326310
builder.name(kClass.simpleName)
@@ -333,11 +317,13 @@ internal class SchemaGenerator(
333317
.forEach {
334318
val objectType = objectType(it.kotlin)
335319
val key = TypesCacheKey(it.kotlin.createType(), false)
320+
336321
if (objectType is GraphQLTypeReference) {
337322
builder.possibleType(objectType)
338323
} else {
339324
builder.possibleType(objectType as GraphQLObjectType)
340325
}
326+
341327
cache.put(key, KGraphQLType(it.kotlin, objectType))
342328
}
343329

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.expedia.graphql.schema.generator
2+
3+
import graphql.schema.DataFetcherFactory
4+
import graphql.schema.GraphQLFieldDefinition
5+
import graphql.schema.GraphQLNonNull
6+
import graphql.schema.GraphQLOutputType
7+
8+
internal fun updatePropertyFieldBuilder(propertyType: GraphQLOutputType, fieldBuilder: GraphQLFieldDefinition.Builder, dataFetcherFactory: DataFetcherFactory<*>?): GraphQLFieldDefinition.Builder {
9+
val updatedFieldBuilder = if (propertyType is GraphQLNonNull) {
10+
val graphQLOutputType = propertyType.wrappedType as? GraphQLOutputType
11+
if (graphQLOutputType != null) fieldBuilder.type(graphQLOutputType) else fieldBuilder
12+
} else {
13+
fieldBuilder
14+
}
15+
16+
return updatedFieldBuilder.dataFetcherFactory(dataFetcherFactory)
17+
}

0 commit comments

Comments
 (0)