public function printAST($ast)
{
return Visitor::visit($ast, ['leave' => [NodeKind::NAME => function (Node $node) {
return '' . $node->value;
}, NodeKind::VARIABLE => function ($node) {
return '$' . $node->name;
}, NodeKind::DOCUMENT => function (DocumentNode $node) {
return $this->join($node->definitions, "\n\n") . "\n";
}, NodeKind::OPERATION_DEFINITION => function (OperationDefinitionNode $node) {
$op = $node->operation;
$name = $node->name;
$varDefs = $this->wrap('(', $this->join($node->variableDefinitions, ', '), ')');
$directives = $this->join($node->directives, ' ');
$selectionSet = $node->selectionSet;
// Anonymous queries with no directives or variable definitions can use
// the query short form.
return !$name && !$directives && !$varDefs && $op === 'query' ? $selectionSet : $this->join([$op, $this->join([$name, $varDefs]), $directives, $selectionSet], ' ');
}, NodeKind::VARIABLE_DEFINITION => function (VariableDefinitionNode $node) {
return $node->variable . ': ' . $node->type . $this->wrap(' = ', $node->defaultValue);
}, NodeKind::SELECTION_SET => function (SelectionSetNode $node) {
return $this->block($node->selections);
}, NodeKind::FIELD => function (FieldNode $node) {
return $this->join([$this->wrap('', $node->alias, ': ') . $node->name . $this->wrap('(', $this->join($node->arguments, ', '), ')'), $this->join($node->directives, ' '), $node->selectionSet], ' ');
}, NodeKind::ARGUMENT => function (ArgumentNode $node) {
return $node->name . ': ' . $node->value;
}, NodeKind::FRAGMENT_SPREAD => function (FragmentSpreadNode $node) {
return '...' . $node->name . $this->wrap(' ', $this->join($node->directives, ' '));
}, NodeKind::INLINE_FRAGMENT => function (InlineFragmentNode $node) {
return $this->join(["...", $this->wrap('on ', $node->typeCondition), $this->join($node->directives, ' '), $node->selectionSet], ' ');
}, NodeKind::FRAGMENT_DEFINITION => function (FragmentDefinitionNode $node) {
return "fragment {$node->name} on {$node->typeCondition} " . $this->wrap('', $this->join($node->directives, ' '), ' ') . $node->selectionSet;
}, NodeKind::INT => function (IntValueNode $node) {
return $node->value;
}, NodeKind::FLOAT => function (FloatValueNode $node) {
return $node->value;
}, NodeKind::STRING => function (StringValueNode $node) {
return json_encode($node->value);
}, NodeKind::BOOLEAN => function (BooleanValueNode $node) {
return $node->value ? 'true' : 'false';
}, NodeKind::NULL => function (NullValueNode $node) {
return 'null';
}, NodeKind::ENUM => function (EnumValueNode $node) {
return $node->value;
}, NodeKind::LST => function (ListValueNode $node) {
return '[' . $this->join($node->values, ', ') . ']';
}, NodeKind::OBJECT => function (ObjectValueNode $node) {
return '{' . $this->join($node->fields, ', ') . '}';
}, NodeKind::OBJECT_FIELD => function (ObjectFieldNode $node) {
return $node->name . ': ' . $node->value;
}, NodeKind::DIRECTIVE => function (DirectiveNode $node) {
return '@' . $node->name . $this->wrap('(', $this->join($node->arguments, ', '), ')');
}, NodeKind::NAMED_TYPE => function (NamedTypeNode $node) {
return $node->name;
}, NodeKind::LIST_TYPE => function (ListTypeNode $node) {
return '[' . $node->type . ']';
}, NodeKind::NON_NULL_TYPE => function (NonNullTypeNode $node) {
return $node->type . '!';
}, NodeKind::SCHEMA_DEFINITION => function (SchemaDefinitionNode $def) {
return $this->join(['schema', $this->join($def->directives, ' '), $this->block($def->operationTypes)], ' ');
}, NodeKind::OPERATION_TYPE_DEFINITION => function (OperationTypeDefinitionNode $def) {
return $def->operation . ': ' . $def->type;
}, NodeKind::SCALAR_TYPE_DEFINITION => function (ScalarTypeDefinitionNode $def) {
return $this->join(['scalar', $def->name, $this->join($def->directives, ' ')], ' ');
}, NodeKind::OBJECT_TYPE_DEFINITION => function (ObjectTypeDefinitionNode $def) {
return $this->join(['type', $def->name, $this->wrap('implements ', $this->join($def->interfaces, ', ')), $this->join($def->directives, ' '), $this->block($def->fields)], ' ');
}, NodeKind::FIELD_DEFINITION => function (FieldDefinitionNode $def) {
return $def->name . $this->wrap('(', $this->join($def->arguments, ', '), ')') . ': ' . $def->type . $this->wrap(' ', $this->join($def->directives, ' '));
}, NodeKind::INPUT_VALUE_DEFINITION => function (InputValueDefinitionNode $def) {
return $this->join([$def->name . ': ' . $def->type, $this->wrap('= ', $def->defaultValue), $this->join($def->directives, ' ')], ' ');
}, NodeKind::INTERFACE_TYPE_DEFINITION => function (InterfaceTypeDefinitionNode $def) {
return $this->join(['interface', $def->name, $this->join($def->directives, ' '), $this->block($def->fields)], ' ');
}, NodeKind::UNION_TYPE_DEFINITION => function (UnionTypeDefinitionNode $def) {
return $this->join(['union', $def->name, $this->join($def->directives, ' '), '= ' . $this->join($def->types, ' | ')], ' ');
}, NodeKind::ENUM_TYPE_DEFINITION => function (EnumTypeDefinitionNode $def) {
return $this->join(['enum', $def->name, $this->join($def->directives, ' '), $this->block($def->values)], ' ');
}, NodeKind::ENUM_VALUE_DEFINITION => function (EnumValueDefinitionNode $def) {
return $this->join([$def->name, $this->join($def->directives, ' ')], ' ');
}, NodeKind::INPUT_OBJECT_TYPE_DEFINITION => function (InputObjectTypeDefinitionNode $def) {
return $this->join(['input', $def->name, $this->join($def->directives, ' '), $this->block($def->fields)], ' ');
}, NodeKind::TYPE_EXTENSION_DEFINITION => function (TypeExtensionDefinitionNode $def) {
return "extend {$def->definition}";
}, NodeKind::DIRECTIVE_DEFINITION => function (DirectiveDefinitionNode $def) {
return 'directive @' . $def->name . $this->wrap('(', $this->join($def->arguments, ', '), ')') . ' on ' . $this->join($def->locations, ' | ');
}]]);
}