From 135b8413079e708bad12125791ff95ffd9ab1392 Mon Sep 17 00:00:00 2001 From: Oryan Date: Thu, 22 Oct 2026 17:33:08 -0400 Subject: [PATCH 1/2] Determine input types with the same recursion as output types determineInputType copied the list, non-null and scalar handling of determineType. Now determineType takes the lookup for named types that aren't scalars, and only the input version builds input objects. Also drop the InputObjectTypeDefinition branch, which a Type can never be. Co-Authored-By: Claude Opus 5.5 --- .../graphql/kickstart/tools/SchemaParser.kt | 72 +++++-------------- 1 file changed, 18 insertions(+), 54 deletions(-) diff --git a/src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt b/src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt index 1a39afa5..4cdd1abe 100644 --- a/src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt +++ b/src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt @@ -202,11 +202,11 @@ class SchemaParser internal constructor( } private fun createInputObject(definition: InputObjectTypeDefinition, inputObjects: List, - referencingInputObjects: MutableSet): GraphQLInputObjectType { + inputObjectsInProgress: MutableSet): GraphQLInputObjectType { val extensionDefinitions = typeExtensions.extensionsOf(definition.name) val directives = directivesOf(definition, extensionDefinitions) - referencingInputObjects.add(definition.name) + inputObjectsInProgress.add(definition.name) val builder = GraphQLInputObjectType.newInputObject() .name(definition.name) @@ -225,7 +225,7 @@ class SchemaParser internal constructor( .description(getDocumentation(fieldDefinition, options)) .apply { fieldDefinition.defaultValue?.let { v -> defaultValueLiteral(v) } } .apply { getDeprecated(fieldDefinition.directives)?.let { deprecate(it) } } - .type(determineInputType(fieldDefinition.type, inputObjects, referencingInputObjects)) + .type(determineInputType(fieldDefinition.type, inputObjects, inputObjectsInProgress)) .withAppliedDirectives(*buildAppliedDirectives(fieldDefinition.directives, INPUT_FIELD_DEFINITION)) .withDirectives(*buildDirectives(fieldDefinition.directives, INPUT_FIELD_DEFINITION)) .build() @@ -598,11 +598,12 @@ class SchemaParser internal constructor( private fun determineType( expectedType: KClass, typeDefinition: Type<*>, - allowedTypeReferences: Set + allowedTypeReferences: Set, + namedType: (TypeName) -> GraphQLType = { GraphQLTypeReference(it.name) } ): GraphQLType = when (typeDefinition) { - is ListType -> GraphQLList(determineType(expectedType, typeDefinition.type, allowedTypeReferences)) - is NonNullType -> GraphQLNonNull(determineType(expectedType, typeDefinition.type, allowedTypeReferences)) + is ListType -> GraphQLList(determineType(expectedType, typeDefinition.type, allowedTypeReferences, namedType)) + is NonNullType -> GraphQLNonNull(determineType(expectedType, typeDefinition.type, allowedTypeReferences, namedType)) is TypeName -> { val scalarType = customScalars[typeDefinition.name] ?: GRAPHQL_SCALARS[typeDefinition.name] @@ -612,60 +613,23 @@ class SchemaParser internal constructor( if (!allowedTypeReferences.contains(typeDefinition.name)) { throw unexpectedTypeError(typeDefinition, expectedType) } - GraphQLTypeReference(typeDefinition.name) + namedType(typeDefinition) } } else -> throw SchemaError("Unknown type: $typeDefinition") } - private fun determineInputType(typeDefinition: Type<*>, inputObjects: List, referencingInputObjects: MutableSet) = - determineInputType(GraphQLInputType::class, typeDefinition, permittedTypesForInputObject, inputObjects, referencingInputObjects) + private fun determineInputType(typeDefinition: Type<*>, inputObjects: List, inputObjectsInProgress: MutableSet) = + determineType(GraphQLInputType::class, typeDefinition, permittedTypesForInputObject) { + inputObjectType(it, inputObjects, inputObjectsInProgress) + } as GraphQLInputType - private fun determineInputType( - expectedType: KClass, - typeDefinition: Type<*>, - allowedTypeReferences: Set, - inputObjects: List, - referencingInputObjects: MutableSet): GraphQLInputType = - when (typeDefinition) { - is ListType -> GraphQLList(determineInputType(expectedType, typeDefinition.type, allowedTypeReferences, inputObjects, referencingInputObjects)) - is NonNullType -> GraphQLNonNull(determineInputType(expectedType, typeDefinition.type, allowedTypeReferences, inputObjects, referencingInputObjects)) - is InputObjectTypeDefinition -> { - log.info("Create input object") - createInputObject(typeDefinition, inputObjects, referencingInputObjects) - } - is TypeName -> { - val scalarType = customScalars[typeDefinition.name] - ?: GRAPHQL_SCALARS[typeDefinition.name] - if (scalarType != null) { - scalarType - } else { - if (!allowedTypeReferences.contains(typeDefinition.name)) { - throw unexpectedTypeError(typeDefinition, expectedType) - } - val found = inputObjects.filter { it.name == typeDefinition.name } - if (found.size == 1) { - found[0] - } else { - val filteredDefinitions = inputObjectDefinitions.filter { it.name == typeDefinition.name } - if (filteredDefinitions.isNotEmpty()) { - val referencingInputObject = referencingInputObjects.find { it == typeDefinition.name } - if (referencingInputObject != null) { - GraphQLTypeReference(referencingInputObject) - } else { - val inputObject = createInputObject(filteredDefinitions[0], inputObjects, referencingInputObjects) - (inputObjects as MutableList).add(inputObject) - inputObject - } - } else { - // todo: handle enum type - GraphQLTypeReference(typeDefinition.name) - } - } - } - } - else -> throw SchemaError("Unknown type: $typeDefinition") - } + private fun inputObjectType(typeName: TypeName, inputObjects: List, inputObjectsInProgress: MutableSet): GraphQLType { + inputObjects.find { it.name == typeName.name }?.let { return it } + val definition = inputObjectDefinitions.find { it.name == typeName.name } + if (definition == null || typeName.name in inputObjectsInProgress) return GraphQLTypeReference(typeName.name) + return createInputObject(definition, inputObjects, inputObjectsInProgress).also { (inputObjects as MutableList).add(it) } + } private fun unexpectedTypeError(typeName: TypeName, expectedType: KClass<*>): SchemaError { val isInput = expectedType == GraphQLInputType::class From 7448f2c68517b9c62578b999d61ef7cecde49f53 Mon Sep 17 00:00:00 2001 From: Oryan Date: Thu, 22 Oct 2026 17:37:36 -0400 Subject: [PATCH 2/2] Drop the determineType comment the namedType default now shows Co-Authored-By: Claude Opus 5.5 --- src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt b/src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt index f5071569..ec1d3259 100644 --- a/src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt +++ b/src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt @@ -629,7 +629,6 @@ class SchemaParser internal constructor( private fun determineOutputType(typeDefinition: Type<*>) = determineType(GraphQLOutputType::class, typeDefinition, permittedTypesForObject) as GraphQLOutputType - // named types other than spec scalars are type references private fun determineType( expectedType: KClass, typeDefinition: Type<*>,