11package graphql.kickstart.tools
22
3+ import graphql.Directives
34import graphql.introspection.Introspection
45import graphql.introspection.Introspection.DirectiveLocation.INPUT_FIELD_DEFINITION
56import graphql.kickstart.tools.directive.DirectiveWiringHelper
@@ -8,7 +9,6 @@ import graphql.kickstart.tools.util.getExtendedFieldDefinitions
89import graphql.kickstart.tools.util.unwrap
910import graphql.language.*
1011import graphql.schema.*
11- import graphql.schema.idl.DirectiveInfo
1212import graphql.schema.idl.RuntimeWiring
1313import graphql.schema.idl.ScalarInfo
1414import graphql.schema.visibility.NoIntrospectionGraphqlFieldVisibility
@@ -351,7 +351,7 @@ class SchemaParser internal constructor(
351351 private fun buildAppliedDirectives (directives : List <Directive >): Array <GraphQLAppliedDirective > {
352352 return directives.map { directive ->
353353 val graphQLDirective = schemaDirectives.find { d -> d.name == directive.name }
354- ? : DirectiveInfo . GRAPHQL_SPECIFICATION_DIRECTIVE_MAP [directive.name]
354+ ? : BUILT_IN_DIRECTIVES [directive.name]
355355 ? : throw SchemaError (" Found applied directive ${directive.name} without corresponding directive definition." )
356356 val graphQLArguments = graphQLDirective.arguments.associateBy { it.name }
357357
@@ -374,6 +374,22 @@ class SchemaParser internal constructor(
374374 )
375375 }
376376 }
377+ .apply {
378+ // a bare @deprecated has no "reason" argument, which makes SchemaPrinter throw a NPE.
379+ // copy the default from the directive definition (for the built-in one: "No longer supported").
380+ if (directive.name == Directives .DeprecatedDirective .name && directive.arguments.none { it.name == " reason" }) {
381+ val reasonArgument = graphQLArguments[" reason" ]
382+ if (reasonArgument != null && reasonArgument.hasSetDefaultValue()) {
383+ argument(GraphQLAppliedDirectiveArgument .newArgument()
384+ .name(reasonArgument.name)
385+ .type(reasonArgument.type)
386+ .description(reasonArgument.description)
387+ .inputValueWithState(reasonArgument.argumentDefaultValue)
388+ .build()
389+ )
390+ }
391+ }
392+ }
377393 .build()
378394 }.toTypedArray()
379395 }
@@ -391,7 +407,7 @@ class SchemaParser internal constructor(
391407 if (repeatable || ! names.contains(directive.name)) {
392408 names.add(directive.name)
393409 val graphQLDirective = this .schemaDirectives.find { d -> d.name == directive.name }
394- ? : DirectiveInfo . GRAPHQL_SPECIFICATION_DIRECTIVE_MAP [directive.name]
410+ ? : BUILT_IN_DIRECTIVES [directive.name]
395411 ? : throw SchemaError (" Found applied directive ${directive.name} without corresponding directive definition." )
396412 val graphQLArguments = graphQLDirective.arguments.associateBy { it.name }
397413 output.add(
@@ -521,4 +537,16 @@ class SchemaError(message: String, cause: Throwable? = null) : RuntimeException(
521537
522538val GRAPHQL_SCALARS = ScalarInfo .GRAPHQL_SPECIFICATION_SCALARS .associateBy { it.name }
523539
540+ // Built from the individual constants rather than Directives.BUILT_IN_DIRECTIVES_MAP (added in graphql-java 26)
541+ // so that the library keeps working with graphql-java 25. TODO replace with Directives.BUILT_IN_DIRECTIVES_MAP once we deploy a major version
542+ private val BUILT_IN_DIRECTIVES = listOf (
543+ Directives .IncludeDirective ,
544+ Directives .SkipDirective ,
545+ Directives .DeprecatedDirective ,
546+ Directives .SpecifiedByDirective ,
547+ Directives .OneOfDirective ,
548+ Directives .DeferDirective ,
549+ Directives .ExperimentalDisableErrorPropagationDirective
550+ ).associateBy { it.name }
551+
524552const val DEFAULT_DEPRECATION_MESSAGE = " No longer supported"
0 commit comments