From 972d933932897c7b4c12a6ccdeefa18212cb4b01 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 17 Nov 2024 09:44:34 +0700 Subject: [PATCH] Fix parsing php 7 --- .../CurlyToSquareBracketArrayStringRector.php | 6 +++--- src/Application/FileProcessor.php | 9 +++++++-- src/NodeAnalyzer/ScopeAnalyzer.php | 3 ++- .../PHPStan/Scope/PHPStanNodeScopeResolver.php | 8 ++++++++ src/PhpParser/Parser/RectorParser.php | 10 +++++++++- 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/rules/Php74/Rector/ArrayDimFetch/CurlyToSquareBracketArrayStringRector.php b/rules/Php74/Rector/ArrayDimFetch/CurlyToSquareBracketArrayStringRector.php index 848d9638c31..9e3bed6a019 100644 --- a/rules/Php74/Rector/ArrayDimFetch/CurlyToSquareBracketArrayStringRector.php +++ b/rules/Php74/Rector/ArrayDimFetch/CurlyToSquareBracketArrayStringRector.php @@ -77,9 +77,9 @@ private function isFollowedByCurlyBracket(File $file, ArrayDimFetch $arrayDimFet $oldTokens = $file->getOldTokens(); $endTokenPost = $arrayDimFetch->getEndTokenPos(); - if (isset($oldTokens[$endTokenPost]) && $oldTokens[$endTokenPost] === '}') { - $startTokenPost = $arrayDimFetch->getStartTokenPos(); - return ! (isset($oldTokens[$startTokenPost][1]) && $oldTokens[$startTokenPost][1] === '${'); + if (isset($oldTokens[$endTokenPost]) && (string) $oldTokens[$endTokenPost] === '}') { + $startTokenPos = $arrayDimFetch->getStartTokenPos(); + return ! (isset($oldTokens[$startTokenPos]) && (string) $oldTokens[$startTokenPos] === '${'); } return false; diff --git a/src/Application/FileProcessor.php b/src/Application/FileProcessor.php index 95b1e838d46..4f2930af7c0 100644 --- a/src/Application/FileProcessor.php +++ b/src/Application/FileProcessor.php @@ -112,6 +112,8 @@ private function parseFileAndDecorateNodes(File $file): ?SystemError { try { $this->parseFileNodes($file); + } catch (ParserErrorsException) { + $this->parseFileNodes($file, false); } catch (ShouldNotHappenException $shouldNotHappenException) { throw $shouldNotHappenException; } catch (AnalysedCodeException $analysedCodeException) { @@ -187,10 +189,13 @@ private function printFile(File $file, Configuration $configuration, string $fil FileSystem::write($filePath, $newContent, null); } - private function parseFileNodes(File $file): void + private function parseFileNodes(File $file, bool $forNewestSupportedVersion = true): void { // store tokens by original file content, so we don't have to print them right now - $stmtsAndTokens = $this->rectorParser->parseFileContentToStmtsAndTokens($file->getOriginalFileContent()); + $stmtsAndTokens = $this->rectorParser->parseFileContentToStmtsAndTokens( + $file->getOriginalFileContent(), + $forNewestSupportedVersion + ); $oldStmts = $stmtsAndTokens->getStmts(); $oldTokens = $stmtsAndTokens->getTokens(); diff --git a/src/NodeAnalyzer/ScopeAnalyzer.php b/src/NodeAnalyzer/ScopeAnalyzer.php index 85da62b19fa..4f4db53b48f 100644 --- a/src/NodeAnalyzer/ScopeAnalyzer.php +++ b/src/NodeAnalyzer/ScopeAnalyzer.php @@ -6,6 +6,7 @@ use PhpParser\Node; use PhpParser\Node\Arg; +use PhpParser\Node\Expr\ArrayDimFetch; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Identifier; use PhpParser\Node\Name; @@ -16,7 +17,7 @@ final class ScopeAnalyzer /** * @var array> */ - private const NON_REFRESHABLE_NODES = [Name::class, Identifier::class, Param::class, Arg::class, Variable::class]; + private const NON_REFRESHABLE_NODES = [Name::class, Identifier::class, Param::class, Arg::class, Variable::class, ArrayDimFetch::class]; public function isRefreshable(Node $node): bool { diff --git a/src/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php b/src/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php index f2f84a2a43b..0eb37b7a378 100644 --- a/src/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php +++ b/src/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php @@ -54,6 +54,8 @@ use PhpParser\Node\Stmt\TryCatch; use PhpParser\Node\UnionType; use PhpParser\NodeTraverser; +use PhpParser\ParserFactory; +use PhpParser\PhpVersion; use PHPStan\Analyser\MutatingScope; use PHPStan\Analyser\NodeScopeResolver; use PHPStan\Analyser\ScopeContext; @@ -63,6 +65,8 @@ use PHPStan\ShouldNotHappenException; use PHPStan\Type\ObjectType; use PHPStan\Type\TypeCombinator; +use Rector\Config\RectorConfig; +use Rector\DependencyInjection\LazyContainerFactory; use Rector\NodeAnalyzer\ClassAnalyzer; use Rector\NodeNameResolver\NodeNameResolver; use Rector\NodeTypeResolver\Node\AttributeKey; @@ -329,7 +333,11 @@ private function nodeScopeResolverProcessNodes( ): void { try { $this->nodeScopeResolver->processNodes($stmts, $mutatingScope, $nodeCallback); + } catch (\PHPStan\Parser\ParserErrorsException) { + // nothing we can do as error parsing from deep internal PHPStan service with service injection we cannot reset + // in the middle of process } catch (ShouldNotHappenException) { + // internal PHPStan error } } diff --git a/src/PhpParser/Parser/RectorParser.php b/src/PhpParser/Parser/RectorParser.php index 1bb469cb50f..a80fb1932f8 100644 --- a/src/PhpParser/Parser/RectorParser.php +++ b/src/PhpParser/Parser/RectorParser.php @@ -5,6 +5,8 @@ namespace Rector\PhpParser\Parser; use PhpParser\Node\Stmt; +use PhpParser\ParserFactory; +use PhpParser\PhpVersion; use PHPStan\Parser\Parser; use Rector\PhpParser\ValueObject\StmtsAndTokens; use Rector\Util\Reflection\PrivatesAccessor; @@ -35,8 +37,14 @@ public function parseString(string $fileContent): array return $this->parser->parseString($fileContent); } - public function parseFileContentToStmtsAndTokens(string $fileContent): StmtsAndTokens + public function parseFileContentToStmtsAndTokens(string $fileContent, bool $forNewestSupportedVersion = true): StmtsAndTokens { + if (! $forNewestSupportedVersion) { + $parserFactory = new ParserFactory(); + $parser = $parserFactory->createForVersion(PhpVersion::fromString('7.0')); + $this->privatesAccessor->setPrivateProperty($this->parser, 'parser', $parser); + } + $stmts = $this->parser->parseString($fileContent); $innerParser = $this->privatesAccessor->getPrivateProperty($this->parser, 'parser');