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