Skip to content

Commit e3ad355

Browse files
Optimise post rectors (#6240)
* Optimise NameImportingPostRector * Optimise UseAddingPostRector * Optimise ClassRenamingPostRector * Optimise UnusedImportRemovingPostRector * Add comment explaining the use of STOP_TRAVERSAL * Updates after PR review
1 parent be50454 commit e3ad355

4 files changed

Lines changed: 48 additions & 31 deletions

File tree

src/PostRector/Rector/ClassRenamingPostRector.php

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ final class ClassRenamingPostRector extends AbstractPostRector
2323
{
2424
private FileWithoutNamespace|Namespace_|null $rootNode = null;
2525

26+
/**
27+
* @var array<string, string>
28+
*/
29+
private array $oldToNewClasses = [];
30+
2631
public function __construct(
2732
private readonly ClassRenamer $classRenamer,
2833
private readonly RenamedClassesDataCollector $renamedClassesDataCollector,
@@ -50,18 +55,13 @@ public function enterNode(Node $node): ?Node
5055
return null;
5156
}
5257

53-
$oldToNewClasses = $this->renamedClassesDataCollector->getOldToNewClasses();
54-
if ($oldToNewClasses === []) {
55-
return null;
56-
}
57-
5858
/** @var Scope|null $scope */
5959
$scope = $node->getAttribute(AttributeKey::SCOPE);
6060

6161
if ($node instanceof FullyQualified) {
62-
$result = $this->classRenamer->renameNode($node, $oldToNewClasses, $scope);
62+
$result = $this->classRenamer->renameNode($node, $this->oldToNewClasses, $scope);
6363
} else {
64-
$result = $this->resolveResultWithPhpAttributeName($node, $oldToNewClasses, $scope);
64+
$result = $this->resolveResultWithPhpAttributeName($node, $scope);
6565
}
6666

6767
if (! SimpleParameterProvider::provideBoolParameter(Option::AUTO_IMPORT_NAMES)) {
@@ -88,19 +88,20 @@ public function afterTraverse(array $nodes): array
8888
return $nodes;
8989
}
9090

91-
/**
92-
* @param array<string, string> $oldToNewClasses
93-
*/
94-
private function resolveResultWithPhpAttributeName(
95-
Name $name,
96-
array $oldToNewClasses,
97-
?Scope $scope
98-
): ?FullyQualified {
91+
public function shouldTraverse(array $stmts): bool
92+
{
93+
$this->oldToNewClasses = $this->renamedClassesDataCollector->getOldToNewClasses();
94+
95+
return $this->oldToNewClasses !== [];
96+
}
97+
98+
private function resolveResultWithPhpAttributeName(Name $name, ?Scope $scope): ?FullyQualified
99+
{
99100
$phpAttributeName = $name->getAttribute(AttributeKey::PHP_ATTRIBUTE_NAME);
100101
if (is_string($phpAttributeName)) {
101102
return $this->classRenamer->renameNode(
102103
new FullyQualified($phpAttributeName, $name->getAttributes()),
103-
$oldToNewClasses,
104+
$this->oldToNewClasses,
104105
$scope
105106
);
106107
}

src/PostRector/Rector/NameImportingPostRector.php

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020

2121
final class NameImportingPostRector extends AbstractPostRector
2222
{
23+
/**
24+
* @var array<Use_|GroupUse>
25+
*/
26+
private array $currentUses = [];
27+
2328
public function __construct(
2429
private readonly NameImporter $nameImporter,
2530
private readonly ClassNameImportSkipper $classNameImportSkipper,
@@ -29,6 +34,12 @@ public function __construct(
2934
) {
3035
}
3136

37+
public function beforeTraverse(array $nodes)
38+
{
39+
$this->currentUses = $this->useImportsResolver->resolve();
40+
return $nodes;
41+
}
42+
3243
public function enterNode(Node $node): Node|int|null
3344
{
3445
if (! $node instanceof FullyQualified) {
@@ -39,13 +50,12 @@ public function enterNode(Node $node): Node|int|null
3950
return null;
4051
}
4152

42-
$currentUses = $this->useImportsResolver->resolve();
43-
if ($this->classNameImportSkipper->shouldSkipName($node, $currentUses)) {
53+
if ($this->classNameImportSkipper->shouldSkipName($node, $this->currentUses)) {
4454
return null;
4555
}
4656

4757
// make use of existing use import
48-
$nameInUse = $this->resolveNameInUse($node, $currentUses);
58+
$nameInUse = $this->resolveNameInUse($node);
4959
if ($nameInUse instanceof Name) {
5060
$nameInUse->setAttribute(AttributeKey::NAMESPACED_NAME, $node->toString());
5161
return $nameInUse;
@@ -62,12 +72,9 @@ public function shouldTraverse(array $stmts): bool
6272
return $this->addUseStatementGuard->shouldTraverse($stmts, $this->getFile()->getFilePath());
6373
}
6474

65-
/**
66-
* @param array<Use_|GroupUse> $currentUses
67-
*/
68-
private function resolveNameInUse(FullyQualified $fullyQualified, array $currentUses): null|Name
75+
private function resolveNameInUse(FullyQualified $fullyQualified): null|Name
6976
{
70-
$aliasName = $this->aliasNameResolver->resolveByName($fullyQualified, $currentUses);
77+
$aliasName = $this->aliasNameResolver->resolveByName($fullyQualified, $this->currentUses);
7178
if (is_string($aliasName)) {
7279
return new Name($aliasName);
7380
}
@@ -77,7 +84,7 @@ private function resolveNameInUse(FullyQualified $fullyQualified, array $current
7784
}
7885

7986
$lastName = $fullyQualified->getLast();
80-
foreach ($currentUses as $currentUse) {
87+
foreach ($this->currentUses as $currentUse) {
8188
foreach ($currentUse->uses as $useUse) {
8289
if ($useUse->name->getLast() !== $lastName) {
8390
continue;

src/PostRector/Rector/UnusedImportRemovingPostRector.php

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
use PhpParser\Node\Stmt\UseUse;
1717
use PhpParser\NodeTraverser;
1818
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
19-
use Rector\Configuration\Option;
20-
use Rector\Configuration\Parameter\SimpleParameterProvider;
2119
use Rector\NodeTypeResolver\Node\AttributeKey;
2220
use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser;
2321
use Rector\PhpParser\Node\CustomNode\FileWithoutNamespace;
@@ -36,10 +34,6 @@ public function enterNode(Node $node): ?Node
3634
return null;
3735
}
3836

39-
if (! SimpleParameterProvider::provideBoolParameter(Option::REMOVE_UNUSED_IMPORTS)) {
40-
return null;
41-
}
42-
4337
$hasChanged = false;
4438

4539
$namespaceName = $node instanceof Namespace_ && $node->name instanceof Name

src/PostRector/Rector/UseAddingPostRector.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
namespace Rector\PostRector\Rector;
66

7+
use PhpParser\Node;
78
use PhpParser\Node\Stmt;
89
use PhpParser\Node\Stmt\Namespace_;
10+
use PhpParser\NodeTraverser;
911
use Rector\CodingStyle\Application\UseImportsAdder;
1012
use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory;
1113
use Rector\PhpParser\Node\CustomNode\FileWithoutNamespace;
@@ -68,6 +70,19 @@ public function beforeTraverse(array $nodes): array
6870
);
6971
}
7072

73+
public function enterNode(Node $node): int
74+
{
75+
/**
76+
* We stop the traversal because all the work has already been done in the beforeTraverse() function
77+
*
78+
* Using STOP_TRAVERSAL is usually dangerous as it will stop the processing of all your nodes for all visitors
79+
* but since the PostFileProcessor is using direct new NodeTraverser() and traverse() for only a single
80+
* visitor per execution, using stop traversal here is safe,
81+
* ref https://github.com/rectorphp/rector-src/blob/fc1e742fa4d9861ccdc5933f3b53613b8223438d/src/PostRector/Application/PostFileProcessor.php#L59-L61
82+
*/
83+
return NodeTraverser::STOP_TRAVERSAL;
84+
}
85+
7186
/**
7287
* @param Stmt[] $nodes
7388
* @param FullyQualifiedObjectType[] $useImportTypes

0 commit comments

Comments
 (0)