*/ private array $cache = []; public function __construct(?Parser $parser = null) { $this->parser = $parser ?? (new ParserFactory())->createParser(); } /** * Analyze the given code, using cached data when possible. */ public function analyze(string $code): BufferAnalysis { foreach ($this->cache as $i => $entry) { if ($entry['code'] === $code) { if ($i > 0) { \array_splice($this->cache, $i, 1); \array_unshift($this->cache, $entry); } return $entry['analysis']; } } $analysis = $this->buildAnalysis($code); \array_unshift($this->cache, ['code' => $code, 'analysis' => $analysis]); if (\count($this->cache) > self::CACHE_SIZE) { \array_pop($this->cache); } return $analysis; } /** * Check whether appending a semicolon would make the code parseable. */ public function canBeFixedWithSemicolon(string $code): bool { try { $this->parser->parse(' $token) { $text = \is_array($token) ? $token[1] : $token; $length = \mb_strlen($text); $tokenPositions[$index] = ['start' => $position, 'end' => $position + $length]; $position += $length; } $ast = null; $lastError = null; try { // Trailing newline improves heredoc EOF behavior to match runtime checks. $ast = $this->parser->parse('createAnalysis($code, $tokens, $tokenPositions, $ast, $lastError); } /** * @param string $code * @param array $tokens * @param array $tokenPositions * @param array|null $ast */ protected function createAnalysis(string $code, array $tokens, array $tokenPositions, ?array $ast, ?Error $lastError): BufferAnalysis { return new BufferAnalysis($code, $tokens, $tokenPositions, $ast, $lastError); } }