Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
#4182 - code built schemas should perform deprecated non null field v…
…alidations as well as SDL built ones
  • Loading branch information
bbakerman committed Dec 18, 2025
commit afbcd52285065393ebb326a2ce4871daf36c700e
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,8 @@ public TraversalControl visitGraphQLInputObjectField(GraphQLInputObjectField inp
// An applied directive's argument cannot be deprecated.
@Override
public TraversalControl visitGraphQLArgument(GraphQLArgument argument, TraverserContext<GraphQLSchemaElement> context) {
// There can only be at most one @deprecated, because it is not a repeatable directive
GraphQLAppliedDirective deprecatedDirective = argument.getAppliedDirective(Directives.DEPRECATED_DIRECTIVE_DEFINITION.getName());

if (deprecatedDirective != null && GraphQLTypeUtil.isNonNull(argument.getType()) && !argument.hasSetDefaultValue()) {
boolean isDeprecated = isDeprecated(argument);
if (isDeprecated && GraphQLTypeUtil.isNonNull(argument.getType()) && !argument.hasSetDefaultValue()) {
if (context.getParentNode() instanceof GraphQLFieldDefinition) {
GraphQLFieldDefinition fieldDefinition = (GraphQLFieldDefinition) context.getParentNode();
SchemaValidationErrorCollector errorCollector = context.getVarFromParents(SchemaValidationErrorCollector.class);
Expand All @@ -61,4 +59,14 @@ public TraversalControl visitGraphQLArgument(GraphQLArgument argument, Traverser
return TraversalControl.CONTINUE;
}

private boolean isDeprecated(GraphQLArgument argument) {
// There can only be at most one @deprecated, because it is not a repeatable directive
GraphQLAppliedDirective deprecatedDirective = argument.getAppliedDirective(Directives.DEPRECATED_DIRECTIVE_DEFINITION.getName());
if (deprecatedDirective != null) {
return true;
}
// handle code built schemas, where they have no directive but `graphql.schema.GraphQLArgument.Builder#deprecate` has been called directly
return argument.isDeprecated();
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package graphql.schema.validation

import graphql.Scalars
import graphql.TestUtil
import graphql.schema.GraphQLArgument
import graphql.schema.GraphQLFieldDefinition
import graphql.schema.GraphQLNonNull
import graphql.schema.GraphQLObjectType
import graphql.schema.GraphQLSchema
import spock.lang.Specification

class DeprecatedInputObjectAndArgumentsAreValidTest extends Specification {
Expand Down Expand Up @@ -293,4 +299,31 @@ class DeprecatedInputObjectAndArgumentsAreValidTest extends Specification {
noExceptionThrown()
}

def "schema build via code has the same validation rule"() {
when:
GraphQLArgument deprecatedArg = GraphQLArgument.newArgument()
.name("input")
.type(GraphQLNonNull.nonNull(Scalars.GraphQLString))
.deprecate("Some very good reason")
.build()

GraphQLFieldDefinition field = GraphQLFieldDefinition.newFieldDefinition()
.name("field")
.type(Scalars.GraphQLString)
.argument(deprecatedArg)
.build()

GraphQLObjectType queryType = GraphQLObjectType.newObject()
.name("Query")
.field(field)
.build()

GraphQLSchema.newSchema()
.query(queryType)
.build()

then:
def invalidSchemaException = thrown(InvalidSchemaException)
invalidSchemaException.message.contains("Required argument 'input' on field 'field' cannot be deprecated")
}
}
Loading