Skip to content

Commit 647885c

Browse files
committed
407 make FieldResolverScanner prefer concrete methods over interface methods
1 parent 7b31d5e commit 647885c

File tree

3 files changed

+34
-8
lines changed

3 files changed

+34
-8
lines changed

src/main/kotlin/graphql/kickstart/tools/resolver/FieldResolverScanner.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import graphql.schema.DataFetchingEnvironment
1414
import org.apache.commons.lang3.ClassUtils
1515
import org.apache.commons.lang3.reflect.FieldUtils
1616
import org.slf4j.LoggerFactory
17+
import java.lang.reflect.Method
1718
import java.lang.reflect.Modifier
1819
import java.lang.reflect.Type
1920
import kotlin.reflect.full.valueParameters
@@ -93,17 +94,20 @@ internal class FieldResolverScanner(val options: SchemaParserOptions) {
9394
}
9495
}
9596

96-
private fun getAllMethods(type: JavaType) =
97-
(type.unwrap().declaredNonProxyMethods.toList()
98-
+ ClassUtils.getAllInterfaces(type.unwrap()).flatMap { it.methods.toList() }
99-
+ ClassUtils.getAllSuperclasses(type.unwrap()).flatMap { it.methods.toList() })
97+
private fun getAllMethods(type: JavaType): List<Method> {
98+
val declaredMethods = type.unwrap().declaredNonProxyMethods
99+
val superClassesMethods = ClassUtils.getAllSuperclasses(type.unwrap()).flatMap { it.methods.toList() }
100+
val interfacesMethods = ClassUtils.getAllInterfaces(type.unwrap()).flatMap { it.methods.toList() }
101+
102+
return (declaredMethods + superClassesMethods + interfacesMethods)
100103
.asSequence()
101104
.filter { !it.isSynthetic }
102105
.filter { !Modifier.isPrivate(it.modifiers) }
103106
// discard any methods that are coming off the root of the class hierarchy
104107
// to avoid issues with duplicate method declarations
105108
.filter { it.declaringClass != Object::class.java }
106109
.toList()
110+
}
107111

108112
private fun isBoolean(type: GraphQLLangType) = type.unwrap().let { it is TypeName && it.name == Scalars.GraphQLBoolean.name }
109113

src/test/groovy/graphql/kickstart/tools/FieldResolverScannerSpec.groovy

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,18 @@ class FieldResolverScannerSpec extends Specification {
7575
users instanceof MethodFieldResolver
7676
}
7777

78+
def "scanner prefers concrete resolver"() {
79+
setup:
80+
def resolver = new DataClassResolverInfo(Kayak.class)
81+
82+
when:
83+
def meta = scanner.findFieldResolver(new FieldDefinition("information", new TypeName("VehicleInformation")), resolver)
84+
85+
then:
86+
meta instanceof MethodFieldResolver
87+
((MethodFieldResolver) meta).getMethod().getReturnType() == BoatInformation.class
88+
}
89+
7890
class RootQuery1 implements GraphQLQueryResolver {
7991
def field1() {}
8092
}
@@ -95,11 +107,17 @@ class FieldResolverScannerSpec extends Specification {
95107
private String name = "name"
96108
}
97109

98-
class User {
99-
100-
}
110+
class User {}
101111

102112
class GenericQuery implements GraphQLQueryResolver {
103113
Connection<User> getUsers() {}
104114
}
115+
116+
abstract class Boat implements Vehicle {
117+
BoatInformation getInformation() { return this.information; }
118+
}
119+
120+
class BoatInformation implements VehicleInformation {}
121+
122+
class Kayak extends Boat {}
105123
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package graphql.kickstart.tools
22

33
interface Animal {
4-
54
SchemaClassScannerSpec.NestedInterfaceTypeQuery.ComplexType type()
5+
}
66

7+
interface Vehicle {
8+
VehicleInformation getInformation();
79
}
10+
11+
interface VehicleInformation {}

0 commit comments

Comments
 (0)