From 61f14909c8f8607cc412a6e9cfb060ca6ccc0806 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 15 Feb 2021 18:46:04 +0100 Subject: [PATCH 1/2] Allowing nested inputs defined in extensions to be parsed as well --- .../kickstart/tools/SchemaClassScanner.kt | 2 +- .../tools/NestedInputTypesSpec.groovy | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/graphql/kickstart/tools/SchemaClassScanner.kt b/src/main/kotlin/graphql/kickstart/tools/SchemaClassScanner.kt index b45ada00..c8c076f4 100644 --- a/src/main/kotlin/graphql/kickstart/tools/SchemaClassScanner.kt +++ b/src/main/kotlin/graphql/kickstart/tools/SchemaClassScanner.kt @@ -333,7 +333,7 @@ internal class SchemaClassScanner( } is InputObjectTypeDefinition -> { - graphQLType.inputValueDefinitions.forEach { inputValueDefinition -> + (listOf(graphQLType) + inputExtensionDefinitions.filter { it.name == graphQLType.name }).flatMap { it.inputValueDefinitions }.forEach { inputValueDefinition -> val inputGraphQLType = inputValueDefinition.type.unwrap() if (inputGraphQLType is TypeName && !ScalarInfo.GRAPHQL_SPECIFICATION_SCALARS_DEFINITIONS.containsKey(inputGraphQLType.name)) { val inputValueJavaType = findInputValueType(inputValueDefinition.name, inputGraphQLType, javaType.unwrap()) diff --git a/src/test/groovy/graphql/kickstart/tools/NestedInputTypesSpec.groovy b/src/test/groovy/graphql/kickstart/tools/NestedInputTypesSpec.groovy index 54be3706..d0ce1a68 100644 --- a/src/test/groovy/graphql/kickstart/tools/NestedInputTypesSpec.groovy +++ b/src/test/groovy/graphql/kickstart/tools/NestedInputTypesSpec.groovy @@ -53,6 +53,55 @@ class NestedInputTypesSpec extends Specification { data.materials == [] } + def "nested input in extensions are parsed"() { + when: + GraphQLSchema schema = SchemaParser.newParser().schemaString('''\ + type Query { + materials(filter: MaterialFilter): [Material!]! + } + + input MaterialFilter { + title: String + } + + extend input MaterialFilter { + requestFilter: RequestFilter + } + + input RequestFilter { + and: [RequestFilter!] + or: [RequestFilter!] + discountTypeFilter: DiscountTypeFilter + } + + input DiscountTypeFilter { + name: String + } + + type Material { + id: ID! + } + ''').resolvers(new QueryResolver()) + .build() + .makeExecutableSchema() + GraphQL gql = GraphQL.newGraphQL(schema) + .queryExecutionStrategy(new AsyncExecutionStrategy()) + .build() + def data = Utils.assertNoGraphQlErrors(gql, [filter: [title: "title", requestFilter: [discountTypeFilter: [name: "discount"]]]]) { + ''' + query materials($filter: MaterialFilter!) { + materials(filter: $filter) { + id + } + } + ''' + } + + then: + noExceptionThrown() + data.materials == [] + } + class QueryResolver implements GraphQLQueryResolver { List materials(MaterialFilter filter) { Collections.emptyList() } } From 2ded2f1dc70d18eb6ccd787228553ee2e9351758 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 16 Feb 2021 21:19:11 +0100 Subject: [PATCH 2/2] Improve readability by storing a seperate variable --- .../kickstart/tools/SchemaClassScanner.kt | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/main/kotlin/graphql/kickstart/tools/SchemaClassScanner.kt b/src/main/kotlin/graphql/kickstart/tools/SchemaClassScanner.kt index c8c076f4..b6f7d34e 100644 --- a/src/main/kotlin/graphql/kickstart/tools/SchemaClassScanner.kt +++ b/src/main/kotlin/graphql/kickstart/tools/SchemaClassScanner.kt @@ -333,26 +333,29 @@ internal class SchemaClassScanner( } is InputObjectTypeDefinition -> { - (listOf(graphQLType) + inputExtensionDefinitions.filter { it.name == graphQLType.name }).flatMap { it.inputValueDefinitions }.forEach { inputValueDefinition -> - val inputGraphQLType = inputValueDefinition.type.unwrap() - if (inputGraphQLType is TypeName && !ScalarInfo.GRAPHQL_SPECIFICATION_SCALARS_DEFINITIONS.containsKey(inputGraphQLType.name)) { - val inputValueJavaType = findInputValueType(inputValueDefinition.name, inputGraphQLType, javaType.unwrap()) - if (inputValueJavaType != null) { - handleFoundType(typeClassMatcher.match(TypeClassMatcher.PotentialMatch.parameterType( - inputValueDefinition.type, - inputValueJavaType, - GenericType(javaType, options).relativeToType(inputValueJavaType), - InputObjectReference(inputValueDefinition) - ))) - } else { - var mappingAdvice = "Try adding it manually to the dictionary" - if (javaType.unwrap().name.contains("Map")) { - mappingAdvice = " or add a class to represent your input type instead of a Map." + val inputObjectTypes = listOf(graphQLType) + inputExtensionDefinitions.filter { it.name == graphQLType.name } + inputObjectTypes + .flatMap { it.inputValueDefinitions } + .forEach { inputValueDefinition -> + val inputGraphQLType = inputValueDefinition.type.unwrap() + if (inputGraphQLType is TypeName && !ScalarInfo.GRAPHQL_SPECIFICATION_SCALARS_DEFINITIONS.containsKey(inputGraphQLType.name)) { + val inputValueJavaType = findInputValueType(inputValueDefinition.name, inputGraphQLType, javaType.unwrap()) + if (inputValueJavaType != null) { + handleFoundType(typeClassMatcher.match(TypeClassMatcher.PotentialMatch.parameterType( + inputValueDefinition.type, + inputValueJavaType, + GenericType(javaType, options).relativeToType(inputValueJavaType), + InputObjectReference(inputValueDefinition) + ))) + } else { + var mappingAdvice = "Try adding it manually to the dictionary" + if (javaType.unwrap().name.contains("Map")) { + mappingAdvice = " or add a class to represent your input type instead of a Map." + } + log.warn("Cannot find definition for field '${inputValueDefinition.name}: ${inputGraphQLType.name}' on input type '${graphQLType.name}' -> ${javaType.unwrap().name}. $mappingAdvice") } - log.warn("Cannot find definition for field '${inputValueDefinition.name}: ${inputGraphQLType.name}' on input type '${graphQLType.name}' -> ${javaType.unwrap().name}. $mappingAdvice") } } - } } } }