Skip to content

Commit

Permalink
407 make FieldResolverScanner prefer concrete methods over interface …
Browse files Browse the repository at this point in the history
…methods
  • Loading branch information
vojtapol committed Jul 16, 2020
1 parent 7b31d5e commit 647885c
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import graphql.schema.DataFetchingEnvironment
import org.apache.commons.lang3.ClassUtils
import org.apache.commons.lang3.reflect.FieldUtils
import org.slf4j.LoggerFactory
import java.lang.reflect.Method
import java.lang.reflect.Modifier
import java.lang.reflect.Type
import kotlin.reflect.full.valueParameters
Expand Down Expand Up @@ -93,17 +94,20 @@ internal class FieldResolverScanner(val options: SchemaParserOptions) {
}
}

private fun getAllMethods(type: JavaType) =
(type.unwrap().declaredNonProxyMethods.toList()
+ ClassUtils.getAllInterfaces(type.unwrap()).flatMap { it.methods.toList() }
+ ClassUtils.getAllSuperclasses(type.unwrap()).flatMap { it.methods.toList() })
private fun getAllMethods(type: JavaType): List<Method> {
val declaredMethods = type.unwrap().declaredNonProxyMethods
val superClassesMethods = ClassUtils.getAllSuperclasses(type.unwrap()).flatMap { it.methods.toList() }
val interfacesMethods = ClassUtils.getAllInterfaces(type.unwrap()).flatMap { it.methods.toList() }

return (declaredMethods + superClassesMethods + interfacesMethods)
.asSequence()
.filter { !it.isSynthetic }
.filter { !Modifier.isPrivate(it.modifiers) }
// discard any methods that are coming off the root of the class hierarchy
// to avoid issues with duplicate method declarations
.filter { it.declaringClass != Object::class.java }
.toList()
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,18 @@ class FieldResolverScannerSpec extends Specification {
users instanceof MethodFieldResolver
}

def "scanner prefers concrete resolver"() {
setup:
def resolver = new DataClassResolverInfo(Kayak.class)

when:
def meta = scanner.findFieldResolver(new FieldDefinition("information", new TypeName("VehicleInformation")), resolver)

then:
meta instanceof MethodFieldResolver
((MethodFieldResolver) meta).getMethod().getReturnType() == BoatInformation.class
}

class RootQuery1 implements GraphQLQueryResolver {
def field1() {}
}
Expand All @@ -95,11 +107,17 @@ class FieldResolverScannerSpec extends Specification {
private String name = "name"
}

class User {

}
class User {}

class GenericQuery implements GraphQLQueryResolver {
Connection<User> getUsers() {}
}

abstract class Boat implements Vehicle {
BoatInformation getInformation() { return this.information; }
}

class BoatInformation implements VehicleInformation {}

class Kayak extends Boat {}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package graphql.kickstart.tools

interface Animal {

SchemaClassScannerSpec.NestedInterfaceTypeQuery.ComplexType type()
}

interface Vehicle {
VehicleInformation getInformation();
}

interface VehicleInformation {}

0 comments on commit 647885c

Please sign in to comment.