1<?php declare(strict_types=1);
2
3namespace PhpParser\Lexer\TokenEmulator;
4
5use PhpParser\PhpVersion;
6use PhpParser\Token;
7
8final class AttributeEmulator extends TokenEmulator {
9    public function getPhpVersion(): PhpVersion {
10        return PhpVersion::fromComponents(8, 0);
11    }
12
13    public function isEmulationNeeded(string $code): bool {
14        return strpos($code, '#[') !== false;
15    }
16
17    public function emulate(string $code, array $tokens): array {
18        // We need to manually iterate and manage a count because we'll change
19        // the tokens array on the way.
20        for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
21            $token = $tokens[$i];
22            if ($token->text === '#' && isset($tokens[$i + 1]) && $tokens[$i + 1]->text === '[') {
23                array_splice($tokens, $i, 2, [
24                    new Token(\T_ATTRIBUTE, '#[', $token->line, $token->pos),
25                ]);
26                $c--;
27                continue;
28            }
29        }
30
31        return $tokens;
32    }
33
34    public function reverseEmulate(string $code, array $tokens): array {
35        // TODO
36        return $tokens;
37    }
38
39    public function preprocessCode(string $code, array &$patches): string {
40        $pos = 0;
41        while (false !== $pos = strpos($code, '#[', $pos)) {
42            // Replace #[ with %[
43            $code[$pos] = '%';
44            $patches[] = [$pos, 'replace', '#'];
45            $pos += 2;
46        }
47        return $code;
48    }
49}
50