44import graphql .Internal ;
55import graphql .language .Argument ;
66import graphql .language .Directive ;
7+ import graphql .language .DirectiveDefinition ;
78import graphql .language .EnumTypeDefinition ;
89import graphql .language .EnumValueDefinition ;
910import graphql .language .FieldDefinition ;
3233import java .util .function .Consumer ;
3334import java .util .stream .Collectors ;
3435
36+ import static graphql .DirectivesUtil .nonRepeatableDirectivesOnly ;
3537import static graphql .schema .idl .SchemaTypeChecker .checkNamedUniqueness ;
3638import static graphql .util .FpKit .mergeFirst ;
3739
4345class SchemaTypeExtensionsChecker {
4446
4547 void checkTypeExtensions (List <GraphQLError > errors , TypeDefinitionRegistry typeRegistry ) {
46- checkObjectTypeExtensions (errors , typeRegistry );
47- checkInterfaceTypeExtensions (errors , typeRegistry );
48+ Map <String , DirectiveDefinition > directiveDefinitionMap = typeRegistry .getDirectiveDefinitions ();
49+ checkObjectTypeExtensions (errors , typeRegistry ,directiveDefinitionMap );
50+ checkInterfaceTypeExtensions (errors , typeRegistry ,directiveDefinitionMap );
4851 checkUnionTypeExtensions (errors , typeRegistry );
4952 checkEnumTypeExtensions (errors , typeRegistry );
5053 checkScalarTypeExtensions (errors , typeRegistry );
51- checkInputObjectTypeExtensions (errors , typeRegistry );
54+ checkInputObjectTypeExtensions (errors , typeRegistry , directiveDefinitionMap );
5255 }
5356
5457
@@ -62,7 +65,7 @@ void checkTypeExtensions(List<GraphQLError> errors, TypeDefinitionRegistry typeR
6265 * Any interfaces provided must not be already implemented by the original Object type.
6366 * The resulting extended object type must be a super-set of all interfaces it implements.
6467 */
65- private void checkObjectTypeExtensions (List <GraphQLError > errors , TypeDefinitionRegistry typeRegistry ) {
68+ private void checkObjectTypeExtensions (List <GraphQLError > errors , TypeDefinitionRegistry typeRegistry , Map < String , DirectiveDefinition > directiveDefinitionMap ) {
6669 typeRegistry .objectTypeExtensions ()
6770 .forEach ((name , extensions ) -> {
6871 checkTypeExtensionHasCorrespondingType (errors , typeRegistry , name , extensions , ObjectTypeDefinition .class );
@@ -79,7 +82,7 @@ private void checkObjectTypeExtensions(List<GraphQLError> errors, TypeDefinition
7982 (namedField , inputValueDefinition ) -> new NonUniqueArgumentError (extension , fld , name )));
8083
8184 // directive checks
82- extension .getFieldDefinitions ().forEach (fld -> checkNamedUniqueness (errors , fld .getDirectives (), Directive ::getName ,
85+ extension .getFieldDefinitions ().forEach (fld -> checkNamedUniqueness (errors , nonRepeatableDirectivesOnly ( directiveDefinitionMap , fld .getDirectives () ), Directive ::getName ,
8386 (directiveName , directive ) -> new NonUniqueDirectiveError (extension , fld , directiveName )));
8487
8588 fieldDefinitions .forEach (fld -> fld .getDirectives ().forEach (directive ->
@@ -101,7 +104,6 @@ private void checkObjectTypeExtensions(List<GraphQLError> errors, TypeDefinition
101104 );
102105 }
103106
104-
105107 /*
106108 * Interface type extensions have the potential to be invalid if incorrectly defined.
107109 *
@@ -111,7 +113,7 @@ private void checkObjectTypeExtensions(List<GraphQLError> errors, TypeDefinition
111113 * Any Object type which implemented the original Interface type must also be a super-set of the fields of the Interface type extension (which may be due to Object type extension).
112114 * Any directives provided must not already apply to the original Interface type.
113115 */
114- private void checkInterfaceTypeExtensions (List <GraphQLError > errors , TypeDefinitionRegistry typeRegistry ) {
116+ private void checkInterfaceTypeExtensions (List <GraphQLError > errors , TypeDefinitionRegistry typeRegistry , Map < String , DirectiveDefinition > directiveDefinitionMap ) {
115117 typeRegistry .interfaceTypeExtensions ()
116118 .forEach ((name , extensions ) -> {
117119 checkTypeExtensionHasCorrespondingType (errors , typeRegistry , name , extensions , InterfaceTypeDefinition .class );
@@ -128,7 +130,7 @@ private void checkInterfaceTypeExtensions(List<GraphQLError> errors, TypeDefinit
128130 (namedField , inputValueDefinition ) -> new NonUniqueArgumentError (extension , fld , name )));
129131
130132 // directive checks
131- extension .getFieldDefinitions ().forEach (fld -> checkNamedUniqueness (errors , fld .getDirectives (), Directive ::getName ,
133+ extension .getFieldDefinitions ().forEach (fld -> checkNamedUniqueness (errors , nonRepeatableDirectivesOnly ( directiveDefinitionMap , fld .getDirectives () ), Directive ::getName ,
132134 (directiveName , directive ) -> new NonUniqueDirectiveError (extension , fld , directiveName )));
133135
134136 fieldDefinitions .forEach (fld -> fld .getDirectives ().forEach (directive ->
@@ -242,7 +244,7 @@ private void checkScalarTypeExtensions(List<GraphQLError> errors, TypeDefinition
242244 * All fields of an Input Object type extension must not already be a field of the original Input Object.
243245 * Any directives provided must not already apply to the original Input Object type.
244246 */
245- private void checkInputObjectTypeExtensions (List <GraphQLError > errors , TypeDefinitionRegistry typeRegistry ) {
247+ private void checkInputObjectTypeExtensions (List <GraphQLError > errors , TypeDefinitionRegistry typeRegistry , Map < String , DirectiveDefinition > directiveDefinitionMap ) {
246248 typeRegistry .inputObjectTypeExtensions ()
247249 .forEach ((name , extensions ) -> {
248250 checkTypeExtensionHasCorrespondingType (errors , typeRegistry , name , extensions , InputObjectTypeDefinition .class );
@@ -255,7 +257,7 @@ private void checkInputObjectTypeExtensions(List<GraphQLError> errors, TypeDefin
255257 (namedField , fieldDef ) -> new NonUniqueNameError (extension , fieldDef ));
256258
257259 // directive checks
258- inputValueDefinitions .forEach (fld -> checkNamedUniqueness (errors , fld .getDirectives (), Directive ::getName ,
260+ inputValueDefinitions .forEach (fld -> checkNamedUniqueness (errors , nonRepeatableDirectivesOnly ( directiveDefinitionMap , fld .getDirectives () ), Directive ::getName ,
259261 (directiveName , directive ) -> new NonUniqueDirectiveError (extension , fld , directiveName )));
260262
261263 inputValueDefinitions .forEach (fld -> fld .getDirectives ().forEach (directive ->
0 commit comments