From 14622ea1d57ce21c131d9fec908885960fc2ed48 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Fri, 9 Oct 2026 15:50:28 +0200 Subject: [PATCH] Pass File as explicit argument to RectorRunner::run() --- .../NodeTraverser/RectorNodeTraverser.php | 17 +++++++++++++++-- src/Rector/RectorRunner.php | 18 +----------------- tests/Rector/RectorRunner/RectorRunnerTest.php | 7 ++----- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/PhpParser/NodeTraverser/RectorNodeTraverser.php b/src/PhpParser/NodeTraverser/RectorNodeTraverser.php index 190b958e8ef..8f869054f16 100644 --- a/src/PhpParser/NodeTraverser/RectorNodeTraverser.php +++ b/src/PhpParser/NodeTraverser/RectorNodeTraverser.php @@ -10,10 +10,12 @@ use PhpParser\Node\Stmt; use PhpParser\NodeTraverserInterface; use PhpParser\NodeVisitor; +use Rector\Application\Provider\CurrentFileProvider; use Rector\Configuration\ConfigurationRuleFilter; use Rector\Contract\Rector\RectorInterface; use Rector\Exception\ShouldNotHappenException; use Rector\Rector\RectorRunner; +use Rector\ValueObject\Application\File; use Rector\VersionBonding\ComposerPackageConstraintFilter; use Rector\VersionBonding\PhpVersionedFilter; use Webmozart\Assert\Assert; @@ -40,6 +42,8 @@ final class RectorNodeTraverser implements NodeTraverserInterface private bool $areNodeVisitorsPrepared = false; + private File $file; + /** * @var array, RectorInterface[]> */ @@ -54,6 +58,7 @@ public function __construct( private readonly ComposerPackageConstraintFilter $composerPackageConstraintFilter, private readonly ConfigurationRuleFilter $configurationRuleFilter, private readonly RectorRunner $rectorRunner, + private readonly CurrentFileProvider $currentFileProvider, ) { } @@ -75,6 +80,14 @@ public function traverse(array $nodes): array { $this->prepareNodeVisitors(); + $file = $this->currentFileProvider->getFile(); + if (! $file instanceof File) { + throw new ShouldNotHappenException( + 'File object is missing. Make sure you call $this->currentFileProvider->setFile(...) before traversing.' + ); + } + + $this->file = $file; $this->stopTraversal = false; return $this->traverseArray($nodes); @@ -146,7 +159,7 @@ private function traverseNode(Node $node): void $currentNodeVisitors = $this->getVisitorsForNode($subNode); foreach ($currentNodeVisitors as $currentNodeVisitor) { - $return = $this->rectorRunner->run($currentNodeVisitor, $subNode); + $return = $this->rectorRunner->run($currentNodeVisitor, $subNode, $this->file); if ($return !== null) { if ($return instanceof Node) { $originalSubNodeClass = $subNode::class; @@ -206,7 +219,7 @@ private function traverseArray(array $nodes): array $currentNodeVisitors = $this->getVisitorsForNode($node); foreach ($currentNodeVisitors as $currentNodeVisitor) { - $return = $this->rectorRunner->run($currentNodeVisitor, $node); + $return = $this->rectorRunner->run($currentNodeVisitor, $node, $this->file); if ($return !== null) { if ($return instanceof Node) { $originalNodeNodeClass = $node::class; diff --git a/src/Rector/RectorRunner.php b/src/Rector/RectorRunner.php index a4548a97216..dfd2696f882 100644 --- a/src/Rector/RectorRunner.php +++ b/src/Rector/RectorRunner.php @@ -10,7 +10,6 @@ use PhpParser\NodeVisitor\CloningVisitor; use PHPStan\Analyser\MutatingScope; use Rector\Application\ChangedNodeScopeRefresher; -use Rector\Application\Provider\CurrentFileProvider; use Rector\ChangesReporting\ValueObject\RectorWithLineChange; use Rector\Contract\Rector\HTMLAverseRectorInterface; use Rector\Contract\Rector\RectorInterface; @@ -46,17 +45,14 @@ public function __construct( private Skipper $skipper, private CreatedByRuleDecorator $createdByRuleDecorator, private ChangedNodeScopeRefresher $changedNodeScopeRefresher, - private CurrentFileProvider $currentFileProvider, ) { } /** * @return int|Node|Node[]|null */ - public function run(RectorInterface $rector, Node $node): int|Node|null|array + public function run(RectorInterface $rector, Node $node, File $file): int|Node|null|array { - $file = $this->getFile(); - if ($rector instanceof HTMLAverseRectorInterface && $file->containsHTML()) { return null; } @@ -114,18 +110,6 @@ public function run(RectorInterface $rector, Node $node): int|Node|null|array return $this->postRefactorProcess($rector, $file, $originalNode, $node, $refactoredNodeOrState, $filePath); } - private function getFile(): File - { - $file = $this->currentFileProvider->getFile(); - if (! $file instanceof File) { - throw new ShouldNotHappenException( - 'File object is missing. Make sure you call $this->currentFileProvider->setFile(...) before traversing.' - ); - } - - return $file; - } - /** * Deep clone, so a skipped rule can be probed on the clone without mutating the real node. */ diff --git a/tests/Rector/RectorRunner/RectorRunnerTest.php b/tests/Rector/RectorRunner/RectorRunnerTest.php index d07cf86118f..5100d57f32d 100644 --- a/tests/Rector/RectorRunner/RectorRunnerTest.php +++ b/tests/Rector/RectorRunner/RectorRunnerTest.php @@ -5,7 +5,6 @@ namespace Rector\Tests\Rector\RectorRunner; use PhpParser\Node\Stmt\Class_; -use Rector\Application\Provider\CurrentFileProvider; use Rector\Rector\RectorRunner; use Rector\Testing\PHPUnit\AbstractLazyTestCase; use Rector\Tests\Rector\RectorRunner\Source\ReturnNullRector; @@ -23,14 +22,12 @@ protected function setUp(): void parent::setUp(); $this->rectorRunner = $this->make(RectorRunner::class); - - $currentFileProvider = $this->make(CurrentFileProvider::class); - $currentFileProvider->setFile(new File('some_file.php', 'rectorRunner->run(new ReturnNullRector(), new Class_('SomeClass')); + $file = new File('some_file.php', 'rectorRunner->run(new ReturnNullRector(), new Class_('SomeClass'), $file); $this->assertNull($return); }