This commit is contained in:
Your Name
2021-07-26 19:46:18 +02:00
parent e7a49138bb
commit aae17f10a6
818 changed files with 70695 additions and 16408 deletions
@@ -9,7 +9,7 @@ class ArgumentNode extends Node
/** @var string */
public $kind = NodeKind::ARGUMENT;
/** @var ValueNode */
/** @var VariableNode|NullValueNode|IntValueNode|FloatValueNode|StringValueNode|BooleanValueNode|EnumValueNode|ListValueNode|ObjectValueNode */
public $value;
/** @var NameNode */
@@ -7,7 +7,7 @@ namespace GraphQL\Language\AST;
/**
* export type DefinitionNode =
* | ExecutableDefinitionNode
* | TypeSystemDefinitionNode; // experimental non-spec addition.
* | TypeSystemDefinitionNode;
*/
interface DefinitionNode
{
@@ -12,12 +12,15 @@ class DirectiveDefinitionNode extends Node implements TypeSystemDefinitionNode
/** @var NameNode */
public $name;
/** @var ArgumentNode[] */
public $arguments;
/** @var NameNode[] */
public $locations;
/** @var StringValueNode|null */
public $description;
/** @var NodeList<InputValueDefinitionNode> */
public $arguments;
/** @var bool */
public $repeatable;
/** @var NodeList<NameNode> */
public $locations;
}
@@ -12,6 +12,6 @@ class DirectiveNode extends Node
/** @var NameNode */
public $name;
/** @var ArgumentNode[] */
/** @var NodeList<ArgumentNode> */
public $arguments;
}
@@ -9,6 +9,6 @@ class DocumentNode extends Node
/** @var string */
public $kind = NodeKind::DOCUMENT;
/** @var NodeList|DefinitionNode[] */
/** @var NodeList<DefinitionNode&Node> */
public $definitions;
}
@@ -12,10 +12,10 @@ class EnumTypeDefinitionNode extends Node implements TypeDefinitionNode
/** @var NameNode */
public $name;
/** @var DirectiveNode[] */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var EnumValueDefinitionNode[]|NodeList|null */
/** @var NodeList<EnumValueDefinitionNode> */
public $values;
/** @var StringValueNode|null */
@@ -12,9 +12,9 @@ class EnumTypeExtensionNode extends Node implements TypeExtensionNode
/** @var NameNode */
public $name;
/** @var DirectiveNode[]|null */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var EnumValueDefinitionNode[]|null */
/** @var NodeList<EnumValueDefinitionNode> */
public $values;
}
@@ -12,7 +12,7 @@ class EnumValueDefinitionNode extends Node
/** @var NameNode */
public $name;
/** @var DirectiveNode[] */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var StringValueNode|null */
@@ -12,13 +12,13 @@ class FieldDefinitionNode extends Node
/** @var NameNode */
public $name;
/** @var InputValueDefinitionNode[]|NodeList */
/** @var NodeList<InputValueDefinitionNode> */
public $arguments;
/** @var TypeNode */
/** @var NamedTypeNode|ListTypeNode|NonNullTypeNode */
public $type;
/** @var DirectiveNode[]|NodeList */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var StringValueNode|null */
+2 -2
View File
@@ -15,10 +15,10 @@ class FieldNode extends Node implements SelectionNode
/** @var NameNode|null */
public $alias;
/** @var ArgumentNode[]|null */
/** @var NodeList<ArgumentNode> */
public $arguments;
/** @var DirectiveNode[]|null */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var SelectionSetNode|null */
@@ -16,14 +16,14 @@ class FragmentDefinitionNode extends Node implements ExecutableDefinitionNode, H
* Note: fragment variable definitions are experimental and may be changed
* or removed in the future.
*
* @var VariableDefinitionNode[]|NodeList
* @var NodeList<VariableDefinitionNode>
*/
public $variableDefinitions;
/** @var NamedTypeNode */
public $typeCondition;
/** @var DirectiveNode[]|NodeList */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var SelectionSetNode */
@@ -12,6 +12,6 @@ class FragmentSpreadNode extends Node implements SelectionNode
/** @var NameNode */
public $name;
/** @var DirectiveNode[] */
/** @var NodeList<DirectiveNode> */
public $directives;
}
@@ -4,10 +4,12 @@ declare(strict_types=1);
namespace GraphQL\Language\AST;
/**
* export type DefinitionNode = OperationDefinitionNode
* | FragmentDefinitionNode
*
* @property SelectionSetNode $selectionSet
*/
interface HasSelectionSet
{
/**
* export type DefinitionNode = OperationDefinitionNode
* | FragmentDefinitionNode
*/
}
@@ -12,7 +12,7 @@ class InlineFragmentNode extends Node implements SelectionNode
/** @var NamedTypeNode */
public $typeCondition;
/** @var DirectiveNode[]|null */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var SelectionSetNode */
@@ -12,10 +12,10 @@ class InputObjectTypeDefinitionNode extends Node implements TypeDefinitionNode
/** @var NameNode */
public $name;
/** @var DirectiveNode[]|null */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var InputValueDefinitionNode[]|null */
/** @var NodeList<InputValueDefinitionNode> */
public $fields;
/** @var StringValueNode|null */
@@ -12,9 +12,9 @@ class InputObjectTypeExtensionNode extends Node implements TypeExtensionNode
/** @var NameNode */
public $name;
/** @var DirectiveNode[]|null */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var InputValueDefinitionNode[]|null */
/** @var NodeList<InputValueDefinitionNode> */
public $fields;
}
@@ -12,13 +12,13 @@ class InputValueDefinitionNode extends Node
/** @var NameNode */
public $name;
/** @var TypeNode */
/** @var NamedTypeNode|ListTypeNode|NonNullTypeNode */
public $type;
/** @var ValueNode */
/** @var VariableNode|NullValueNode|IntValueNode|FloatValueNode|StringValueNode|BooleanValueNode|EnumValueNode|ListValueNode|ObjectValueNode|null */
public $defaultValue;
/** @var DirectiveNode[] */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var StringValueNode|null */
@@ -12,10 +12,13 @@ class InterfaceTypeDefinitionNode extends Node implements TypeDefinitionNode
/** @var NameNode */
public $name;
/** @var DirectiveNode[]|null */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var FieldDefinitionNode[]|null */
/** @var NodeList<NamedTypeNode> */
public $interfaces;
/** @var NodeList<FieldDefinitionNode> */
public $fields;
/** @var StringValueNode|null */
@@ -12,9 +12,12 @@ class InterfaceTypeExtensionNode extends Node implements TypeExtensionNode
/** @var NameNode */
public $name;
/** @var DirectiveNode[]|null */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var FieldDefinitionNode[]|null */
/** @var NodeList<InterfaceTypeDefinitionNode> */
public $interfaces;
/** @var NodeList<FieldDefinitionNode> */
public $fields;
}
@@ -9,6 +9,6 @@ class ListTypeNode extends Node implements TypeNode
/** @var string */
public $kind = NodeKind::LIST_TYPE;
/** @var Node */
/** @var NamedTypeNode|ListTypeNode|NonNullTypeNode */
public $type;
}
@@ -9,6 +9,6 @@ class ListValueNode extends Node implements ValueNode
/** @var string */
public $kind = NodeKind::LST;
/** @var ValueNode[]|NodeList */
/** @var NodeList<ValueNode&Node> */
public $values;
}
+3 -3
View File
@@ -30,14 +30,14 @@ class Location
/**
* The Token at which this Node begins.
*
* @var Token
* @var Token|null
*/
public $startToken;
/**
* The Token at which this Node ends.
*
* @var Token
* @var Token|null
*/
public $endToken;
@@ -69,7 +69,7 @@ class Location
$this->endToken = $endToken;
$this->source = $source;
if (! $startToken || ! $endToken) {
if ($startToken === null || $endToken === null) {
return;
}
+10 -11
View File
@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace GraphQL\Language\AST;
use GraphQL\Utils\Utils;
use function count;
use function get_object_vars;
use function is_array;
use function is_scalar;
@@ -36,15 +37,18 @@ use function json_encode;
*/
abstract class Node
{
/** @var Location */
/** @var Location|null */
public $loc;
/** @var string */
public $kind;
/**
* @param (NameNode|NodeList|SelectionSetNode|Location|string|int|bool|float|null)[] $vars
*/
public function __construct(array $vars)
{
if (empty($vars)) {
if (count($vars) === 0) {
return;
}
@@ -83,10 +87,7 @@ abstract class Node
return $cloned;
}
/**
* @return string
*/
public function __toString()
public function __toString() : string
{
$tmp = $this->toArray(true);
@@ -94,11 +95,9 @@ abstract class Node
}
/**
* @param bool $recursive
*
* @return mixed[]
*/
public function toArray($recursive = false)
public function toArray(bool $recursive = false) : array
{
if ($recursive) {
return $this->recursiveToArray($this);
@@ -106,7 +105,7 @@ abstract class Node
$tmp = (array) $this;
if ($this->loc) {
if ($this->loc !== null) {
$tmp['loc'] = [
'start' => $this->loc->start,
'end' => $this->loc->end,
@@ -125,7 +124,7 @@ abstract class Node
'kind' => $node->kind,
];
if ($node->loc) {
if ($node->loc !== null) {
$result['loc'] = [
'start' => $node->loc->start,
'end' => $node->loc->end,
+58 -35
View File
@@ -6,31 +6,43 @@ namespace GraphQL\Language\AST;
use ArrayAccess;
use Countable;
use Generator;
use GraphQL\Utils\AST;
use InvalidArgumentException;
use IteratorAggregate;
use Traversable;
use function array_merge;
use function array_splice;
use function count;
use function is_array;
/**
* @template T of Node
* @phpstan-implements ArrayAccess<int|string, T>
* @phpstan-implements IteratorAggregate<T>
*/
class NodeList implements ArrayAccess, IteratorAggregate, Countable
{
/** @var Node[]|mixed[] */
/**
* @var Node[]
* @phpstan-var array<T>
*/
private $nodes;
/**
* @param Node[]|mixed[] $nodes
* @param Node[] $nodes
*
* @return static
* @phpstan-param array<T> $nodes
* @phpstan-return self<T>
*/
public static function create(array $nodes)
public static function create(array $nodes) : self
{
return new static($nodes);
}
/**
* @param Node[]|mixed[] $nodes
* @param Node[] $nodes
*
* @phpstan-param array<T> $nodes
*/
public function __construct(array $nodes)
{
@@ -38,59 +50,75 @@ class NodeList implements ArrayAccess, IteratorAggregate, Countable
}
/**
* @param mixed $offset
*
* @return bool
* @param int|string $offset
*/
public function offsetExists($offset)
public function offsetExists($offset) : bool
{
return isset($this->nodes[$offset]);
}
/**
* @param mixed $offset
* TODO enable strict typing by changing how the Visitor deals with NodeList.
* Ideally, this function should always return a Node instance.
* However, the Visitor currently allows mutation of the NodeList
* and puts arbitrary values in the NodeList, such as strings.
* We will have to switch to using an array or a less strict
* type instead so we can enable strict typing in this class.
*
* @return mixed
* @param int|string $offset
*
* @phpstan-return T
*/
public function offsetGet($offset)
public function offsetGet($offset)// : Node
{
$item = $this->nodes[$offset];
if (is_array($item) && isset($item['kind'])) {
$this->nodes[$offset] = $item = AST::fromArray($item);
/** @phpstan-var T $node */
$node = AST::fromArray($item);
$this->nodes[$offset] = $node;
}
return $item;
return $this->nodes[$offset];
}
/**
* @param mixed $offset
* @param mixed $value
* @param int|string|null $offset
* @param Node|mixed[] $value
*
* @phpstan-param T|mixed[] $value
*/
public function offsetSet($offset, $value)
public function offsetSet($offset, $value) : void
{
if (is_array($value) && isset($value['kind'])) {
if (is_array($value)) {
/** @phpstan-var T $value */
$value = AST::fromArray($value);
}
// Happens when a Node is pushed via []=
if ($offset === null) {
$this->nodes[] = $value;
return;
}
$this->nodes[$offset] = $value;
}
/**
* @param mixed $offset
* @param int|string $offset
*/
public function offsetUnset($offset)
public function offsetUnset($offset) : void
{
unset($this->nodes[$offset]);
}
/**
* @param int $offset
* @param int $length
* @param mixed $replacement
*
* @return NodeList
* @phpstan-return NodeList<T>
*/
public function splice($offset, $length, $replacement = null)
public function splice(int $offset, int $length, $replacement = null) : NodeList
{
return new NodeList(array_splice($this->nodes, $offset, $length, $replacement));
}
@@ -98,9 +126,10 @@ class NodeList implements ArrayAccess, IteratorAggregate, Countable
/**
* @param NodeList|Node[] $list
*
* @return NodeList
* @phpstan-param NodeList<T>|array<T> $list
* @phpstan-return NodeList<T>
*/
public function merge($list)
public function merge($list) : NodeList
{
if ($list instanceof self) {
$list = $list->nodes;
@@ -109,20 +138,14 @@ class NodeList implements ArrayAccess, IteratorAggregate, Countable
return new NodeList(array_merge($this->nodes, $list));
}
/**
* @return Generator
*/
public function getIterator()
public function getIterator() : Traversable
{
foreach ($this->nodes as $key => $_) {
yield $this->offsetGet($key);
}
}
/**
* @return int
*/
public function count()
public function count() : int
{
return count($this->nodes);
}
@@ -9,6 +9,6 @@ class NonNullTypeNode extends Node implements TypeNode
/** @var string */
public $kind = NodeKind::NON_NULL_TYPE;
/** @var NameNode | ListTypeNode */
/** @var NamedTypeNode|ListTypeNode */
public $type;
}
@@ -12,6 +12,6 @@ class ObjectFieldNode extends Node
/** @var NameNode */
public $name;
/** @var ValueNode */
/** @var VariableNode|NullValueNode|IntValueNode|FloatValueNode|StringValueNode|BooleanValueNode|EnumValueNode|ListValueNode|ObjectValueNode */
public $value;
}
@@ -12,13 +12,13 @@ class ObjectTypeDefinitionNode extends Node implements TypeDefinitionNode
/** @var NameNode */
public $name;
/** @var NamedTypeNode[] */
public $interfaces = [];
/** @var NodeList<NamedTypeNode> */
public $interfaces;
/** @var DirectiveNode[]|null */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var FieldDefinitionNode[]|null */
/** @var NodeList<FieldDefinitionNode> */
public $fields;
/** @var StringValueNode|null */
@@ -12,12 +12,12 @@ class ObjectTypeExtensionNode extends Node implements TypeExtensionNode
/** @var NameNode */
public $name;
/** @var NamedTypeNode[] */
public $interfaces = [];
/** @var NodeList<NamedTypeNode> */
public $interfaces;
/** @var DirectiveNode[] */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var FieldDefinitionNode[] */
/** @var NodeList<FieldDefinitionNode> */
public $fields;
}
@@ -9,6 +9,6 @@ class ObjectValueNode extends Node implements ValueNode
/** @var string */
public $kind = NodeKind::OBJECT;
/** @var ObjectFieldNode[]|NodeList */
/** @var NodeList<ObjectFieldNode> */
public $fields;
}
@@ -9,16 +9,16 @@ class OperationDefinitionNode extends Node implements ExecutableDefinitionNode,
/** @var string */
public $kind = NodeKind::OPERATION_DEFINITION;
/** @var NameNode */
/** @var NameNode|null */
public $name;
/** @var string (oneOf 'query', 'mutation')) */
/** @var string (oneOf 'query', 'mutation', 'subscription')) */
public $operation;
/** @var VariableDefinitionNode[] */
/** @var NodeList<VariableDefinitionNode> */
public $variableDefinitions;
/** @var DirectiveNode[] */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var SelectionSetNode */
@@ -12,7 +12,7 @@ class ScalarTypeDefinitionNode extends Node implements TypeDefinitionNode
/** @var NameNode */
public $name;
/** @var DirectiveNode[] */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var StringValueNode|null */
@@ -12,6 +12,6 @@ class ScalarTypeExtensionNode extends Node implements TypeExtensionNode
/** @var NameNode */
public $name;
/** @var DirectiveNode[]|null */
/** @var NodeList<DirectiveNode> */
public $directives;
}
@@ -9,9 +9,9 @@ class SchemaDefinitionNode extends Node implements TypeSystemDefinitionNode
/** @var string */
public $kind = NodeKind::SCHEMA_DEFINITION;
/** @var DirectiveNode[] */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var OperationTypeDefinitionNode[] */
/** @var NodeList<OperationTypeDefinitionNode> */
public $operationTypes;
}
@@ -9,9 +9,9 @@ class SchemaTypeExtensionNode extends Node implements TypeExtensionNode
/** @var string */
public $kind = NodeKind::SCHEMA_EXTENSION;
/** @var DirectiveNode[]|null */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var OperationTypeDefinitionNode[]|null */
/** @var NodeList<OperationTypeDefinitionNode> */
public $operationTypes;
}
@@ -9,6 +9,6 @@ class SelectionSetNode extends Node
/** @var string */
public $kind = NodeKind::SELECTION_SET;
/** @var SelectionNode[] */
/** @var NodeList<SelectionNode&Node> */
public $selections;
}
@@ -12,6 +12,6 @@ class StringValueNode extends Node implements ValueNode
/** @var string */
public $value;
/** @var bool|null */
/** @var bool */
public $block;
}
@@ -10,6 +10,8 @@ namespace GraphQL\Language\AST;
* | TypeDefinitionNode
* | TypeExtensionNode
* | DirectiveDefinitionNode
*
* @property NameNode $name
*/
interface TypeSystemDefinitionNode extends DefinitionNode
{
@@ -12,10 +12,10 @@ class UnionTypeDefinitionNode extends Node implements TypeDefinitionNode
/** @var NameNode */
public $name;
/** @var DirectiveNode[] */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var NamedTypeNode[]|null */
/** @var NodeList<NamedTypeNode> */
public $types;
/** @var StringValueNode|null */
@@ -12,9 +12,9 @@ class UnionTypeExtensionNode extends Node implements TypeExtensionNode
/** @var NameNode */
public $name;
/** @var DirectiveNode[]|null */
/** @var NodeList<DirectiveNode> */
public $directives;
/** @var NamedTypeNode[]|null */
/** @var NodeList<NamedTypeNode> */
public $types;
}
@@ -12,9 +12,12 @@ class VariableDefinitionNode extends Node implements DefinitionNode
/** @var VariableNode */
public $variable;
/** @var TypeNode */
/** @var NamedTypeNode|ListTypeNode|NonNullTypeNode */
public $type;
/** @var ValueNode|null */
/** @var VariableNode|NullValueNode|IntValueNode|FloatValueNode|StringValueNode|BooleanValueNode|EnumValueNode|ListValueNode|ObjectValueNode|null */
public $defaultValue;
/** @var NodeList<DirectiveNode> */
public $directives;
}
@@ -17,6 +17,7 @@ class DirectiveLocation
const FRAGMENT_DEFINITION = 'FRAGMENT_DEFINITION';
const FRAGMENT_SPREAD = 'FRAGMENT_SPREAD';
const INLINE_FRAGMENT = 'INLINE_FRAGMENT';
const VARIABLE_DEFINITION = 'VARIABLE_DEFINITION';
// Type System Definitions
const SCHEMA = 'SCHEMA';
@@ -53,12 +54,7 @@ class DirectiveLocation
self::INPUT_FIELD_DEFINITION => self::INPUT_FIELD_DEFINITION,
];
/**
* @param string $name
*
* @return bool
*/
public static function has($name)
public static function has(string $name) : bool
{
return isset(self::$locations[$name]);
}
+29 -7
View File
@@ -9,8 +9,11 @@ use GraphQL\Utils\BlockString;
use GraphQL\Utils\Utils;
use function chr;
use function hexdec;
use function mb_convert_encoding;
use function ord;
use function pack;
use function preg_match;
use function substr;
/**
* A Lexer is a stateful stream generator in that every time
@@ -118,7 +121,7 @@ class Lexer
$token = $this->token;
if ($token->kind !== Token::EOF) {
do {
$token = $token->next ?: ($token->next = $this->readToken($token));
$token = $token->next ?? ($token->next = $this->readToken($token));
} while ($token->kind === Token::COMMENT);
}
@@ -314,11 +317,11 @@ class Lexer
$start = $this->position;
[$char, $code] = $this->readChar();
while ($code && (
while ($code !== null && (
$code === 95 || // _
$code >= 48 && $code <= 57 || // 0-9
$code >= 65 && $code <= 90 || // A-Z
$code >= 97 && $code <= 122 // a-z
($code >= 48 && $code <= 57) || // 0-9
($code >= 65 && $code <= 90) || // A-Z
($code >= 97 && $code <= 122) // a-z
)) {
$value .= $char;
[$char, $code] = $this->moveStringCursor(1, 1)->readChar();
@@ -522,8 +525,27 @@ class Lexer
'Invalid character escape sequence: \\u' . $hex
);
}
$code = hexdec($hex);
// UTF-16 surrogate pair detection and handling.
$highOrderByte = $code >> 8;
if (0xD8 <= $highOrderByte && $highOrderByte <= 0xDF) {
[$utf16Continuation] = $this->readChars(6, true);
if (! preg_match('/^\\\u[0-9a-fA-F]{4}$/', $utf16Continuation)) {
throw new SyntaxError(
$this->source,
$this->position - 5,
'Invalid UTF-16 trailing surrogate: ' . $utf16Continuation
);
}
$surrogatePairHex = $hex . substr($utf16Continuation, 2, 4);
$value .= mb_convert_encoding(pack('H*', $surrogatePairHex), 'UTF-8', 'UTF-16');
break;
}
$this->assertValidStringCharacterCode($code, $position - 2);
$value .= Utils::chr($code);
break;
default:
@@ -695,7 +717,7 @@ class Lexer
do {
[$char, $code, $bytes] = $this->moveStringCursor(1, $bytes)->readChar();
$value .= $char;
} while ($code &&
} while ($code !== null &&
// SourceCharacter but not LineTerminator
($code > 0x001F || $code === 0x0009)
);
@@ -771,7 +793,7 @@ class Lexer
{
$result = '';
$totalBytes = 0;
$byteOffset = $byteStreamPosition ?: $this->byteStreamPosition;
$byteOffset = $byteStreamPosition ?? $this->byteStreamPosition;
for ($i = 0; $i < $charCount; $i++) {
[$char, $code, $bytes] = $this->readChar(false, $byteOffset);
File diff suppressed because it is too large Load Diff
+73 -54
View File
@@ -28,6 +28,7 @@ use GraphQL\Language\AST\IntValueNode;
use GraphQL\Language\AST\ListTypeNode;
use GraphQL\Language\AST\ListValueNode;
use GraphQL\Language\AST\NamedTypeNode;
use GraphQL\Language\AST\NameNode;
use GraphQL\Language\AST\Node;
use GraphQL\Language\AST\NodeKind;
use GraphQL\Language\AST\NonNullTypeNode;
@@ -47,6 +48,7 @@ use GraphQL\Language\AST\StringValueNode;
use GraphQL\Language\AST\UnionTypeDefinitionNode;
use GraphQL\Language\AST\UnionTypeExtensionNode;
use GraphQL\Language\AST\VariableDefinitionNode;
use GraphQL\Language\AST\VariableNode;
use GraphQL\Utils\Utils;
use function count;
use function implode;
@@ -54,6 +56,7 @@ use function json_encode;
use function preg_replace;
use function sprintf;
use function str_replace;
use function strlen;
use function strpos;
/**
@@ -82,7 +85,7 @@ class Printer
public static function doPrint($ast)
{
static $instance;
$instance = $instance ?: new static();
$instance = $instance ?? new static();
return $instance->printAST($ast);
}
@@ -91,25 +94,31 @@ class Printer
{
}
/**
* Traverse an AST bottom-up, converting all nodes to strings.
*
* That means the AST is manipulated in such a way that it no longer
* resembles the well-formed result of parsing.
*/
public function printAST($ast)
{
return Visitor::visit(
$ast,
[
'leave' => [
NodeKind::NAME => static function (Node $node) {
return '' . $node->value;
NodeKind::NAME => static function (NameNode $node) : string {
return $node->value;
},
NodeKind::VARIABLE => static function ($node) {
NodeKind::VARIABLE => static function (VariableNode $node) : string {
return '$' . $node->name;
},
NodeKind::DOCUMENT => function (DocumentNode $node) {
NodeKind::DOCUMENT => function (DocumentNode $node) : string {
return $this->join($node->definitions, "\n\n") . "\n";
},
NodeKind::OPERATION_DEFINITION => function (OperationDefinitionNode $node) {
NodeKind::OPERATION_DEFINITION => function (OperationDefinitionNode $node) : string {
$op = $node->operation;
$name = $node->name;
$varDefs = $this->wrap('(', $this->join($node->variableDefinitions, ', '), ')');
@@ -118,20 +127,24 @@ class Printer
// Anonymous queries with no directives or variable definitions can use
// the query short form.
return ! $name && ! $directives && ! $varDefs && $op === 'query'
return $name === null && strlen($directives ?? '') === 0 && ! $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::VARIABLE_DEFINITION => function (VariableDefinitionNode $node) : string {
return $node->variable
. ': '
. $node->type
. $this->wrap(' = ', $node->defaultValue)
. $this->wrap(' ', $this->join($node->directives, ' '));
},
NodeKind::SELECTION_SET => function (SelectionSetNode $node) {
return $this->block($node->selections);
},
NodeKind::FIELD => function (FieldNode $node) {
NodeKind::FIELD => function (FieldNode $node) : string {
return $this->join(
[
$this->wrap('', $node->alias, ': ') . $node->name . $this->wrap(
@@ -146,15 +159,17 @@ class Printer
);
},
NodeKind::ARGUMENT => static function (ArgumentNode $node) {
NodeKind::ARGUMENT => static function (ArgumentNode $node) : string {
return $node->name . ': ' . $node->value;
},
NodeKind::FRAGMENT_SPREAD => function (FragmentSpreadNode $node) {
return '...' . $node->name . $this->wrap(' ', $this->join($node->directives, ' '));
NodeKind::FRAGMENT_SPREAD => function (FragmentSpreadNode $node) : string {
return '...'
. $node->name
. $this->wrap(' ', $this->join($node->directives, ' '));
},
NodeKind::INLINE_FRAGMENT => function (InlineFragmentNode $node) {
NodeKind::INLINE_FRAGMENT => function (InlineFragmentNode $node) : string {
return $this->join(
[
'...',
@@ -166,7 +181,7 @@ class Printer
);
},
NodeKind::FRAGMENT_DEFINITION => function (FragmentDefinitionNode $node) {
NodeKind::FRAGMENT_DEFINITION => function (FragmentDefinitionNode $node) : string {
// Note: fragment variable definitions are experimental and may be changed or removed in the future.
return sprintf('fragment %s', $node->name)
. $this->wrap('(', $this->join($node->variableDefinitions, ', '), ')')
@@ -175,15 +190,15 @@ class Printer
. $node->selectionSet;
},
NodeKind::INT => static function (IntValueNode $node) {
NodeKind::INT => static function (IntValueNode $node) : string {
return $node->value;
},
NodeKind::FLOAT => static function (FloatValueNode $node) {
NodeKind::FLOAT => static function (FloatValueNode $node) : string {
return $node->value;
},
NodeKind::STRING => function (StringValueNode $node, $key) {
NodeKind::STRING => function (StringValueNode $node, $key) : string {
if ($node->block) {
return $this->printBlockString($node->value, $key === 'description');
}
@@ -191,47 +206,48 @@ class Printer
return json_encode($node->value);
},
NodeKind::BOOLEAN => static function (BooleanValueNode $node) {
NodeKind::BOOLEAN => static function (BooleanValueNode $node) : string {
return $node->value ? 'true' : 'false';
},
NodeKind::NULL => static function (NullValueNode $node) {
NodeKind::NULL => static function (NullValueNode $node) : string {
return 'null';
},
NodeKind::ENUM => static function (EnumValueNode $node) {
NodeKind::ENUM => static function (EnumValueNode $node) : string {
return $node->value;
},
NodeKind::LST => function (ListValueNode $node) {
NodeKind::LST => function (ListValueNode $node) : string {
return '[' . $this->join($node->values, ', ') . ']';
},
NodeKind::OBJECT => function (ObjectValueNode $node) {
NodeKind::OBJECT => function (ObjectValueNode $node) : string {
return '{' . $this->join($node->fields, ', ') . '}';
},
NodeKind::OBJECT_FIELD => static function (ObjectFieldNode $node) {
NodeKind::OBJECT_FIELD => static function (ObjectFieldNode $node) : string {
return $node->name . ': ' . $node->value;
},
NodeKind::DIRECTIVE => function (DirectiveNode $node) {
NodeKind::DIRECTIVE => function (DirectiveNode $node) : string {
return '@' . $node->name . $this->wrap('(', $this->join($node->arguments, ', '), ')');
},
NodeKind::NAMED_TYPE => static function (NamedTypeNode $node) {
NodeKind::NAMED_TYPE => static function (NamedTypeNode $node) : string {
// @phpstan-ignore-next-line the printer works bottom up, so this is already a string here
return $node->name;
},
NodeKind::LIST_TYPE => static function (ListTypeNode $node) {
NodeKind::LIST_TYPE => static function (ListTypeNode $node) : string {
return '[' . $node->type . ']';
},
NodeKind::NON_NULL_TYPE => static function (NonNullTypeNode $node) {
NodeKind::NON_NULL_TYPE => static function (NonNullTypeNode $node) : string {
return $node->type . '!';
},
NodeKind::SCHEMA_DEFINITION => function (SchemaDefinitionNode $def) {
NodeKind::SCHEMA_DEFINITION => function (SchemaDefinitionNode $def) : string {
return $this->join(
[
'schema',
@@ -242,15 +258,15 @@ class Printer
);
},
NodeKind::OPERATION_TYPE_DEFINITION => static function (OperationTypeDefinitionNode $def) {
NodeKind::OPERATION_TYPE_DEFINITION => static function (OperationTypeDefinitionNode $def) : string {
return $def->operation . ': ' . $def->type;
},
NodeKind::SCALAR_TYPE_DEFINITION => $this->addDescription(function (ScalarTypeDefinitionNode $def) {
NodeKind::SCALAR_TYPE_DEFINITION => $this->addDescription(function (ScalarTypeDefinitionNode $def) : string {
return $this->join(['scalar', $def->name, $this->join($def->directives, ' ')], ' ');
}),
NodeKind::OBJECT_TYPE_DEFINITION => $this->addDescription(function (ObjectTypeDefinitionNode $def) {
NodeKind::OBJECT_TYPE_DEFINITION => $this->addDescription(function (ObjectTypeDefinitionNode $def) : string {
return $this->join(
[
'type',
@@ -263,8 +279,8 @@ class Printer
);
}),
NodeKind::FIELD_DEFINITION => $this->addDescription(function (FieldDefinitionNode $def) {
$noIndent = Utils::every($def->arguments, static function (string $arg) {
NodeKind::FIELD_DEFINITION => $this->addDescription(function (FieldDefinitionNode $def) : string {
$noIndent = Utils::every($def->arguments, static function (string $arg) : bool {
return strpos($arg, "\n") === false;
});
@@ -276,7 +292,7 @@ class Printer
. $this->wrap(' ', $this->join($def->directives, ' '));
}),
NodeKind::INPUT_VALUE_DEFINITION => $this->addDescription(function (InputValueDefinitionNode $def) {
NodeKind::INPUT_VALUE_DEFINITION => $this->addDescription(function (InputValueDefinitionNode $def) : string {
return $this->join(
[
$def->name . ': ' . $def->type,
@@ -288,11 +304,12 @@ class Printer
}),
NodeKind::INTERFACE_TYPE_DEFINITION => $this->addDescription(
function (InterfaceTypeDefinitionNode $def) {
function (InterfaceTypeDefinitionNode $def) : string {
return $this->join(
[
'interface',
$def->name,
$this->wrap('implements ', $this->join($def->interfaces, ' & ')),
$this->join($def->directives, ' '),
$this->block($def->fields),
],
@@ -301,13 +318,13 @@ class Printer
}
),
NodeKind::UNION_TYPE_DEFINITION => $this->addDescription(function (UnionTypeDefinitionNode $def) {
NodeKind::UNION_TYPE_DEFINITION => $this->addDescription(function (UnionTypeDefinitionNode $def) : string {
return $this->join(
[
'union',
$def->name,
$this->join($def->directives, ' '),
$def->types
count($def->types ?? []) > 0
? '= ' . $this->join($def->types, ' | ')
: '',
],
@@ -315,7 +332,7 @@ class Printer
);
}),
NodeKind::ENUM_TYPE_DEFINITION => $this->addDescription(function (EnumTypeDefinitionNode $def) {
NodeKind::ENUM_TYPE_DEFINITION => $this->addDescription(function (EnumTypeDefinitionNode $def) : string {
return $this->join(
[
'enum',
@@ -327,13 +344,13 @@ class Printer
);
}),
NodeKind::ENUM_VALUE_DEFINITION => $this->addDescription(function (EnumValueDefinitionNode $def) {
NodeKind::ENUM_VALUE_DEFINITION => $this->addDescription(function (EnumValueDefinitionNode $def) : string {
return $this->join([$def->name, $this->join($def->directives, ' ')], ' ');
}),
NodeKind::INPUT_OBJECT_TYPE_DEFINITION => $this->addDescription(function (
InputObjectTypeDefinitionNode $def
) {
) : string {
return $this->join(
[
'input',
@@ -345,7 +362,7 @@ class Printer
);
}),
NodeKind::SCHEMA_EXTENSION => function (SchemaTypeExtensionNode $def) {
NodeKind::SCHEMA_EXTENSION => function (SchemaTypeExtensionNode $def) : string {
return $this->join(
[
'extend schema',
@@ -356,7 +373,7 @@ class Printer
);
},
NodeKind::SCALAR_TYPE_EXTENSION => function (ScalarTypeExtensionNode $def) {
NodeKind::SCALAR_TYPE_EXTENSION => function (ScalarTypeExtensionNode $def) : string {
return $this->join(
[
'extend scalar',
@@ -367,7 +384,7 @@ class Printer
);
},
NodeKind::OBJECT_TYPE_EXTENSION => function (ObjectTypeExtensionNode $def) {
NodeKind::OBJECT_TYPE_EXTENSION => function (ObjectTypeExtensionNode $def) : string {
return $this->join(
[
'extend type',
@@ -380,11 +397,12 @@ class Printer
);
},
NodeKind::INTERFACE_TYPE_EXTENSION => function (InterfaceTypeExtensionNode $def) {
NodeKind::INTERFACE_TYPE_EXTENSION => function (InterfaceTypeExtensionNode $def) : string {
return $this->join(
[
'extend interface',
$def->name,
$this->wrap('implements ', $this->join($def->interfaces, ' & ')),
$this->join($def->directives, ' '),
$this->block($def->fields),
],
@@ -392,13 +410,13 @@ class Printer
);
},
NodeKind::UNION_TYPE_EXTENSION => function (UnionTypeExtensionNode $def) {
NodeKind::UNION_TYPE_EXTENSION => function (UnionTypeExtensionNode $def) : string {
return $this->join(
[
'extend union',
$def->name,
$this->join($def->directives, ' '),
$def->types
count($def->types ?? []) > 0
? '= ' . $this->join($def->types, ' | ')
: '',
],
@@ -406,7 +424,7 @@ class Printer
);
},
NodeKind::ENUM_TYPE_EXTENSION => function (EnumTypeExtensionNode $def) {
NodeKind::ENUM_TYPE_EXTENSION => function (EnumTypeExtensionNode $def) : string {
return $this->join(
[
'extend enum',
@@ -418,7 +436,7 @@ class Printer
);
},
NodeKind::INPUT_OBJECT_TYPE_EXTENSION => function (InputObjectTypeExtensionNode $def) {
NodeKind::INPUT_OBJECT_TYPE_EXTENSION => function (InputObjectTypeExtensionNode $def) : string {
return $this->join(
[
'extend input',
@@ -430,8 +448,8 @@ class Printer
);
},
NodeKind::DIRECTIVE_DEFINITION => $this->addDescription(function (DirectiveDefinitionNode $def) {
$noIndent = Utils::every($def->arguments, static function (string $arg) {
NodeKind::DIRECTIVE_DEFINITION => $this->addDescription(function (DirectiveDefinitionNode $def) : string {
$noIndent = Utils::every($def->arguments, static function (string $arg) : bool {
return strpos($arg, "\n") === false;
});
@@ -440,6 +458,7 @@ class Printer
. ($noIndent
? $this->wrap('(', $this->join($def->arguments, ', '), ')')
: $this->wrap("(\n", $this->indent($this->join($def->arguments, "\n")), "\n"))
. ($def->repeatable ? ' repeatable' : '')
. ' on ' . $this->join($def->locations, ' | ');
}),
],
@@ -449,7 +468,7 @@ class Printer
public function addDescription(callable $cb)
{
return function ($node) use ($cb) {
return function ($node) use ($cb) : string {
return $this->join([$node->description, $cb($node)], "\n");
};
}
@@ -489,14 +508,14 @@ class Printer
return $maybeArray ? count($maybeArray) : 0;
}
public function join($maybeArray, $separator = '')
public function join($maybeArray, $separator = '') : string
{
return $maybeArray
? implode(
$separator,
Utils::filter(
$maybeArray,
static function ($x) {
static function ($x) : bool {
return (bool) $x;
}
)
+2 -2
View File
@@ -46,8 +46,8 @@ class Source
$this->body = $body;
$this->length = mb_strlen($body, 'UTF-8');
$this->name = $name ?: 'GraphQL request';
$this->locationOffset = $location ?: new SourceLocation(1, 1);
$this->name = $name === '' || $name === null ? 'GraphQL request' : $name;
$this->locationOffset = $location ?? new SourceLocation(1, 1);
Utils::invariant(
$this->locationOffset->line > 0,
+28 -36
View File
@@ -11,28 +11,28 @@ namespace GraphQL\Language;
class Token
{
// Each kind of token.
const SOF = '<SOF>';
const EOF = '<EOF>';
const BANG = '!';
const DOLLAR = '$';
const AMP = '&';
const PAREN_L = '(';
const PAREN_R = ')';
const SPREAD = '...';
const COLON = ':';
const EQUALS = '=';
const AT = '@';
const BRACKET_L = '[';
const BRACKET_R = ']';
const BRACE_L = '{';
const PIPE = '|';
const BRACE_R = '}';
const NAME = 'Name';
const INT = 'Int';
const FLOAT = 'Float';
const STRING = 'String';
const BLOCK_STRING = 'BlockString';
const COMMENT = 'Comment';
public const SOF = '<SOF>';
public const EOF = '<EOF>';
public const BANG = '!';
public const DOLLAR = '$';
public const AMP = '&';
public const PAREN_L = '(';
public const PAREN_R = ')';
public const SPREAD = '...';
public const COLON = ':';
public const EQUALS = '=';
public const AT = '@';
public const BRACKET_L = '[';
public const BRACKET_R = ']';
public const BRACE_L = '{';
public const PIPE = '|';
public const BRACE_R = '}';
public const NAME = 'Name';
public const INT = 'Int';
public const FLOAT = 'Float';
public const STRING = 'String';
public const BLOCK_STRING = 'BlockString';
public const COMMENT = 'Comment';
/**
* The kind of Token (see one of constants above).
@@ -81,18 +81,13 @@ class Token
*/
public $prev;
/** @var Token */
/** @var Token|null */
public $next;
/**
* @param string $kind
* @param int $start
* @param int $end
* @param int $line
* @param int $column
* @param mixed|null $value
* @param mixed $value
*/
public function __construct($kind, $start, $end, $line, $column, ?Token $previous = null, $value = null)
public function __construct(string $kind, int $start, int $end, int $line, int $column, ?Token $previous = null, $value = null)
{
$this->kind = $kind;
$this->start = $start;
@@ -104,18 +99,15 @@ class Token
$this->value = $value;
}
/**
* @return string
*/
public function getDescription()
public function getDescription() : string
{
return $this->kind . ($this->value ? ' "' . $this->value . '"' : '');
return $this->kind . ($this->value === null ? '' : ' "' . $this->value . '"');
}
/**
* @return (string|int|null)[]
*/
public function toArray()
public function toArray() : array
{
return [
'kind' => $this->kind,
+42 -47
View File
@@ -14,8 +14,6 @@ use SplFixedArray;
use stdClass;
use function array_pop;
use function array_splice;
use function call_user_func;
use function call_user_func_array;
use function count;
use function func_get_args;
use function is_array;
@@ -116,7 +114,7 @@ class Visitor
NodeKind::NAME => [],
NodeKind::DOCUMENT => ['definitions'],
NodeKind::OPERATION_DEFINITION => ['name', 'variableDefinitions', 'directives', 'selectionSet'],
NodeKind::VARIABLE_DEFINITION => ['variable', 'type', 'defaultValue'],
NodeKind::VARIABLE_DEFINITION => ['variable', 'type', 'defaultValue', 'directives'],
NodeKind::VARIABLE => ['name'],
NodeKind::SELECTION_SET => ['selections'],
NodeKind::FIELD => ['alias', 'name', 'arguments', 'directives', 'selectionSet'],
@@ -153,7 +151,7 @@ class Visitor
NodeKind::OBJECT_TYPE_DEFINITION => ['description', 'name', 'interfaces', 'directives', 'fields'],
NodeKind::FIELD_DEFINITION => ['description', 'name', 'arguments', 'type', 'directives'],
NodeKind::INPUT_VALUE_DEFINITION => ['description', 'name', 'type', 'defaultValue', 'directives'],
NodeKind::INTERFACE_TYPE_DEFINITION => ['description', 'name', 'directives', 'fields'],
NodeKind::INTERFACE_TYPE_DEFINITION => ['description', 'name', 'interfaces', 'directives', 'fields'],
NodeKind::UNION_TYPE_DEFINITION => ['description', 'name', 'directives', 'types'],
NodeKind::ENUM_TYPE_DEFINITION => ['description', 'name', 'directives', 'values'],
NodeKind::ENUM_VALUE_DEFINITION => ['description', 'name', 'directives'],
@@ -161,7 +159,7 @@ class Visitor
NodeKind::SCALAR_TYPE_EXTENSION => ['name', 'directives'],
NodeKind::OBJECT_TYPE_EXTENSION => ['name', 'interfaces', 'directives', 'fields'],
NodeKind::INTERFACE_TYPE_EXTENSION => ['name', 'directives', 'fields'],
NodeKind::INTERFACE_TYPE_EXTENSION => ['name', 'interfaces', 'directives', 'fields'],
NodeKind::UNION_TYPE_EXTENSION => ['name', 'directives', 'types'],
NodeKind::ENUM_TYPE_EXTENSION => ['name', 'directives', 'values'],
NodeKind::INPUT_OBJECT_TYPE_EXTENSION => ['name', 'directives', 'fields'],
@@ -186,7 +184,7 @@ class Visitor
*/
public static function visit($root, $visitor, $keyMap = null)
{
$visitorKeys = $keyMap ?: self::$visitorKeys;
$visitorKeys = $keyMap ?? self::$visitorKeys;
$stack = null;
$inArray = $root instanceof NodeList || is_array($root);
@@ -205,7 +203,7 @@ class Visitor
$isLeaving = $index === count($keys);
$key = null;
$node = null;
$isEdited = $isLeaving && count($edits) !== 0;
$isEdited = $isLeaving && count($edits) > 0;
if ($isLeaving) {
$key = ! $ancestors ? $UNDEFINED : $path[count($path) - 1];
@@ -230,11 +228,7 @@ class Visitor
$editKey -= $editOffset;
}
if ($inArray && $editValue === null) {
if ($node instanceof NodeList) {
$node->splice($editKey, 1);
} else {
array_splice($node, $editKey, 1);
}
$node->splice($editKey, 1);
$editOffset++;
} else {
if ($node instanceof NodeList || is_array($node)) {
@@ -251,8 +245,18 @@ class Visitor
$inArray = $stack['inArray'];
$stack = $stack['prev'];
} else {
$key = $parent !== null ? ($inArray ? $index : $keys[$index]) : $UNDEFINED;
$node = $parent !== null ? ($parent instanceof NodeList || is_array($parent) ? $parent[$key] : $parent->{$key}) : $newRoot;
$key = $parent !== null
? ($inArray
? $index
: $keys[$index]
)
: $UNDEFINED;
$node = $parent !== null
? ($parent instanceof NodeList || is_array($parent)
? $parent[$key]
: $parent->{$key}
)
: $newRoot;
if ($node === null || $node === $UNDEFINED) {
continue;
}
@@ -269,8 +273,8 @@ class Visitor
$visitFn = self::getVisitFn($visitor, $node->kind, $isLeaving);
if ($visitFn) {
$result = call_user_func($visitFn, $node, $key, $parent, $path, $ancestors);
if ($visitFn !== null) {
$result = $visitFn($node, $key, $parent, $path, $ancestors);
$editValue = null;
if ($result !== null) {
@@ -318,7 +322,7 @@ class Visitor
];
$inArray = $node instanceof NodeList || is_array($node);
$keys = ($inArray ? $node : $visitorKeys[$node->kind]) ?: [];
$keys = ($inArray ? $node : $visitorKeys[$node->kind]) ?? [];
$index = -1;
$edits = [];
if ($parent !== null) {
@@ -328,7 +332,7 @@ class Visitor
}
} while ($stack);
if (count($edits) !== 0) {
if (count($edits) > 0) {
$newRoot = $edits[0][1];
}
@@ -383,7 +387,7 @@ class Visitor
/**
* @param callable[][] $visitors
*
* @return callable[][]
* @return array<string, callable>
*/
public static function visitInParallel($visitors)
{
@@ -393,7 +397,7 @@ class Visitor
return [
'enter' => static function (Node $node) use ($visitors, $skipping, $visitorsCount) {
for ($i = 0; $i < $visitorsCount; $i++) {
if (! empty($skipping[$i])) {
if ($skipping[$i] !== null) {
continue;
}
@@ -407,7 +411,7 @@ class Visitor
continue;
}
$result = call_user_func_array($fn, func_get_args());
$result = $fn(...func_get_args());
if ($result instanceof VisitorOperation) {
if ($result->doContinue) {
@@ -424,15 +428,15 @@ class Visitor
},
'leave' => static function (Node $node) use ($visitors, $skipping, $visitorsCount) {
for ($i = 0; $i < $visitorsCount; $i++) {
if (empty($skipping[$i])) {
if ($skipping[$i] === null) {
$fn = self::getVisitFn(
$visitors[$i],
$node->kind, /* isLeaving */
true
);
if ($fn) {
$result = call_user_func_array($fn, func_get_args());
if (isset($fn)) {
$result = $fn(...func_get_args());
if ($result instanceof VisitorOperation) {
if ($result->doBreak) {
$skipping[$i] = $result;
@@ -462,8 +466,8 @@ class Visitor
$typeInfo->enter($node);
$fn = self::getVisitFn($visitor, $node->kind, false);
if ($fn) {
$result = call_user_func_array($fn, func_get_args());
if (isset($fn)) {
$result = $fn(...func_get_args());
if ($result !== null) {
$typeInfo->leave($node);
if ($result instanceof Node) {
@@ -478,7 +482,10 @@ class Visitor
},
'leave' => static function (Node $node) use ($typeInfo, $visitor) {
$fn = self::getVisitFn($visitor, $node->kind, true);
$result = $fn ? call_user_func_array($fn, func_get_args()) : null;
$result = $fn !== null
? $fn(...func_get_args())
: null;
$typeInfo->leave($node);
return $result;
@@ -490,10 +497,8 @@ class Visitor
* @param callable[]|null $visitor
* @param string $kind
* @param bool $isLeaving
*
* @return callable|null
*/
public static function getVisitFn($visitor, $kind, $isLeaving)
public static function getVisitFn($visitor, $kind, $isLeaving) : ?callable
{
if ($visitor === null) {
return null;
@@ -501,11 +506,6 @@ class Visitor
$kindVisitor = $visitor[$kind] ?? null;
if (! $isLeaving && is_callable($kindVisitor)) {
// { Kind() {} }
return $kindVisitor;
}
if (is_array($kindVisitor)) {
if ($isLeaving) {
$kindSpecificVisitor = $kindVisitor['leave'] ?? null;
@@ -513,29 +513,24 @@ class Visitor
$kindSpecificVisitor = $kindVisitor['enter'] ?? null;
}
if ($kindSpecificVisitor && is_callable($kindSpecificVisitor)) {
// { Kind: { enter() {}, leave() {} } }
return $kindSpecificVisitor;
}
return $kindSpecificVisitor;
}
return null;
if ($kindVisitor !== null && ! $isLeaving) {
return $kindVisitor;
}
$visitor += ['leave' => null, 'enter' => null];
$specificVisitor = $isLeaving ? $visitor['leave'] : $visitor['enter'];
if ($specificVisitor) {
if (is_callable($specificVisitor)) {
if (isset($specificVisitor)) {
if (! is_array($specificVisitor)) {
// { enter() {}, leave() {} }
return $specificVisitor;
}
$specificKindVisitor = $specificVisitor[$kind] ?? null;
if (is_callable($specificKindVisitor)) {
// { enter: { Kind() {} }, leave: { Kind() {} } }
return $specificKindVisitor;
}
return $specificVisitor[$kind] ?? null;
}
return null;