public function __invoke(ValidationContext $context)
{
return [NodeKind::OPERATION_DEFINITION => ['enter' => function () {
$this->varDefMap = [];
}, 'leave' => function (OperationDefinitionNode $operation) use($context) {
$usages = $context->getRecursiveVariableUsages($operation);
foreach ($usages as $usage) {
$node = $usage['node'];
$type = $usage['type'];
$varName = $node->name->value;
$varDef = isset($this->varDefMap[$varName]) ? $this->varDefMap[$varName] : null;
if ($varDef && $type) {
// A var type is allowed if it is the same or more strict (e.g. is
// a subtype of) than the expected type. It can be more strict if
// the variable type is non-null when the expected type is nullable.
// If both are list types, the variable item type can be more strict
// than the expected item type (contravariant).
$schema = $context->getSchema();
$varType = TypeInfo::typeFromAST($schema, $varDef->type);
if ($varType && !TypeInfo::isTypeSubTypeOf($schema, $this->effectiveType($varType, $varDef), $type)) {
$context->reportError(new Error(self::badVarPosMessage($varName, $varType, $type), [$varDef, $node]));
}
}
}
}], NodeKind::VARIABLE_DEFINITION => function (VariableDefinitionNode $varDefNode) {
$this->varDefMap[$varDefNode->variable->name->value] = $varDefNode;
}];
}