Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
56 changes: 56 additions & 0 deletions src/main/java/graphql/Directives.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
import graphql.language.StringValue;
import graphql.schema.GraphQLDirective;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import static graphql.Scalars.GraphQLBoolean;
Expand Down Expand Up @@ -249,6 +254,57 @@ public class Directives {
.definition(EXPERIMENTAL_DISABLE_ERROR_PROPAGATION_DIRECTIVE_DEFINITION)
.build();

/**
* The set of all built-in directives that are always present in a graphql schema.
* The iteration order is stable and meaningful.
*/
public static final Set<GraphQLDirective> BUILT_IN_DIRECTIVES;

/**
* A map from directive name to directive for all built-in directives.
*/
public static final Map<String, GraphQLDirective> BUILT_IN_DIRECTIVES_MAP;

static {
LinkedHashSet<GraphQLDirective> directives = new LinkedHashSet<>();
directives.add(IncludeDirective);
directives.add(SkipDirective);
directives.add(DeprecatedDirective);
directives.add(SpecifiedByDirective);
directives.add(OneOfDirective);
directives.add(DeferDirective);
directives.add(ExperimentalDisableErrorPropagationDirective);
BUILT_IN_DIRECTIVES = Collections.unmodifiableSet(directives);

LinkedHashMap<String, GraphQLDirective> map = new LinkedHashMap<>();
for (GraphQLDirective d : BUILT_IN_DIRECTIVES) {
map.put(d.getName(), d);
}
BUILT_IN_DIRECTIVES_MAP = Collections.unmodifiableMap(map);
}

/**
* Returns true if a directive with the provided name is a built-in directive.
*
* @param directiveName the name of the directive in question
*
* @return true if the directive is built-in, false otherwise
*/
public static boolean isBuiltInDirective(String directiveName) {
return BUILT_IN_DIRECTIVES_MAP.containsKey(directiveName);
}

/**
* Returns true if the provided directive is a built-in directive.
*
* @param directive the directive in question
*
* @return true if the directive is built-in, false otherwise
*/
public static boolean isBuiltInDirective(GraphQLDirective directive) {
return isBuiltInDirective(directive.getName());
}

private static Description createDescription(String s) {
return new Description(s, null, false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
import static graphql.Assert.assertShouldNeverHappen;
import static graphql.Assert.assertTrue;
import static graphql.collect.ImmutableKit.map;
import static graphql.schema.idl.DirectiveInfo.isGraphqlSpecifiedDirective;
import static graphql.Directives.isBuiltInDirective;

@SuppressWarnings("unchecked")
@PublicApi
Expand Down Expand Up @@ -131,7 +131,7 @@ public Document createSchemaDefinition(Map<String, Object> introspectionResult)

private DirectiveDefinition createDirective(Map<String, Object> input) {
String directiveName = (String) input.get("name");
if (isGraphqlSpecifiedDirective(directiveName)) {
if (isBuiltInDirective(directiveName)) {
return null;
}

Expand Down
40 changes: 18 additions & 22 deletions src/main/java/graphql/schema/GraphQLSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import static graphql.collect.ImmutableKit.nonNullCopyOf;
import static graphql.schema.GraphqlTypeComparators.byNameAsc;
import static graphql.schema.GraphqlTypeComparators.sortTypes;
import static java.util.Arrays.asList;


/**
* The schema represents the combined type system of the graphql engine. This is how the engine knows
Expand Down Expand Up @@ -692,7 +692,6 @@ public static Builder newSchema(GraphQLSchema existingSchema) {
.introspectionSchemaType(existingSchema.getIntrospectionSchemaType())
.codeRegistry(existingSchema.getCodeRegistry())
.clearAdditionalTypes()
.clearDirectives()
.additionalDirectives(new LinkedHashSet<>(existingSchema.getDirectives()))
.clearSchemaDirectives()
.withSchemaDirectives(schemaDirectivesArray(existingSchema))
Expand Down Expand Up @@ -741,10 +740,7 @@ public static class Builder {
private List<SchemaExtensionDefinition> extensionDefinitions;
private String description;

// we default these in
private final Set<GraphQLDirective> additionalDirectives = new LinkedHashSet<>(
asList(Directives.IncludeDirective, Directives.SkipDirective)
);
private final Set<GraphQLDirective> additionalDirectives = new LinkedHashSet<>();
private final Set<GraphQLNamedType> additionalTypes = new LinkedHashSet<>();
private final List<GraphQLDirective> schemaDirectives = new ArrayList<>();
private final List<GraphQLAppliedDirective> schemaAppliedDirectives = new ArrayList<>();
Expand Down Expand Up @@ -862,12 +858,6 @@ public Builder additionalDirective(GraphQLDirective additionalDirective) {
return this;
}

public Builder clearDirectives() {
this.additionalDirectives.clear();
return this;
}


public Builder withSchemaDirectives(GraphQLDirective... directives) {
for (GraphQLDirective directive : directives) {
withSchemaDirective(directive);
Expand Down Expand Up @@ -960,13 +950,8 @@ private GraphQLSchema buildImpl() {
assertNotNull(additionalTypes, "additionalTypes can't be null");
assertNotNull(additionalDirectives, "additionalDirectives can't be null");

// schemas built via the schema generator have the deprecated directive BUT we want it present for hand built
// schemas - it's inherently part of the spec!
addBuiltInDirective(Directives.DeprecatedDirective, additionalDirectives);
addBuiltInDirective(Directives.SpecifiedByDirective, additionalDirectives);
addBuiltInDirective(Directives.OneOfDirective, additionalDirectives);
addBuiltInDirective(Directives.DeferDirective, additionalDirectives);
addBuiltInDirective(Directives.ExperimentalDisableErrorPropagationDirective, additionalDirectives);
// built-in directives are always present in a schema and come first
ensureBuiltInDirectives();

// quick build - no traversing
final GraphQLSchema partiallyBuiltSchema = new GraphQLSchema(this);
Expand All @@ -989,10 +974,21 @@ private GraphQLSchema buildImpl() {
return validateSchema(finalSchema);
}

private void addBuiltInDirective(GraphQLDirective qlDirective, Set<GraphQLDirective> additionalDirectives1) {
if (additionalDirectives1.stream().noneMatch(d -> d.getName().equals(qlDirective.getName()))) {
additionalDirectives1.add(qlDirective);
private void ensureBuiltInDirectives() {
// put built-in directives first, preserving user-supplied overrides by name
Set<String> userDirectiveNames = new LinkedHashSet<>();
for (GraphQLDirective d : additionalDirectives) {
userDirectiveNames.add(d.getName());
}
LinkedHashSet<GraphQLDirective> ordered = new LinkedHashSet<>();
for (GraphQLDirective builtIn : Directives.BUILT_IN_DIRECTIVES) {
if (!userDirectiveNames.contains(builtIn.getName())) {
ordered.add(builtIn);
}
}
ordered.addAll(additionalDirectives);
additionalDirectives.clear();
additionalDirectives.addAll(ordered);
}

private GraphQLSchema validateSchema(GraphQLSchema graphQLSchema) {
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/graphql/schema/GraphQLTypeUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import graphql.Assert;
import graphql.PublicApi;
import graphql.introspection.Introspection;
import graphql.schema.idl.DirectiveInfo;
import graphql.Directives;
import graphql.schema.idl.ScalarInfo;

import java.util.Stack;
Expand Down Expand Up @@ -293,7 +293,7 @@ public static Predicate<GraphQLNamedSchemaElement> isSystemElement() {
return ScalarInfo.isGraphqlSpecifiedScalar((GraphQLScalarType) schemaElement);
}
if (schemaElement instanceof GraphQLDirective) {
return DirectiveInfo.isGraphqlSpecifiedDirective((GraphQLDirective) schemaElement);
return Directives.isBuiltInDirective((GraphQLDirective) schemaElement);
}
if (schemaElement instanceof GraphQLNamedType) {
return Introspection.isIntrospectionTypes((GraphQLNamedType) schemaElement);
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/graphql/schema/diffing/SchemaGraphFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import graphql.introspection.Introspection;
import graphql.language.AstPrinter;
import graphql.schema.*;
import graphql.schema.idl.DirectiveInfo;
import graphql.Directives;
import graphql.schema.idl.ScalarInfo;
import graphql.util.TraversalControl;
import graphql.util.Traverser;
Expand Down Expand Up @@ -390,7 +390,7 @@ private void newDirective(GraphQLDirective directive, SchemaGraph schemaGraph) {
directiveVertex.add("name", directive.getName());
directiveVertex.add("repeatable", directive.isRepeatable());
directiveVertex.add("locations", directive.validLocations());
boolean graphqlSpecified = DirectiveInfo.isGraphqlSpecifiedDirective(directive.getName());
boolean graphqlSpecified = Directives.isBuiltInDirective(directive.getName());
directiveVertex.setBuiltInType(graphqlSpecified);
directiveVertex.add("description", desc(directive.getDescription()));
for (GraphQLArgument argument : directive.getArguments()) {
Expand Down
61 changes: 0 additions & 61 deletions src/main/java/graphql/schema/idl/DirectiveInfo.java

This file was deleted.

19 changes: 17 additions & 2 deletions src/main/java/graphql/schema/idl/SchemaPrinter.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package graphql.schema.idl;

import graphql.Assert;
import graphql.Directives;
import graphql.DirectivesUtil;
import graphql.GraphQLContext;
import graphql.PublicApi;
Expand Down Expand Up @@ -64,6 +65,7 @@
import java.util.stream.Stream;

import static graphql.Directives.DeprecatedDirective;
import static graphql.Directives.SpecifiedByDirective;
import static graphql.Scalars.GraphQLString;
import static graphql.schema.visibility.DefaultGraphqlFieldVisibility.DEFAULT_FIELD_VISIBILITY;
import static graphql.util.EscapeUtil.escapeJsonString;
Expand All @@ -80,7 +82,7 @@ public class SchemaPrinter {
* This predicate excludes all directives which are specified by the GraphQL Specification.
* Printing these directives is optional.
*/
public static final Predicate<String> ExcludeGraphQLSpecifiedDirectivesPredicate = d -> !DirectiveInfo.isGraphqlSpecifiedDirective(d);
public static final Predicate<String> ExcludeGraphQLSpecifiedDirectivesPredicate = d -> !Directives.isBuiltInDirective(d);

/**
* Options to use when printing a schema
Expand Down Expand Up @@ -559,7 +561,12 @@ private SchemaElementPrinter<GraphQLScalarType> scalarPrinter() {
printAsAst(out, type.getDefinition(), type.getExtensionDefinitions());
} else {
printComments(out, type, "");
out.format("scalar %s%s\n\n", type.getName(), directivesString(GraphQLScalarType.class, type));
List<GraphQLAppliedDirective> directives = DirectivesUtil.toAppliedDirectives(type).stream()
.filter(d -> !d.getName().equals(SpecifiedByDirective.getName()))
.collect(toList());
out.format("scalar %s%s%s\n\n", type.getName(),
directivesString(GraphQLScalarType.class, directives),
specifiedByUrlString(type));
}
}
};
Expand Down Expand Up @@ -1103,6 +1110,14 @@ private String getDeprecationReason(GraphQLDirectiveContainer directiveContainer
}
}

private String specifiedByUrlString(GraphQLScalarType scalarType) {
String url = scalarType.getSpecifiedByUrl();
if (url == null || !options.getIncludeDirective().test(SpecifiedByDirective.getName())) {
return "";
}
return " @specifiedBy(url : \"" + escapeJsonString(url) + "\")";
}

private String directiveDefinition(GraphQLDirective directive) {
StringBuilder sb = new StringBuilder();

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/graphql/schema/usage/SchemaUsage.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import graphql.schema.GraphQLNamedType;
import graphql.schema.GraphQLObjectType;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.DirectiveInfo;
import graphql.Directives;
import graphql.schema.idl.ScalarInfo;

import java.util.HashSet;
Expand Down Expand Up @@ -180,7 +180,7 @@ private boolean isReferencedImpl(GraphQLSchema schema, String elementName, Set<S
GraphQLDirective directive = schema.getDirective(elementName);
if (directive != null) {
String directiveName = directive.getName();
if (DirectiveInfo.isGraphqlSpecifiedDirective(directiveName)) {
if (Directives.isBuiltInDirective(directiveName)) {
return true;
}
if (isNamedElementReferenced(schema, directiveName, pathSoFar)) {
Expand Down
9 changes: 4 additions & 5 deletions src/main/java/graphql/util/Anonymizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
import graphql.schema.GraphQLUnionType;
import graphql.schema.SchemaTransformer;
import graphql.schema.TypeResolver;
import graphql.schema.idl.DirectiveInfo;
import graphql.schema.idl.ScalarInfo;
import graphql.schema.idl.TypeUtil;
import graphql.schema.impl.SchemaUtil;
Expand Down Expand Up @@ -259,7 +258,7 @@ public TraversalControl visitGraphQLFieldDefinition(GraphQLFieldDefinition graph

@Override
public TraversalControl visitGraphQLDirective(GraphQLDirective graphQLDirective, TraverserContext<GraphQLSchemaElement> context) {
if (DirectiveInfo.isGraphqlSpecifiedDirective(graphQLDirective.getName())) {
if (Directives.isBuiltInDirective(graphQLDirective.getName())) {
return TraversalControl.ABORT;
}
String newName = assertNotNull(newNameMap.get(graphQLDirective));
Expand All @@ -282,7 +281,7 @@ public TraversalControl visitGraphQLAppliedDirective(GraphQLAppliedDirective gra
changeNode(context, newElement);
return TraversalControl.ABORT;
}
if (DirectiveInfo.isGraphqlSpecifiedDirective(graphQLDirective.getName())) {
if (Directives.isBuiltInDirective(graphQLDirective.getName())) {
return TraversalControl.ABORT;
}
String newName = assertNotNull(newNameMap.get(graphQLDirective));
Expand Down Expand Up @@ -516,7 +515,7 @@ public TraversalControl visitGraphQLAppliedDirectiveArgument(GraphQLAppliedDirec

@Override
public TraversalControl visitGraphQLDirective(GraphQLDirective graphQLDirective, TraverserContext<GraphQLSchemaElement> context) {
if (DirectiveInfo.isGraphqlSpecifiedDirective(graphQLDirective)) {
if (Directives.isBuiltInDirective(graphQLDirective)) {
return TraversalControl.ABORT;
}
recordDirectiveName.accept(graphQLDirective);
Expand All @@ -525,7 +524,7 @@ public TraversalControl visitGraphQLDirective(GraphQLDirective graphQLDirective,

@Override
public TraversalControl visitGraphQLAppliedDirective(GraphQLAppliedDirective graphQLAppliedDirective, TraverserContext<GraphQLSchemaElement> context) {
if (DirectiveInfo.isGraphqlSpecifiedDirective(graphQLAppliedDirective.getName())) {
if (Directives.isBuiltInDirective(graphQLAppliedDirective.getName())) {
return TraversalControl.ABORT;
}
recordDirectiveName.accept(graphQLAppliedDirective);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,6 @@ class JSpecifyAnnotationsCheck extends Specification {
"graphql.schema.diff.reporting.PrintStreamReporter",
"graphql.schema.diffing.SchemaGraph",
"graphql.schema.idl.CombinedWiringFactory",
"graphql.schema.idl.DirectiveInfo",
"graphql.schema.idl.MapEnumValuesProvider",
"graphql.schema.idl.NaturalEnumValuesProvider",
"graphql.schema.idl.RuntimeWiring",
Expand Down
Loading
Loading