From a727ddb0d6e49260a985ddeb9196d803cc600f3f Mon Sep 17 00:00:00 2001 From: Jonathan D'Orleans Date: Fri, 31 Jan 2020 00:27:52 -0500 Subject: [PATCH 1/4] fix unwrapGenericType to properly find generic type in arguments Map --- src/main/kotlin/graphql/kickstart/tools/GenericType.kt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/graphql/kickstart/tools/GenericType.kt b/src/main/kotlin/graphql/kickstart/tools/GenericType.kt index 60a58454..7615ff54 100644 --- a/src/main/kotlin/graphql/kickstart/tools/GenericType.kt +++ b/src/main/kotlin/graphql/kickstart/tools/GenericType.kt @@ -121,9 +121,13 @@ internal open class GenericType(protected val mostSpecificType: JavaType, protec } } - private fun unwrapGenericType(declaringType: ParameterizedType, type: TypeVariable<*>) = - unwrapGenericType(TypeUtils.determineTypeArguments(getRawClass(mostSpecificType), declaringType)[type] - ?: error("No type variable found for: ${TypeUtils.toLongString(type)}")) + private fun unwrapGenericType(declaringType: ParameterizedType, type: TypeVariable<*>): JavaType { + val rawClass = getRawClass(mostSpecificType) + val arguments = TypeUtils.determineTypeArguments(rawClass, declaringType) + val t = arguments.filter { it.key.name == type.name }.values.firstOrNull() + ?: error("No type variable found for: ${TypeUtils.toLongString(type)}") + return unwrapGenericType(t) + } private fun replaceTypeVariable(type: JavaType): JavaType { return when (type) { From 60123dcf5d1aef86136aa7fc2e2d534020e62eee Mon Sep 17 00:00:00 2001 From: Jonathan D'Orleans Date: Fri, 14 Feb 2020 01:10:22 -0500 Subject: [PATCH 2/4] add tests for unwrapGenericType to handle generics for deep hierarchy --- pom.xml | 2 +- .../graphql/kickstart/tools/place/Entity.kt | 3 ++ .../kickstart/tools/place/OtherPlace.kt | 7 +++ .../graphql/kickstart/tools/place/Place.kt | 8 +++ .../graphql/kickstart/tools/place/Place1.kt | 3 ++ .../graphql/kickstart/tools/place/Place2.kt | 3 ++ .../kickstart/tools/place/PlaceTest.kt | 28 ++++++++++ .../graphql/kickstart/tools/place/Review.kt | 8 +++ .../graphql/kickstart/tools/place/Review1.kt | 3 ++ .../graphql/kickstart/tools/place/Review2.kt | 3 ++ src/test/resources/place.graphqls | 51 +++++++++++++++++++ 11 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/test/kotlin/graphql/kickstart/tools/place/Entity.kt create mode 100644 src/test/kotlin/graphql/kickstart/tools/place/OtherPlace.kt create mode 100644 src/test/kotlin/graphql/kickstart/tools/place/Place.kt create mode 100644 src/test/kotlin/graphql/kickstart/tools/place/Place1.kt create mode 100644 src/test/kotlin/graphql/kickstart/tools/place/Place2.kt create mode 100644 src/test/kotlin/graphql/kickstart/tools/place/PlaceTest.kt create mode 100644 src/test/kotlin/graphql/kickstart/tools/place/Review.kt create mode 100644 src/test/kotlin/graphql/kickstart/tools/place/Review1.kt create mode 100644 src/test/kotlin/graphql/kickstart/tools/place/Review2.kt create mode 100644 src/test/resources/place.graphqls diff --git a/pom.xml b/pom.xml index 765014e4..7035a94c 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.graphql-java-kickstart graphql-java-tools - 5.7.2-SNAPSHOT + 5.7.3-SNAPSHOT jar GraphQL Java Tools diff --git a/src/test/kotlin/graphql/kickstart/tools/place/Entity.kt b/src/test/kotlin/graphql/kickstart/tools/place/Entity.kt new file mode 100644 index 00000000..ec1db38a --- /dev/null +++ b/src/test/kotlin/graphql/kickstart/tools/place/Entity.kt @@ -0,0 +1,3 @@ +package graphql.kickstart.tools.place + +abstract class Entity(val id: String? = null) \ No newline at end of file diff --git a/src/test/kotlin/graphql/kickstart/tools/place/OtherPlace.kt b/src/test/kotlin/graphql/kickstart/tools/place/OtherPlace.kt new file mode 100644 index 00000000..cd4fda46 --- /dev/null +++ b/src/test/kotlin/graphql/kickstart/tools/place/OtherPlace.kt @@ -0,0 +1,7 @@ +package graphql.kickstart.tools.place + +abstract class OtherPlace>(id: String? = null) : Place(id) { + + val other: String? = null + +} \ No newline at end of file diff --git a/src/test/kotlin/graphql/kickstart/tools/place/Place.kt b/src/test/kotlin/graphql/kickstart/tools/place/Place.kt new file mode 100644 index 00000000..9689a0ec --- /dev/null +++ b/src/test/kotlin/graphql/kickstart/tools/place/Place.kt @@ -0,0 +1,8 @@ +package graphql.kickstart.tools.place + +abstract class Place>(id: String? = null) : Entity(id) { + + val name: String? = null + val reviews: MutableSet? = null + +} \ No newline at end of file diff --git a/src/test/kotlin/graphql/kickstart/tools/place/Place1.kt b/src/test/kotlin/graphql/kickstart/tools/place/Place1.kt new file mode 100644 index 00000000..82f7c2a0 --- /dev/null +++ b/src/test/kotlin/graphql/kickstart/tools/place/Place1.kt @@ -0,0 +1,3 @@ +package graphql.kickstart.tools.place + +class Place1(id: String? = null) : OtherPlace(id) \ No newline at end of file diff --git a/src/test/kotlin/graphql/kickstart/tools/place/Place2.kt b/src/test/kotlin/graphql/kickstart/tools/place/Place2.kt new file mode 100644 index 00000000..0fe0cdeb --- /dev/null +++ b/src/test/kotlin/graphql/kickstart/tools/place/Place2.kt @@ -0,0 +1,3 @@ +package graphql.kickstart.tools.place + +class Place2(id: String? = null) : OtherPlace(id) \ No newline at end of file diff --git a/src/test/kotlin/graphql/kickstart/tools/place/PlaceTest.kt b/src/test/kotlin/graphql/kickstart/tools/place/PlaceTest.kt new file mode 100644 index 00000000..fb84005c --- /dev/null +++ b/src/test/kotlin/graphql/kickstart/tools/place/PlaceTest.kt @@ -0,0 +1,28 @@ +package graphql.kickstart.tools.place + +import graphql.ExecutionInput +import graphql.GraphQL +import graphql.kickstart.tools.GraphQLQueryResolver +import graphql.kickstart.tools.SchemaParser +import org.junit.Test + +class PlaceQuery : GraphQLQueryResolver { + fun places1(): List = listOf(Place1("1"), Place1("2"), Place1("3")) + fun places2(): List = listOf(Place2("4"), Place2("5")) +} + +class PlaceTest { + + @Test + fun shouldHandleGenericsDeepHierarchy() { + val schema = SchemaParser.newParser() + .file("place.graphqls") + .resolvers(PlaceQuery()) + .build().makeExecutableSchema() + val gql = GraphQL.newGraphQL(schema).build() + val result = gql.execute(ExecutionInput.newExecutionInput().query("query { places1 { id } places2 { id } }").build()) + assert(result.getData>>()["places1"]?.size == 3) + assert(result.getData>>()["places2"]?.size == 2) + } + +} diff --git a/src/test/kotlin/graphql/kickstart/tools/place/Review.kt b/src/test/kotlin/graphql/kickstart/tools/place/Review.kt new file mode 100644 index 00000000..7093dac2 --- /dev/null +++ b/src/test/kotlin/graphql/kickstart/tools/place/Review.kt @@ -0,0 +1,8 @@ +package graphql.kickstart.tools.place + +abstract class Review(id: String? = null) : Entity(id) { + + val rating: Int? = null + val content: T? = null + +} \ No newline at end of file diff --git a/src/test/kotlin/graphql/kickstart/tools/place/Review1.kt b/src/test/kotlin/graphql/kickstart/tools/place/Review1.kt new file mode 100644 index 00000000..540daded --- /dev/null +++ b/src/test/kotlin/graphql/kickstart/tools/place/Review1.kt @@ -0,0 +1,3 @@ +package graphql.kickstart.tools.place + +class Review1(id: String? = null) : Review(id) \ No newline at end of file diff --git a/src/test/kotlin/graphql/kickstart/tools/place/Review2.kt b/src/test/kotlin/graphql/kickstart/tools/place/Review2.kt new file mode 100644 index 00000000..2dfde1d7 --- /dev/null +++ b/src/test/kotlin/graphql/kickstart/tools/place/Review2.kt @@ -0,0 +1,3 @@ +package graphql.kickstart.tools.place + +class Review2(id: String? = null) : Review(id) \ No newline at end of file diff --git a/src/test/resources/place.graphqls b/src/test/resources/place.graphqls new file mode 100644 index 00000000..dc9c7c6b --- /dev/null +++ b/src/test/resources/place.graphqls @@ -0,0 +1,51 @@ +type Query { + places1: [Place1!] + places2: [Place2!] +} + +interface Entity { + id: ID! +} + +interface Place { + name: String + reviews: [Review!] +} + +interface OtherPlace { + name: String + other: String + reviews: [Review!] +} + +type Place1 implements Entity, Place, OtherPlace { + id: ID! + name: String + other: String + reviews: [Review1!] +} + +type Place2 implements Entity, Place, OtherPlace { + id: ID! + name: String + other: String + reviews: [Review2!] +} + +interface Review { + id: ID! + rating: Int + content: Entity +} + +type Review1 implements Review { + id: ID! + rating: Int + content: Place1 +} + +type Review2 implements Review { + id: ID! + rating: Int + content: Place2 +} From e55fd82108d87120cc920852027fdf5b324e82ba Mon Sep 17 00:00:00 2001 From: vojtapol Date: Wed, 19 Feb 2020 08:35:07 -0500 Subject: [PATCH 3/4] Simplify and rename PlaceTest.kt --- pom.xml | 2 +- .../graphql/kickstart/tools/GenericType.kt | 8 ++- .../tools/DeepGenericsHierarchyTest.kt | 55 +++++++++++++++++++ .../graphql/kickstart/tools/UtilsTest.kt | 2 +- .../graphql/kickstart/tools/place/Entity.kt | 3 - .../kickstart/tools/place/OtherPlace.kt | 7 --- .../graphql/kickstart/tools/place/Place.kt | 8 --- .../graphql/kickstart/tools/place/Place1.kt | 3 - .../graphql/kickstart/tools/place/Place2.kt | 3 - .../kickstart/tools/place/PlaceTest.kt | 28 ---------- .../graphql/kickstart/tools/place/Review.kt | 8 --- .../graphql/kickstart/tools/place/Review1.kt | 3 - .../graphql/kickstart/tools/place/Review2.kt | 3 - 13 files changed, 63 insertions(+), 70 deletions(-) create mode 100644 src/test/kotlin/graphql/kickstart/tools/DeepGenericsHierarchyTest.kt delete mode 100644 src/test/kotlin/graphql/kickstart/tools/place/Entity.kt delete mode 100644 src/test/kotlin/graphql/kickstart/tools/place/OtherPlace.kt delete mode 100644 src/test/kotlin/graphql/kickstart/tools/place/Place.kt delete mode 100644 src/test/kotlin/graphql/kickstart/tools/place/Place1.kt delete mode 100644 src/test/kotlin/graphql/kickstart/tools/place/Place2.kt delete mode 100644 src/test/kotlin/graphql/kickstart/tools/place/PlaceTest.kt delete mode 100644 src/test/kotlin/graphql/kickstart/tools/place/Review.kt delete mode 100644 src/test/kotlin/graphql/kickstart/tools/place/Review1.kt delete mode 100644 src/test/kotlin/graphql/kickstart/tools/place/Review2.kt diff --git a/pom.xml b/pom.xml index 7035a94c..765014e4 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.graphql-java-kickstart graphql-java-tools - 5.7.3-SNAPSHOT + 5.7.2-SNAPSHOT jar GraphQL Java Tools diff --git a/src/main/kotlin/graphql/kickstart/tools/GenericType.kt b/src/main/kotlin/graphql/kickstart/tools/GenericType.kt index 7615ff54..7771c5fd 100644 --- a/src/main/kotlin/graphql/kickstart/tools/GenericType.kt +++ b/src/main/kotlin/graphql/kickstart/tools/GenericType.kt @@ -124,9 +124,13 @@ internal open class GenericType(protected val mostSpecificType: JavaType, protec private fun unwrapGenericType(declaringType: ParameterizedType, type: TypeVariable<*>): JavaType { val rawClass = getRawClass(mostSpecificType) val arguments = TypeUtils.determineTypeArguments(rawClass, declaringType) - val t = arguments.filter { it.key.name == type.name }.values.firstOrNull() + val matchingType = arguments + .filter { it.key.name == type.name } + .values + .firstOrNull() ?: error("No type variable found for: ${TypeUtils.toLongString(type)}") - return unwrapGenericType(t) + + return unwrapGenericType(matchingType) } private fun replaceTypeVariable(type: JavaType): JavaType { diff --git a/src/test/kotlin/graphql/kickstart/tools/DeepGenericsHierarchyTest.kt b/src/test/kotlin/graphql/kickstart/tools/DeepGenericsHierarchyTest.kt new file mode 100644 index 00000000..b96461cf --- /dev/null +++ b/src/test/kotlin/graphql/kickstart/tools/DeepGenericsHierarchyTest.kt @@ -0,0 +1,55 @@ +package graphql.kickstart.tools + +import graphql.ExecutionInput +import graphql.GraphQL +import org.junit.Test + +class PlaceTest { + + @Test + fun shouldHandleGenericsDeepHierarchy() { + val schema = SchemaParser.newParser() + .file("place.graphqls") + .resolvers(PlaceQuery()) + .build().makeExecutableSchema() + + val graphql = GraphQL.newGraphQL(schema).build() + val query = "query { places1 { id } places2 { id } }" + val executionInput = ExecutionInput.newExecutionInput().query(query).build() + val result = graphql.execute(executionInput) + + assert(result.getData>>()["places1"]?.size == 3) + assert(result.getData>>()["places2"]?.size == 2) + } +} + +private class PlaceQuery : GraphQLQueryResolver { + + fun places1(): List = listOf(Place1("1"), Place1("2"), Place1("3")) + + fun places2(): List = listOf(Place2("4"), Place2("5")) +} + +private abstract class Entity(val id: String? = null) + +private abstract class OtherPlace>(id: String? = null) : Place(id) { + val other: String? = null +} + +private abstract class Place>(id: String? = null) : Entity(id) { + val name: String? = null + val reviews: MutableSet? = null +} + +private class Place1(id: String? = null) : OtherPlace(id) + +private class Place2(id: String? = null) : OtherPlace(id) + +private abstract class Review(id: String? = null) : Entity(id) { + val rating: Int? = null + val content: T? = null +} + +private class Review1(id: String? = null) : Review(id) + +private class Review2(id: String? = null) : Review(id) diff --git a/src/test/kotlin/graphql/kickstart/tools/UtilsTest.kt b/src/test/kotlin/graphql/kickstart/tools/UtilsTest.kt index 38f9cc61..5294300c 100644 --- a/src/test/kotlin/graphql/kickstart/tools/UtilsTest.kt +++ b/src/test/kotlin/graphql/kickstart/tools/UtilsTest.kt @@ -24,7 +24,7 @@ class UtilsTest { } @Test - fun `isTrivialDataFetcher`() { + fun isTrivialDataFetcher() { val clazz = Bean::class.java Assert.assertTrue(isTrivialDataFetcher(clazz.getMethod("getterValid"))) diff --git a/src/test/kotlin/graphql/kickstart/tools/place/Entity.kt b/src/test/kotlin/graphql/kickstart/tools/place/Entity.kt deleted file mode 100644 index ec1db38a..00000000 --- a/src/test/kotlin/graphql/kickstart/tools/place/Entity.kt +++ /dev/null @@ -1,3 +0,0 @@ -package graphql.kickstart.tools.place - -abstract class Entity(val id: String? = null) \ No newline at end of file diff --git a/src/test/kotlin/graphql/kickstart/tools/place/OtherPlace.kt b/src/test/kotlin/graphql/kickstart/tools/place/OtherPlace.kt deleted file mode 100644 index cd4fda46..00000000 --- a/src/test/kotlin/graphql/kickstart/tools/place/OtherPlace.kt +++ /dev/null @@ -1,7 +0,0 @@ -package graphql.kickstart.tools.place - -abstract class OtherPlace>(id: String? = null) : Place(id) { - - val other: String? = null - -} \ No newline at end of file diff --git a/src/test/kotlin/graphql/kickstart/tools/place/Place.kt b/src/test/kotlin/graphql/kickstart/tools/place/Place.kt deleted file mode 100644 index 9689a0ec..00000000 --- a/src/test/kotlin/graphql/kickstart/tools/place/Place.kt +++ /dev/null @@ -1,8 +0,0 @@ -package graphql.kickstart.tools.place - -abstract class Place>(id: String? = null) : Entity(id) { - - val name: String? = null - val reviews: MutableSet? = null - -} \ No newline at end of file diff --git a/src/test/kotlin/graphql/kickstart/tools/place/Place1.kt b/src/test/kotlin/graphql/kickstart/tools/place/Place1.kt deleted file mode 100644 index 82f7c2a0..00000000 --- a/src/test/kotlin/graphql/kickstart/tools/place/Place1.kt +++ /dev/null @@ -1,3 +0,0 @@ -package graphql.kickstart.tools.place - -class Place1(id: String? = null) : OtherPlace(id) \ No newline at end of file diff --git a/src/test/kotlin/graphql/kickstart/tools/place/Place2.kt b/src/test/kotlin/graphql/kickstart/tools/place/Place2.kt deleted file mode 100644 index 0fe0cdeb..00000000 --- a/src/test/kotlin/graphql/kickstart/tools/place/Place2.kt +++ /dev/null @@ -1,3 +0,0 @@ -package graphql.kickstart.tools.place - -class Place2(id: String? = null) : OtherPlace(id) \ No newline at end of file diff --git a/src/test/kotlin/graphql/kickstart/tools/place/PlaceTest.kt b/src/test/kotlin/graphql/kickstart/tools/place/PlaceTest.kt deleted file mode 100644 index fb84005c..00000000 --- a/src/test/kotlin/graphql/kickstart/tools/place/PlaceTest.kt +++ /dev/null @@ -1,28 +0,0 @@ -package graphql.kickstart.tools.place - -import graphql.ExecutionInput -import graphql.GraphQL -import graphql.kickstart.tools.GraphQLQueryResolver -import graphql.kickstart.tools.SchemaParser -import org.junit.Test - -class PlaceQuery : GraphQLQueryResolver { - fun places1(): List = listOf(Place1("1"), Place1("2"), Place1("3")) - fun places2(): List = listOf(Place2("4"), Place2("5")) -} - -class PlaceTest { - - @Test - fun shouldHandleGenericsDeepHierarchy() { - val schema = SchemaParser.newParser() - .file("place.graphqls") - .resolvers(PlaceQuery()) - .build().makeExecutableSchema() - val gql = GraphQL.newGraphQL(schema).build() - val result = gql.execute(ExecutionInput.newExecutionInput().query("query { places1 { id } places2 { id } }").build()) - assert(result.getData>>()["places1"]?.size == 3) - assert(result.getData>>()["places2"]?.size == 2) - } - -} diff --git a/src/test/kotlin/graphql/kickstart/tools/place/Review.kt b/src/test/kotlin/graphql/kickstart/tools/place/Review.kt deleted file mode 100644 index 7093dac2..00000000 --- a/src/test/kotlin/graphql/kickstart/tools/place/Review.kt +++ /dev/null @@ -1,8 +0,0 @@ -package graphql.kickstart.tools.place - -abstract class Review(id: String? = null) : Entity(id) { - - val rating: Int? = null - val content: T? = null - -} \ No newline at end of file diff --git a/src/test/kotlin/graphql/kickstart/tools/place/Review1.kt b/src/test/kotlin/graphql/kickstart/tools/place/Review1.kt deleted file mode 100644 index 540daded..00000000 --- a/src/test/kotlin/graphql/kickstart/tools/place/Review1.kt +++ /dev/null @@ -1,3 +0,0 @@ -package graphql.kickstart.tools.place - -class Review1(id: String? = null) : Review(id) \ No newline at end of file diff --git a/src/test/kotlin/graphql/kickstart/tools/place/Review2.kt b/src/test/kotlin/graphql/kickstart/tools/place/Review2.kt deleted file mode 100644 index 2dfde1d7..00000000 --- a/src/test/kotlin/graphql/kickstart/tools/place/Review2.kt +++ /dev/null @@ -1,3 +0,0 @@ -package graphql.kickstart.tools.place - -class Review2(id: String? = null) : Review(id) \ No newline at end of file From 420057267958eae1740d34222f75e097be193bc5 Mon Sep 17 00:00:00 2001 From: vojtapol Date: Wed, 19 Feb 2020 08:37:47 -0500 Subject: [PATCH 4/4] Make test schema file names consistent --- .../groovy/graphql/kickstart/tools/SchemaParserSpec.groovy | 6 +++--- .../graphql/kickstart/tools/DeepGenericsHierarchyTest.kt | 2 +- src/test/resources/{place.graphqls => Place.graphqls} | 0 src/test/resources/{test.graphqls => Test.graphqls} | 0 4 files changed, 4 insertions(+), 4 deletions(-) rename src/test/resources/{place.graphqls => Place.graphqls} (100%) rename src/test/resources/{test.graphqls => Test.graphqls} (100%) diff --git a/src/test/groovy/graphql/kickstart/tools/SchemaParserSpec.groovy b/src/test/groovy/graphql/kickstart/tools/SchemaParserSpec.groovy index 78e486ec..f98e20f4 100644 --- a/src/test/groovy/graphql/kickstart/tools/SchemaParserSpec.groovy +++ b/src/test/groovy/graphql/kickstart/tools/SchemaParserSpec.groovy @@ -33,7 +33,7 @@ class SchemaParserSpec extends Specification { def "builder doesn't throw FileNotFound exception when file is present"() { when: - SchemaParser.newParser().file("test.graphqls") + SchemaParser.newParser().file("Test.graphqls") .resolvers(new GraphQLQueryResolver() { String getId() { "1" } }) @@ -286,7 +286,7 @@ class SchemaParserSpec extends Specification { def "parser should include source location for field definition when loaded from single classpath file"() { when: GraphQLSchema schema = SchemaParser.newParser() - .file("test.graphqls") + .file("Test.graphqls") .resolvers(new QueryWithIdResolver()) .build() .makeExecutableSchema() @@ -298,7 +298,7 @@ class SchemaParserSpec extends Specification { sourceLocation != null sourceLocation.line == 2 sourceLocation.column == 5 - sourceLocation.sourceName == "test.graphqls" + sourceLocation.sourceName == "Test.graphqls" } def "support enum types if only used as input type"() { diff --git a/src/test/kotlin/graphql/kickstart/tools/DeepGenericsHierarchyTest.kt b/src/test/kotlin/graphql/kickstart/tools/DeepGenericsHierarchyTest.kt index b96461cf..72a6e35f 100644 --- a/src/test/kotlin/graphql/kickstart/tools/DeepGenericsHierarchyTest.kt +++ b/src/test/kotlin/graphql/kickstart/tools/DeepGenericsHierarchyTest.kt @@ -9,7 +9,7 @@ class PlaceTest { @Test fun shouldHandleGenericsDeepHierarchy() { val schema = SchemaParser.newParser() - .file("place.graphqls") + .file("Place.graphqls") .resolvers(PlaceQuery()) .build().makeExecutableSchema() diff --git a/src/test/resources/place.graphqls b/src/test/resources/Place.graphqls similarity index 100% rename from src/test/resources/place.graphqls rename to src/test/resources/Place.graphqls diff --git a/src/test/resources/test.graphqls b/src/test/resources/Test.graphqls similarity index 100% rename from src/test/resources/test.graphqls rename to src/test/resources/Test.graphqls