Skip to content
Merged
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
28 changes: 21 additions & 7 deletions src/Application/FileProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,21 +58,30 @@ public function processFile(File $file, Configuration $configuration): FileProce

$fileHasChanged = false;
$filePath = $file->getFilePath();
$rulesReachedFixedPoint = false;

do {
$file->changeHasChanged(false);

// every rule and post rector records a line change when it mutates the AST
$changeCountBeforePass = count($file->getRectorWithLineChanges());

// 1. change nodes with Rector Rules
$newStmts = $this->rectorNodeTraverser->traverse($file->getNewStmts(), $file);
// 1. change nodes with Rector Rules, until they reach a fixed point
if ($rulesReachedFixedPoint) {
$newStmts = $file->getNewStmts();
} else {
$newStmts = $this->rectorNodeTraverser->traverse($file->getNewStmts(), $file);
$rulesReachedFixedPoint = count($file->getRectorWithLineChanges()) === $changeCountBeforePass;
}

// 2. apply post rectors
$postNewStmts = $this->postFileProcessor->traverse($newStmts, $file);
// 2. apply post rectors after the rules: a rule in a next pass would resolve
// a short name they import against the global namespace
if ($rulesReachedFixedPoint) {
Comment thread
samsonasik marked this conversation as resolved.
Resolved
$newStmts = $this->postFileProcessor->traverse($newStmts, $file);
}

// 3. this is needed for new tokens added in "afterTraverse()"
$file->changeNewStmts($postNewStmts);
$file->changeNewStmts($newStmts);

// file never changed and this pass changed nothing: the print would just reproduce the
// original content, so skip the expensive format-preserving print entirely.
Expand All @@ -86,9 +95,14 @@ public function processFile(File $file, Configuration $configuration): FileProce
// important to detect if file has changed
$this->printFile($file, $configuration, $filePath);

// no change in current iteration, stop
// no change in current iteration: stop, once the post rectors ran
if (! $file->hasChanged()) {
break;
if ($rulesReachedFixedPoint) {
break;
}

$rulesReachedFixedPoint = true;
continue;
}

$fileHasChanged = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Rector\Tests\Issues\ImportedNameInNextPass\Fixture;

use Rector\Tests\Issues\ImportedNameInNextPass\Source\Directory;

final class NullableEnumParam
{
public function run(?Directory $directory): void
{
if ($directory === null) {
return;
}

echo $directory->value;
}
}

?>
-----
<?php

namespace Rector\Tests\Issues\ImportedNameInNextPass\Fixture;

use Rector\Tests\Issues\ImportedNameInNextPass\Source\Directory;

final class NullableEnumParam
{
public function run(?Directory $directory): void
{
if (!$directory instanceof Directory) {
return;
}

echo $directory->value;
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Rector\Tests\Issues\ImportedNameInNextPass\Fixture;

use Rector\Tests\Issues\ImportedNameInNextPass\Source\ArrayObject;

final class NullableFinalClassParam
{
public function run(?ArrayObject $arrayObject): void
{
if ($arrayObject === null) {
return;
}

echo 'set';
}
}

?>
-----
<?php

namespace Rector\Tests\Issues\ImportedNameInNextPass\Fixture;

use Rector\Tests\Issues\ImportedNameInNextPass\Source\ArrayObject;

final class NullableFinalClassParam
{
public function run(?ArrayObject $arrayObject): void
{
if (!$arrayObject instanceof ArrayObject) {
return;
}

echo 'set';
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Rector\Tests\Issues\ImportedNameInNextPass\Fixture;

use Rector\Tests\Issues\ImportedNameInNextPass\Source\Directory;

final class SkipWrittenShortInstanceof
{
public function run(?Directory $directory): void
{
if (! $directory instanceof Directory) {
return;
}

echo $directory->value;
}
}
28 changes: 28 additions & 0 deletions tests/Issues/ImportedNameInNextPass/ImportedNameInNextPassTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\Issues\ImportedNameInNextPass;

use Iterator;
use PHPUnit\Framework\Attributes\DataProvider;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class ImportedNameInNextPassTest extends AbstractRectorTestCase
{
#[DataProvider('provideData')]
public function test(string $filePath): void
{
$this->doTestFile($filePath);
}

public static function provideData(): Iterator
{
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}
9 changes: 9 additions & 0 deletions tests/Issues/ImportedNameInNextPass/Source/ArrayObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\Issues\ImportedNameInNextPass\Source;

final class ArrayObject
{
}
10 changes: 10 additions & 0 deletions tests/Issues/ImportedNameInNextPass/Source/Directory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\Issues\ImportedNameInNextPass\Source;

enum Directory: string
{
case One = 'one';
}
11 changes: 11 additions & 0 deletions tests/Issues/ImportedNameInNextPass/config/configured_rule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

use Rector\CodeQuality\Rector\If_\ExplicitNullableObjectInstanceRector;
use Rector\Config\RectorConfig;
use Rector\DeadCode\Rector\If_\RemoveAlwaysTrueIfConditionRector;

return RectorConfig::configure()
->withRules([ExplicitNullableObjectInstanceRector::class, RemoveAlwaysTrueIfConditionRector::class])
->withImportNames();
Loading