Skip to content

Commit be99494

Browse files
authored
Merge branch 'master' into environment-coroutine-scope
2 parents de09f34 + 0e4b8a9 commit be99494

File tree

4 files changed

+86
-5
lines changed

4 files changed

+86
-5
lines changed

src/main/kotlin/com/coxautodev/graphql/tools/MethodFieldResolver.kt

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.coxautodev.graphql.tools
33
import com.coxautodev.graphql.tools.SchemaParserOptions.GenericWrapper
44
import com.esotericsoftware.reflectasm.MethodAccess
55
import com.fasterxml.jackson.core.type.TypeReference
6+
import graphql.TrivialDataFetcher
67
import graphql.execution.batched.Batched
78
import graphql.language.FieldDefinition
89
import graphql.language.ListType
@@ -11,7 +12,8 @@ import graphql.language.Type
1112
import graphql.language.TypeName
1213
import graphql.schema.DataFetcher
1314
import graphql.schema.DataFetchingEnvironment
14-
import graphql.schema.GraphQLTypeUtil.isScalar
15+
import graphql.schema.GraphQLTypeUtil.*
16+
import kotlinx.coroutines.GlobalScope
1517
import kotlinx.coroutines.future.future
1618
import java.lang.reflect.Method
1719
import java.util.Comparator
@@ -115,17 +117,24 @@ internal class MethodFieldResolver(field: FieldDefinition, search: FieldResolver
115117
return if (batched) {
116118
BatchedMethodFieldResolverDataFetcher(getSourceResolver(), this.method, args, options)
117119
} else {
118-
MethodFieldResolverDataFetcher(getSourceResolver(), this.method, args, options)
120+
if (args.isEmpty() && isTrivialDataFetcher(this.method)) {
121+
TrivialMethodFieldResolverDataFetcher(getSourceResolver(), this.method, args, options)
122+
} else {
123+
MethodFieldResolverDataFetcher(getSourceResolver(), this.method, args, options)
124+
}
125+
119126
}
120127
}
121128

122129
private fun isScalarType(environment: DataFetchingEnvironment, type: Type<*>, genericParameterType: JavaType): Boolean =
123-
when (type) {
124-
is ListType ->
130+
when {
131+
type is ListType ->
125132
List::class.java.isAssignableFrom(this.genericType.getRawClass(genericParameterType))
126133
&& isScalarType(environment, type.type, this.genericType.unwrapGenericType(genericParameterType))
127-
is TypeName ->
134+
type is TypeName ->
128135
environment.graphQLSchema?.getType(type.name)?.let { isScalar(it) } ?: false
136+
type is NonNullType && type.type is TypeName ->
137+
environment.graphQLSchema?.getType((type.type as TypeName).name)?.let { isScalar(unwrapNonNull(it)) } ?: false
129138
else ->
130139
false
131140
}
@@ -220,6 +229,10 @@ open class MethodFieldResolverDataFetcher(private val sourceResolver: SourceReso
220229
}
221230
}
222231

232+
open class TrivialMethodFieldResolverDataFetcher(private val sourceResolver: SourceResolver, method: Method, private val args: List<ArgumentPlaceholder>, private val options: SchemaParserOptions) : MethodFieldResolverDataFetcher(sourceResolver, method, args, options), TrivialDataFetcher<Any> {
233+
234+
}
235+
223236
private suspend inline fun MethodAccess.invokeSuspend(target: Any, methodIndex: Int, args: Array<Any?>): Any? {
224237
return suspendCoroutineUninterceptedOrReturn { continuation ->
225238
invoke(target, methodIndex, *args + continuation)

src/main/kotlin/com/coxautodev/graphql/tools/Utils.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import graphql.language.Type
99
import graphql.schema.DataFetchingEnvironment
1010
import kotlinx.coroutines.CoroutineScope
1111
import kotlinx.coroutines.GlobalScope
12+
import java.lang.reflect.Method
1213
import java.lang.reflect.ParameterizedType
1314

1415
/**
@@ -37,7 +38,26 @@ internal fun JavaType.unwrap(): Class<out Any> =
3738
this as Class<*>
3839
}
3940

41+
4042
internal fun DataFetchingEnvironment.coroutineScope(): CoroutineScope {
4143
val context: Any? = this.getContext()
4244
return if (context is CoroutineScope) context else GlobalScope
4345
}
46+
47+
/**
48+
* Simple heuristic to check is a method is a trivial data fetcher.
49+
*
50+
* Requirements are:
51+
* prefixed with get
52+
* must have zero parameters
53+
*/
54+
internal fun isTrivialDataFetcher(method: Method): Boolean {
55+
return (method.parameterCount == 0
56+
&& (
57+
method.name.startsWith("get")
58+
|| isBooleanGetter(method)))
59+
}
60+
61+
private fun isBooleanGetter(method: Method) = (method.name.startsWith("is")
62+
&& (method.returnType == java.lang.Boolean::class.java)
63+
|| method.returnType == Boolean::class.java)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.coxautodev.graphql.tools;
2+
3+
public class UtilsTestTrivialDataFetcherBean {
4+
5+
public boolean isBooleanPrimitive() {
6+
return false;
7+
}
8+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.coxautodev.graphql.tools
2+
3+
import org.junit.Assert
4+
import org.junit.Test
5+
6+
class UtilsTest {
7+
8+
@Suppress("unused")
9+
class Bean {
10+
fun getterValid(): String = ""
11+
12+
fun getterWithArgument(@Suppress("UNUSED_PARAMETER") arg1: String): String = ""
13+
14+
internal fun getterInternal(): String = ""
15+
16+
fun notAGetter(): String = ""
17+
18+
fun isString(): String = ""
19+
20+
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
21+
fun isJavaBoolean(): java.lang.Boolean = java.lang.Boolean(false)
22+
23+
fun isKotlinBoolean(): Boolean = false
24+
}
25+
26+
@Test
27+
fun `isTrivialDataFetcher`() {
28+
val clazz = Bean::class.java
29+
30+
Assert.assertTrue(isTrivialDataFetcher(clazz.getMethod("getterValid")))
31+
Assert.assertFalse(isTrivialDataFetcher(clazz.getMethod("getterWithArgument", String::class.java)))
32+
Assert.assertFalse(isTrivialDataFetcher(clazz.getMethod("notAGetter")))
33+
34+
Assert.assertFalse(isTrivialDataFetcher(clazz.getMethod("isString")))
35+
Assert.assertTrue(isTrivialDataFetcher(clazz.getMethod("isJavaBoolean")))
36+
Assert.assertTrue(isTrivialDataFetcher(clazz.getMethod("isKotlinBoolean")))
37+
38+
Assert.assertTrue(isTrivialDataFetcher(UtilsTestTrivialDataFetcherBean::class.java.getMethod("isBooleanPrimitive")))
39+
}
40+
}

0 commit comments

Comments
 (0)