1<?php declare(strict_types=1); 2 3namespace PhpParser\Lexer\TokenEmulator; 4 5use PhpParser\Lexer\Emulative; 6 7final class FnTokenEmulator implements TokenEmulatorInterface 8{ 9 public function isEmulationNeeded(string $code) : bool 10 { 11 // skip version where this is supported 12 if (version_compare(\PHP_VERSION, Emulative::PHP_7_4, '>=')) { 13 return false; 14 } 15 16 return strpos($code, 'fn') !== 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 foreach ($tokens as $i => $token) { 24 if ($token[0] === T_STRING && $token[1] === 'fn') { 25 $previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $i); 26 if ($previousNonSpaceToken !== null && $previousNonSpaceToken[0] === T_OBJECT_OPERATOR) { 27 continue; 28 } 29 30 $tokens[$i][0] = Emulative::T_FN; 31 } 32 } 33 34 return $tokens; 35 } 36 37 /** 38 * @param mixed[] $tokens 39 * @return mixed[]|null 40 */ 41 private function getPreviousNonSpaceToken(array $tokens, int $start) 42 { 43 for ($i = $start - 1; $i >= 0; --$i) { 44 if ($tokens[$i][0] === T_WHITESPACE) { 45 continue; 46 } 47 48 return $tokens[$i]; 49 } 50 51 return null; 52 } 53} 54