public function __invoke(ValidationContext $context) { $operation = null; $visitedFragmentNames = []; $definedVariableNames = []; return ['visitSpreadFragments' => true, Node::OPERATION_DEFINITION => function (OperationDefinition $node, $key, $parent, $path, $ancestors) use(&$operation, &$visitedFragmentNames, &$definedVariableNames) { $operation = $node; $visitedFragmentNames = []; $definedVariableNames = []; }, Node::VARIABLE_DEFINITION => function (VariableDefinition $def) use(&$definedVariableNames) { $definedVariableNames[$def->variable->name->value] = true; }, Node::VARIABLE => function (Variable $variable, $key, $parent, $path, $ancestors) use(&$definedVariableNames, &$visitedFragmentNames, &$operation) { $varName = $variable->name->value; if (empty($definedVariableNames[$varName])) { $withinFragment = false; foreach ($ancestors as $ancestor) { if ($ancestor instanceof FragmentDefinition) { $withinFragment = true; break; } } if ($withinFragment && $operation && $operation->name) { return new Error(Messages::undefinedVarByOpMessage($varName, $operation->name->value), [$variable, $operation]); } return new Error(Messages::undefinedVarMessage($varName), [$variable]); } }, Node::FRAGMENT_SPREAD => function (FragmentSpread $spreadAST) use(&$visitedFragmentNames) { // Only visit fragments of a particular name once per operation if (!empty($visitedFragmentNames[$spreadAST->name->value])) { return Visitor::skipNode(); } $visitedFragmentNames[$spreadAST->name->value] = true; }]; }
private function undefVarByOp($varName, $l1, $c1, $opName, $l2, $c2) { return new FormattedError(Messages::undefinedVarByOpMessage($varName, $opName), [new SourceLocation($l1, $c1), new SourceLocation($l2, $c2)]); }