Skip to content

Commit 0e4b8a9

Browse files
authored
Merge pull request #337 from cliedeman/trivial-dataloader
fix #336
2 parents a5db848 + f78a312 commit 0e4b8a9

File tree

4 files changed

+78
-1
lines changed

4 files changed

+78
-1
lines changed

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

Lines changed: 11 additions & 1 deletion
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
@@ -116,7 +117,12 @@ internal class MethodFieldResolver(field: FieldDefinition, search: FieldResolver
116117
return if (batched) {
117118
BatchedMethodFieldResolverDataFetcher(getSourceResolver(), this.method, args, options)
118119
} else {
119-
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+
120126
}
121127
}
122128

@@ -223,6 +229,10 @@ open class MethodFieldResolverDataFetcher(private val sourceResolver: SourceReso
223229
}
224230
}
225231

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+
226236
private suspend inline fun MethodAccess.invokeSuspend(target: Any, methodIndex: Int, args: Array<Any?>): Any? {
227237
return suspendCoroutineUninterceptedOrReturn { continuation ->
228238
invoke(target, methodIndex, *args + continuation)

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import graphql.language.NonNullType
66
import graphql.language.ObjectTypeDefinition
77
import graphql.language.ObjectTypeExtensionDefinition
88
import graphql.language.Type
9+
import java.lang.reflect.Method
910
import java.lang.reflect.ParameterizedType
1011

1112
/**
@@ -33,3 +34,21 @@ internal fun JavaType.unwrap(): Class<out Any> =
3334
} else {
3435
this as Class<*>
3536
}
37+
38+
/**
39+
* Simple heuristic to check is a method is a trivial data fetcher.
40+
*
41+
* Requirements are:
42+
* prefixed with get
43+
* must have zero parameters
44+
*/
45+
internal fun isTrivialDataFetcher(method: Method): Boolean {
46+
return (method.parameterCount == 0
47+
&& (
48+
method.name.startsWith("get")
49+
|| isBooleanGetter(method)))
50+
}
51+
52+
private fun isBooleanGetter(method: Method) = (method.name.startsWith("is")
53+
&& (method.returnType == java.lang.Boolean::class.java)
54+
|| 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)