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