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