From 0b0d2ebdf90939c733282cd537068bd0ab32cee3 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sat, 17 Oct 2026 16:48:10 +0200 Subject: [PATCH] cache aliased uses per file in AliasUsesResolver --- .../ClassNameImport/AliasUsesResolver.php | 62 ++++++++++++++----- .../AliasClassNameImportSkipVoter.php | 2 +- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/rules/CodingStyle/ClassNameImport/AliasUsesResolver.php b/rules/CodingStyle/ClassNameImport/AliasUsesResolver.php index 2419c381f58..6d89f2c1d7e 100644 --- a/rules/CodingStyle/ClassNameImport/AliasUsesResolver.php +++ b/rules/CodingStyle/ClassNameImport/AliasUsesResolver.php @@ -4,41 +4,48 @@ namespace Rector\CodingStyle\ClassNameImport; -use PhpParser\Node; use PhpParser\Node\Identifier; use PhpParser\Node\Stmt; use PhpParser\Node\Stmt\Namespace_; use PhpParser\Node\Stmt\Use_; use PhpParser\Node\UseItem; use Rector\PhpParser\Node\FileNode; +use Rector\ValueObject\Application\File; -final readonly class AliasUsesResolver +final class AliasUsesResolver { + private ?File $cachedFile = null; + + private int $cachedVersion = -1; + + /** + * @var string[] + */ + private array $cachedAliasedUses = []; + public function __construct( - private UseImportsTraverser $useImportsTraverser + private readonly UseImportsTraverser $useImportsTraverser ) { } /** - * @param Stmt[] $stmts + * Aliased uses are file-global, so resolve once per file stmts version and reuse + * across every imported name in the same traversal + * * @return string[] */ - public function resolveFromNode(Node $node, array $stmts): array + public function resolveFromFile(File $file): array { - if (! $node instanceof Namespace_ && ! $node instanceof FileNode) { - /** @var Namespace_[]|FileNode[] $namespaces */ - $namespaces = array_filter( - $stmts, - static fn (Stmt $stmt): bool => $stmt instanceof Namespace_ || $stmt instanceof FileNode - ); - if (count($namespaces) !== 1) { - return []; - } - - $node = current($namespaces); + $newStmtsVersion = $file->getNewStmtsVersion(); + if ($file === $this->cachedFile && $newStmtsVersion === $this->cachedVersion) { + return $this->cachedAliasedUses; } - return $this->resolveFromStmts($node->stmts); + $this->cachedFile = $file; + $this->cachedVersion = $newStmtsVersion; + $this->cachedAliasedUses = $this->resolveFromNewStmts($file->getNewStmts()); + + return $this->cachedAliasedUses; } /** @@ -68,4 +75,25 @@ public function resolveFromStmts(array $stmts): array return $aliasedUses; } + + /** + * @param Stmt[] $stmts + * @return string[] + */ + private function resolveFromNewStmts(array $stmts): array + { + /** @var Namespace_[]|FileNode[] $namespaces */ + $namespaces = array_filter( + $stmts, + static fn (Stmt $stmt): bool => $stmt instanceof Namespace_ || $stmt instanceof FileNode + ); + + if (count($namespaces) !== 1) { + return []; + } + + $namespace = current($namespaces); + + return $this->resolveFromStmts($namespace->stmts); + } } diff --git a/rules/CodingStyle/ClassNameImport/ClassNameImportSkipVoter/AliasClassNameImportSkipVoter.php b/rules/CodingStyle/ClassNameImport/ClassNameImportSkipVoter/AliasClassNameImportSkipVoter.php index c774a0c4e07..9282e7c37ea 100644 --- a/rules/CodingStyle/ClassNameImport/ClassNameImportSkipVoter/AliasClassNameImportSkipVoter.php +++ b/rules/CodingStyle/ClassNameImport/ClassNameImportSkipVoter/AliasClassNameImportSkipVoter.php @@ -28,7 +28,7 @@ public function __construct( public function shouldSkip(File $file, FullyQualifiedObjectType $fullyQualifiedObjectType, Node $node): bool { - $aliasedUses = $this->aliasUsesResolver->resolveFromNode($node, $file->getNewStmts()); + $aliasedUses = $this->aliasUsesResolver->resolveFromFile($file); $longNameLowered = strtolower($fullyQualifiedObjectType->getClassName()); $shortNameLowered = $fullyQualifiedObjectType->getShortNameLowered();