diff --git a/rules/CodingStyle/ClassNameImport/AliasUsesResolver.php b/rules/CodingStyle/ClassNameImport/AliasUsesResolver.php index 2419c381f58..e514d5f3261 100644 --- a/rules/CodingStyle/ClassNameImport/AliasUsesResolver.php +++ b/rules/CodingStyle/ClassNameImport/AliasUsesResolver.php @@ -4,13 +4,10 @@ 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; final readonly class AliasUsesResolver { @@ -19,28 +16,6 @@ public function __construct( ) { } - /** - * @param Stmt[] $stmts - * @return string[] - */ - public function resolveFromNode(Node $node, array $stmts): 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); - } - - return $this->resolveFromStmts($node->stmts); - } - /** * @param Stmt[] $stmts * @return string[] diff --git a/rules/CodingStyle/ClassNameImport/ClassNameImportContext.php b/rules/CodingStyle/ClassNameImport/ClassNameImportContext.php new file mode 100644 index 00000000000..7bf3d1562e7 --- /dev/null +++ b/rules/CodingStyle/ClassNameImport/ClassNameImportContext.php @@ -0,0 +1,104 @@ + + */ + private array $usedImportTypes = []; + + public function __construct( + private readonly AliasUsesResolver $aliasUsesResolver + ) { + } + + /** + * @return string[] + */ + public function resolveAliasedUses(File $file): array + { + $this->ensureResolved($file); + + return $this->aliasedUses; + } + + /** + * @return array + */ + public function resolveUsedImportTypes(File $file): array + { + $this->ensureResolved($file); + + return $this->usedImportTypes; + } + + private function ensureResolved(File $file): void + { + $newStmtsVersion = $file->getNewStmtsVersion(); + if ($file === $this->cachedFile && $newStmtsVersion === $this->cachedVersion) { + return; + } + + $this->cachedFile = $file; + $this->cachedVersion = $newStmtsVersion; + $this->aliasedUses = $this->resolveAliasedUsesFromFile($file); + $this->usedImportTypes = $this->resolveUsedImportTypesFromFile($file); + } + + /** + * @return string[] + */ + private function resolveAliasedUsesFromFile(File $file): array + { + /** @var Namespace_[]|FileNode[] $namespaces */ + $namespaces = array_filter( + $file->getNewStmts(), + static fn (Stmt $stmt): bool => $stmt instanceof Namespace_ || $stmt instanceof FileNode + ); + + if (count($namespaces) !== 1) { + return []; + } + + $namespace = current($namespaces); + + return $this->aliasUsesResolver->resolveFromStmts($namespace->stmts); + } + + /** + * @return array + */ + private function resolveUsedImportTypesFromFile(File $file): array + { + $fileNode = $file->getFileNode(); + if (! $fileNode instanceof FileNode) { + return []; + } + + return $fileNode->resolveUsedImportTypes(); + } +} diff --git a/rules/CodingStyle/ClassNameImport/ClassNameImportSkipVoter/AliasClassNameImportSkipVoter.php b/rules/CodingStyle/ClassNameImport/ClassNameImportSkipVoter/AliasClassNameImportSkipVoter.php index c774a0c4e07..0812f6da40a 100644 --- a/rules/CodingStyle/ClassNameImport/ClassNameImportSkipVoter/AliasClassNameImportSkipVoter.php +++ b/rules/CodingStyle/ClassNameImport/ClassNameImportSkipVoter/AliasClassNameImportSkipVoter.php @@ -5,7 +5,7 @@ namespace Rector\CodingStyle\ClassNameImport\ClassNameImportSkipVoter; use PhpParser\Node; -use Rector\CodingStyle\ClassNameImport\AliasUsesResolver; +use Rector\CodingStyle\ClassNameImport\ClassNameImportContext; use Rector\CodingStyle\Contract\ClassNameImport\ClassNameImportSkipVoterInterface; use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType; use Rector\ValueObject\Application\File; @@ -22,13 +22,13 @@ final readonly class AliasClassNameImportSkipVoter implements ClassNameImportSkipVoterInterface { public function __construct( - private AliasUsesResolver $aliasUsesResolver + private ClassNameImportContext $classNameImportContext ) { } public function shouldSkip(File $file, FullyQualifiedObjectType $fullyQualifiedObjectType, Node $node): bool { - $aliasedUses = $this->aliasUsesResolver->resolveFromNode($node, $file->getNewStmts()); + $aliasedUses = $this->classNameImportContext->resolveAliasedUses($file); $longNameLowered = strtolower($fullyQualifiedObjectType->getClassName()); $shortNameLowered = $fullyQualifiedObjectType->getShortNameLowered(); diff --git a/rules/CodingStyle/ClassNameImport/ClassNameImportSkipVoter/UsesClassNameImportSkipVoter.php b/rules/CodingStyle/ClassNameImport/ClassNameImportSkipVoter/UsesClassNameImportSkipVoter.php index a397a837651..eed696d7a1e 100644 --- a/rules/CodingStyle/ClassNameImport/ClassNameImportSkipVoter/UsesClassNameImportSkipVoter.php +++ b/rules/CodingStyle/ClassNameImport/ClassNameImportSkipVoter/UsesClassNameImportSkipVoter.php @@ -5,8 +5,8 @@ namespace Rector\CodingStyle\ClassNameImport\ClassNameImportSkipVoter; use PhpParser\Node; +use Rector\CodingStyle\ClassNameImport\ClassNameImportContext; use Rector\CodingStyle\Contract\ClassNameImport\ClassNameImportSkipVoterInterface; -use Rector\PhpParser\Node\FileNode; use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType; use Rector\ValueObject\Application\File; @@ -19,14 +19,14 @@ */ final readonly class UsesClassNameImportSkipVoter implements ClassNameImportSkipVoterInterface { + public function __construct( + private ClassNameImportContext $classNameImportContext + ) { + } + public function shouldSkip(File $file, FullyQualifiedObjectType $fullyQualifiedObjectType, Node $node): bool { - $fileNode = $file->getFileNode(); - if (! $fileNode instanceof FileNode) { - return false; - } - - $useImportTypes = $fileNode->resolveUsedImportTypes(); + $useImportTypes = $this->classNameImportContext->resolveUsedImportTypes($file); foreach ($useImportTypes as $useImportType) { if (! $useImportType->equals($fullyQualifiedObjectType) && $useImportType->areShortNamesEqual( diff --git a/rules/Visibility/Rector/ClassMethod/ChangeMethodVisibilityRector.php b/rules/Visibility/Rector/ClassMethod/ChangeMethodVisibilityRector.php index 715e7722e0e..132ad4e8fc7 100644 --- a/rules/Visibility/Rector/ClassMethod/ChangeMethodVisibilityRector.php +++ b/rules/Visibility/Rector/ClassMethod/ChangeMethodVisibilityRector.php @@ -133,12 +133,6 @@ public function configure(array $configuration): void private function hasMatchingMethodName(ClassMethod $classMethod): bool { - foreach ($this->methodVisibilities as $methodVisibility) { - if ($this->isName($classMethod, $methodVisibility->getMethod())) { - return true; - } - } - - return false; + return array_any($this->methodVisibilities, fn(ChangeMethodVisibility $methodVisibility): bool => $this->isName($classMethod, $methodVisibility->getMethod())); } }