Repository: graphql-java-kickstart/graphql-java-tools (kotlin)

Issue:
GraphQLTypeReference instead of proper GraphQlInputObjectType during runtime (Directive wiring) on NonNull Input types
My team is using the graphql-java-extended-validation library and we identified that the validations would not execute when we add the validation on a NonNull input type. Initially, we thought this would be a bug there, but now we identified that this is happening because this validation library executes over the directive wiring, and sadly at that level of execution GraphQLArguments that are NonNull hasn't the proper GraphQLInputObjectType definition for it, just has the `GraphQLTypeRefernce` for that type, which will later be replaced on GraphQLSchema building method. But we need the proper InputObject Definition at runtime, at Directive Wiring.
I created a test case to illustrate this issue and also pushing a PR with the solution we found to have this reference properly set at runtime without falling into infinity recursion.


Test Case to illustrate the issue:
```groovy
def "NonNull and nullable arguments returning it's GraphQLInputObjectType "() {
        when:
        GraphQLSchema schema = SchemaParser.newParser().schemaString('''\
                    type Query { 
                        testNonNullable(filter: Filter!): Boolean
                        testNullable(filter: Filter): Boolean
                    }
                    input Filter {
                        filter: String
                    }
                '''.stripIndent())
                .resolvers(new GraphQLQueryResolver() {
                    boolean testNonNullable(Filter filter) { false }
                    boolean testNullable(Filter filter) { false }
                })
                .directiveWiring(new SchemaDirectiveWiring(){
                        GraphQLArgument onArgument(SchemaDirectiveWiringEnvironment<GraphQLArgument> environment) {
                            switch (environment.getElement().type.class) {
                                case GraphQLNonNull:
                                    assert (environment.getElement().type as graphql.schema.GraphQLNonNull).wrappedType.class == GraphQLInputObjectType
                            }
                            return environment.getElement()
                        }})
                .build()
                .makeExecutableSchema()

        then:
        GraphQLArgument testNonNullableArgument = schema.getObjectType("Query")
                .getFieldDefinition("testNonNullable")
                .arguments.first()
        GraphQLArgument testNullableArgument = schema.getObjectType("Query")
                .getFieldDefinition("testNullable")
                .arguments.first()
        testNonNullableArgument.type.class == graphql.schema.GraphQLNonNull
        (testNonNullableArgument.type as graphql.schema.GraphQLNonNull).wrappedType.class == GraphQLInputObjectType
        testNullableArgument.type.class == GraphQLInputObjectType
    }
```

Pull request:
Fixes #434  Add GraphQlInputObjectType reference for NonNull INput types at …Runtime Wiring



## Checklist
<!-- Change [ ] to [x] to indicate you acknowledge the check. -->
- [x] Pull requests follows the [contribution guide](https://github.com/graphql-java-kickstart/graphql-java-tools/wiki/Contribution-guide)
- [x] New or modified functionality is covered by tests

## Description
- Added to the determineType the same approach as  determineInputType, but without the creation of nonexisting INput types (this could lead to infinity recursion)
- Added Groovy Unit Test to ensure the problem is solved

Patch:
diff --git a/src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt b/src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt
index ee1d217a..788d09ee 100644
--- a/src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt
+++ b/src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt
@@ -400,7 +400,7 @@ class SchemaParser internal constructor(
                         throw SchemaError("Expected type '${typeDefinition.name}' to be a ${expectedType.simpleName}, but it wasn't!  " +
                             "Was a type only permitted for object types incorrectly used as an input type, or vice-versa?")
                     }
-                    GraphQLTypeReference(typeDefinition.name)
+                    inputObjects.find { it.name == typeDefinition.name } ?: GraphQLTypeReference(typeDefinition.name)
                 }
             }
             else -> throw SchemaError("Unknown type: $typeDefinition")


Test patch:
diff --git a/src/test/kotlin/graphql/kickstart/tools/SchemaParserTest.kt b/src/test/kotlin/graphql/kickstart/tools/SchemaParserTest.kt
index 3b6c3783..263745be 100644
--- a/src/test/kotlin/graphql/kickstart/tools/SchemaParserTest.kt
+++ b/src/test/kotlin/graphql/kickstart/tools/SchemaParserTest.kt
@@ -3,6 +3,11 @@ package graphql.kickstart.tools
 import graphql.kickstart.tools.resolver.FieldResolverError
 import graphql.schema.GraphQLInterfaceType
 import graphql.schema.GraphQLObjectType
+import graphql.schema.GraphQLArgument
+import graphql.schema.GraphQLInputObjectType
+import graphql.schema.GraphQLNonNull
+import graphql.schema.idl.SchemaDirectiveWiring
+import graphql.schema.idl.SchemaDirectiveWiringEnvironment
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -479,6 +484,47 @@ class SchemaParserTest {
         class Poodle(override var traits: List<PoodleTrait>) : Dog<PoodleTrait>()
     }
 
+    @Test
+    fun `NonNull and nullable input arguments should resolve to GraphQLInputObjectType`() {
+        val schema = SchemaParser.newParser()
+            .schemaString(
+                """
+                type Query {
+                    testNonNullable(filter: Filter!): Boolean
+                    testNullable(filter: Filter): Boolean
+                }
+        
+                input Filter {
+                    filter: String
+                }
+                """)
+            .resolvers(object : GraphQLQueryResolver {
+                fun testNonNullable(filter: Filter): Boolean = false
+                fun testNullable(filter: Filter): Boolean = false
+            })
+            .directiveWiring(object : SchemaDirectiveWiring {
+                override fun onArgument(environment: SchemaDirectiveWiringEnvironment<GraphQLArgument>): GraphQLArgument {
+                    when (environment.element.type) {
+                        is GraphQLNonNull ->
+                            assert((environment.element.type as GraphQLNonNull).wrappedType is GraphQLInputObjectType)
+                    }
+                    return environment.element
+                }
+            })
+            .build()
+            .makeExecutableSchema()
+
+        val testNonNullableArgument = schema.getObjectType("Query")
+            .getFieldDefinition("testNonNullable")
+            .arguments.first()
+        val testNullableArgument = schema.getObjectType("Query")
+            .getFieldDefinition("testNullable")
+            .arguments.first()
+        assert(testNonNullableArgument.type is GraphQLNonNull)
+        assert((testNonNullableArgument.type as GraphQLNonNull).wrappedType is GraphQLInputObjectType)
+        assert(testNullableArgument.type is GraphQLInputObjectType)
+    }
+
     enum class EnumType {
         TEST
     }