phplrt/phplrt

View on GitHub
libs/compiler/src/Runtime/PrintableNode.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

declare(strict_types=1);

namespace Phplrt\Compiler\Runtime;

use Phplrt\Contracts\Ast\NodeInterface;
use Phplrt\Contracts\Lexer\TokenInterface;

/**
 * @internal This is an internal library class, please do not use it in your code.
 * @psalm-internal Phplrt\Compiler\Runtime
 */
class PrintableNode implements NodeInterface, \Stringable
{
    /**
     * @param int<0, max> $offset
     * @param non-empty-string $state
     * @param array<array-key, PrintableNode> $children
     */
    public function __construct(
        private readonly int $offset,
        private readonly string $state,
        public array $children,
    ) {}

    /**
     * @return \Traversable<non-empty-string, array<array-key, PrintableNode>>
     */
    public function getIterator(): \Traversable
    {
        yield 'children' => $this->children;
    }

    public function __toString(): string
    {
        return \implode("\n", $this->render(0));
    }

    /**
     * @param int<0, max> $depth
     * @return array<string>
     */
    public function render(int $depth): array
    {
        $prefix = \str_repeat('    ', $depth);

        $result = [
            $prefix . '<' . $this->state . ' offset="' . $this->offset . '">',
        ];

        foreach ($this->children as $child) {
            switch (true) {
                case $child instanceof self:
                    /** @psalm-suppress RedundantFunctionCall: PHP 7.4 unpacking expect only integer keys */
                    $result = [
                        ...\array_values($result),
                        ...\array_values($child->render($depth + 1))
                    ];
                    break;

                case $child instanceof TokenInterface:
                    $result[] = $prefix . '    <' . $child->getName() . ' offset="' . $child->getOffset() . '">' .
                        $child->getValue() . '</' . $child->getName() . '>';
                    break;

                default:
                    $result[] = $prefix . '    <' . $child . ' />';
            }
        }

        $result[] = $prefix . '</' . $this->state . '>';

        return $result;
    }

    public function getState(): string
    {
        return $this->state;
    }
}