* @phpstan-implements IteratorAggregate */ class NodeList implements ArrayAccess, IteratorAggregate, Countable { /** * @var Node[] * @phpstan-var array */ private $nodes; /** * @param Node[] $nodes * * @phpstan-param array $nodes * @phpstan-return self */ public static function create(array $nodes) : self { return new static($nodes); } /** * @param Node[] $nodes * * @phpstan-param array $nodes */ public function __construct(array $nodes) { $this->nodes = $nodes; } /** * @param int|string $offset */ public function offsetExists($offset) : bool { return isset($this->nodes[$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. * * @param int|string $offset * * @phpstan-return T */ #[ReturnTypeWillChange] public function offsetGet($offset)// : Node { $item = $this->nodes[$offset]; if (is_array($item) && isset($item['kind'])) { /** @phpstan-var T $node */ $node = AST::fromArray($item); $this->nodes[$offset] = $node; } return $this->nodes[$offset]; } /** * @param int|string|null $offset * @param Node|mixed[] $value * * @phpstan-param T|mixed[] $value */ public function offsetSet($offset, $value) : void { 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 int|string $offset */ public function offsetUnset($offset) : void { unset($this->nodes[$offset]); } /** * @param mixed $replacement * * @phpstan-return NodeList */ public function splice(int $offset, int $length, $replacement = null) : NodeList { return new NodeList(array_splice($this->nodes, $offset, $length, $replacement)); } /** * @param NodeList|Node[] $list * * @phpstan-param NodeList|array $list * @phpstan-return NodeList */ public function merge($list) : NodeList { if ($list instanceof self) { $list = $list->nodes; } return new NodeList(array_merge($this->nodes, $list)); } public function getIterator() : Traversable { foreach ($this->nodes as $key => $_) { yield $this->offsetGet($key); } } public function count() : int { return count($this->nodes); } }