1: <?php declare(strict_types=1);
2:
3: namespace PhpParser\Lexer\TokenEmulator;
4:
5: use PhpParser\PhpVersion;
6: use PhpParser\Token;
7:
8: class VoidCastEmulator extends TokenEmulator {
9: public function getPhpVersion(): PhpVersion {
10: return PhpVersion::fromComponents(8, 5);
11: }
12:
13: public function isEmulationNeeded(string $code): bool {
14: return (bool)\preg_match('/\([ \t]*void[ \t]*\)/i', $code);
15: }
16:
17: public function emulate(string $code, array $tokens): array {
18: for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
19: $token = $tokens[$i];
20: if ($token->text !== '(') {
21: continue;
22: }
23:
24: $numTokens = 1;
25: $text = '(';
26: $j = $i + 1;
27: if ($j < $c && $tokens[$j]->id === \T_WHITESPACE && preg_match('/[ \t]+/', $tokens[$j]->text)) {
28: $text .= $tokens[$j]->text;
29: $numTokens++;
30: $j++;
31: }
32:
33: if ($j >= $c || $tokens[$j]->id !== \T_STRING || \strtolower($tokens[$j]->text) !== 'void') {
34: continue;
35: }
36:
37: $text .= $tokens[$j]->text;
38: $numTokens++;
39: $k = $j + 1;
40: if ($k < $c && $tokens[$k]->id === \T_WHITESPACE && preg_match('/[ \t]+/', $tokens[$k]->text)) {
41: $text .= $tokens[$k]->text;
42: $numTokens++;
43: $k++;
44: }
45:
46: if ($k >= $c || $tokens[$k]->text !== ')') {
47: continue;
48: }
49:
50: $text .= ')';
51: $numTokens++;
52: array_splice($tokens, $i, $numTokens, [
53: new Token(\T_VOID_CAST, $text, $token->line, $token->pos),
54: ]);
55: $c -= $numTokens - 1;
56: }
57: return $tokens;
58: }
59:
60: public function reverseEmulate(string $code, array $tokens): array {
61: for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
62: $token = $tokens[$i];
63: if ($token->id !== \T_VOID_CAST) {
64: continue;
65: }
66:
67: if (!preg_match('/^\(([ \t]*)(void)([ \t]*)\)$/i', $token->text, $match)) {
68: throw new \LogicException('Unexpected T_VOID_CAST contents');
69: }
70:
71: $newTokens = [];
72: $pos = $token->pos;
73:
74: $newTokens[] = new Token(\ord('('), '(', $token->line, $pos);
75: $pos++;
76:
77: if ($match[1] !== '') {
78: $newTokens[] = new Token(\T_WHITESPACE, $match[1], $token->line, $pos);
79: $pos += \strlen($match[1]);
80: }
81:
82: $newTokens[] = new Token(\T_STRING, $match[2], $token->line, $pos);
83: $pos += \strlen($match[2]);
84:
85: if ($match[3] !== '') {
86: $newTokens[] = new Token(\T_WHITESPACE, $match[3], $token->line, $pos);
87: $pos += \strlen($match[3]);
88: }
89:
90: $newTokens[] = new Token(\ord(')'), ')', $token->line, $pos);
91:
92: array_splice($tokens, $i, 1, $newTokens);
93: $i += \count($newTokens) - 1;
94: $c += \count($newTokens) - 1;
95: }
96: return $tokens;
97: }
98: }
99: