getASTVisitor($context); } public function getSDLVisitor(SDLValidationContext $context) { return $this->getASTVisitor($context); } public function getASTVisitor(ASTValidationContext $context) { /** @var array $uniqueDirectiveMap */ $uniqueDirectiveMap = []; $schema = $context->getSchema(); $definedDirectives = $schema !== null ? $schema->getDirectives() : Directive::getInternalDirectives(); foreach ($definedDirectives as $directive) { if ($directive->isRepeatable) { continue; } $uniqueDirectiveMap[$directive->name] = true; } $astDefinitions = $context->getDocument()->definitions; foreach ($astDefinitions as $definition) { if (! ($definition instanceof DirectiveDefinitionNode) || $definition->repeatable ) { continue; } $uniqueDirectiveMap[$definition->name->value] = true; } return [ 'enter' => static function (Node $node) use ($uniqueDirectiveMap, $context) : void { if (! isset($node->directives)) { return; } $knownDirectives = []; /** @var DirectiveNode $directive */ foreach ($node->directives as $directive) { $directiveName = $directive->name->value; if (! isset($uniqueDirectiveMap[$directiveName])) { continue; } if (isset($knownDirectives[$directiveName])) { $context->reportError(new Error( self::duplicateDirectiveMessage($directiveName), [$knownDirectives[$directiveName], $directive] )); } else { $knownDirectives[$directiveName] = $directive; } } }, ]; } public static function duplicateDirectiveMessage($directiveName) { return sprintf('The directive "%s" can only be used once at this location.', $directiveName); } }