Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions src/Application/FileProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,7 @@ public function processFile(File $file, Configuration $configuration): FileProce
private function parseFileAndDecorateNodes(File $file): ?SystemError
{
try {
try {
$this->parseFileNodes($file);
} catch (ParserErrorsException) {
$this->parseFileNodes($file, false);
}
$this->parseFileNodes($file);
} catch (ShouldNotHappenException $shouldNotHappenException) {
throw $shouldNotHappenException;
} catch (AnalysedCodeException $analysedCodeException) {
Expand Down Expand Up @@ -164,12 +160,11 @@ private function printFile(File $file, Configuration $configuration, string $fil
FileSystem::write($filePath, $newFileContent, null);
}

private function parseFileNodes(File $file, bool $forNewestSupportedVersion = true): void
private function parseFileNodes(File $file): void
{
// store tokens by original file content, so we don't have to print them right now
$stmtsAndTokens = $this->rectorParser->parseFileContentToStmtsAndTokens(
$file->getOriginalFileContent(),
$forNewestSupportedVersion
);

$oldStmts = $stmtsAndTokens->getStmts();
Expand Down
47 changes: 27 additions & 20 deletions src/PhpParser/Parser/RectorParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
use PhpParser\PhpVersion;
use PHPStan\Parser\Parser;
use PHPStan\Parser\RichParser;
use Rector\Php\PhpVersionProvider;
use Rector\PhpParser\ValueObject\StmtsAndTokens;
use Rector\Util\Reflection\PrivatesAccessor;
use Rector\ValueObject\PhpVersion as CorePhpVersion;

final readonly class RectorParser
{
Expand All @@ -19,7 +21,8 @@
*/
public function __construct(
private Parser $parser,
private PrivatesAccessor $privatesAccessor
private PrivatesAccessor $privatesAccessor,
private PhpVersionProvider $phpVersionProvider
) {
}

Expand All @@ -41,32 +44,36 @@ public function parseString(string $fileContent): array
return $this->parser->parseString($fileContent);
}

public function parseFileContentToStmtsAndTokens(
string $fileContent,
bool $forNewestSupportedVersion = true
): StmtsAndTokens {
if (! $forNewestSupportedVersion) {
// don't directly change PHPStan Parser service
// to avoid reuse on next file
$phpstanParser = clone $this->parser;
public function parseFileContentToStmtsAndTokens(string $fileContent): StmtsAndTokens
{
$parser = $this->resolveConfiguredVersionParser();

$parserFactory = new ParserFactory();
$parser = $parserFactory->createForVersion(PhpVersion::fromString('7.0'));
$this->privatesAccessor->setPrivateProperty($phpstanParser, 'parser', $parser);
$stmts = $parser->parseString($fileContent);

return $this->resolveStmtsAndTokens($phpstanParser, $fileContent);
}
$innerParser = $this->privatesAccessor->getPrivateProperty($parser, 'parser');
$tokens = $innerParser->getTokens();

return $this->resolveStmtsAndTokens($this->parser, $fileContent);
return new StmtsAndTokens($stmts, $tokens);
}

private function resolveStmtsAndTokens(Parser $parser, string $fileContent): StmtsAndTokens
private function resolveConfiguredVersionParser(): Parser
{
$stmts = $parser->parseString($fileContent);
$phpVersion = $this->phpVersionProvider->provide();

$innerParser = $this->privatesAccessor->getPrivateProperty($parser, 'parser');
$tokens = $innerParser->getTokens();
// on 8.0+ the default newest parser is correct;
// only pre-8.0 syntax (e.g. curly offset access) needs an older parser
if ($phpVersion >= CorePhpVersion::PHP_80) {
return $this->parser;
}

return new StmtsAndTokens($stmts, $tokens);
// don't mutate the shared PHPStan parser service, clone to avoid reuse on the next file
$phpstanParser = clone $this->parser;

$parser = new ParserFactory()->createForVersion(
PhpVersion::fromComponents(intdiv($phpVersion, 10000), intdiv($phpVersion % 10000, 100))
);
$this->privatesAccessor->setPrivateProperty($phpstanParser, 'parser', $parser);

return $phpstanParser;
}
}
Loading