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
44 changes: 44 additions & 0 deletions packages/post-rector/src/Rector/ClassRenamingPostRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

namespace Rector\PostRector\Rector;

use PhpParser\Node;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\PSR4\Collector\RenamedClassesCollector;
use Rector\Renaming\NodeManipulator\ClassRenamer;

final class ClassRenamingPostRector extends AbstractPostRector
{
/**
* @var RenamedClassesCollector
*/
private $renamedClassesCollector;

/**
* @var ClassRenamer
*/
private $classRenamer;

public function __construct(RenamedClassesCollector $renamedClassesCollector, ClassRenamer $classRenamer)
{
$this->renamedClassesCollector = $renamedClassesCollector;
$this->classRenamer = $classRenamer;
}

public function getPriority(): int
{
return 100;
}

public function enterNode(Node $node): ?Node
{
return $this->classRenamer->renameNode($node, $this->renamedClassesCollector->getOldToNewClasses());
}

public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Post Rector that renames classes');
}
}
15 changes: 2 additions & 13 deletions rules/autodiscovery/src/FileMover/FileMover.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use Rector\Autodiscovery\Configuration\CategoryNamespaceProvider;
use Rector\Autodiscovery\ValueObject\NodesWithFileDestinationValueObject;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\PSR4\Collector\RenamedClassesCollector;
use Rector\PSR4\FileRelocationResolver;
use Symplify\SmartFileSystem\SmartFileInfo;

Expand All @@ -26,11 +25,6 @@ final class FileMover
*/
private $fileRelocationResolver;

/**
* @var RenamedClassesCollector
*/
private $renamedClassesCollector;

/**
* @var CategoryNamespaceProvider
*/
Expand All @@ -39,12 +33,10 @@ final class FileMover
public function __construct(
BetterNodeFinder $betterNodeFinder,
FileRelocationResolver $fileRelocationResolver,
RenamedClassesCollector $renamedClassesCollector,
CategoryNamespaceProvider $categoryNamespaceProvider
) {
$this->betterNodeFinder = $betterNodeFinder;
$this->fileRelocationResolver = $fileRelocationResolver;
$this->renamedClassesCollector = $renamedClassesCollector;
$this->categoryNamespaceProvider = $categoryNamespaceProvider;
}

Expand Down Expand Up @@ -75,17 +67,14 @@ public function createMovedNodesAndFilePath(
return null;
}

// 1. create helping rename class rector.yaml + class_alias autoload file
$this->renamedClassesCollector->addClassRename($currentClassName, $newClassName);

// 2. rename namespace
// 1. rename namespace
foreach ($nodes as $node) {
if ($node instanceof Namespace_) {
$node->name = new Name($newNamespaceName);
}
}

// 3. return changed nodes and new file destination
// 2. return changed nodes and new file destination
$newFileDestination = $this->fileRelocationResolver->createNewFileDestination(
$smartFileInfo,
$desiredGroupName,
Expand Down
111 changes: 5 additions & 106 deletions rules/psr4/src/Collector/RenamedClassesCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,124 +4,23 @@

namespace Rector\PSR4\Collector;

use Rector\PSR4\ValueObject\ClassRenameValueObject;

final class RenamedClassesCollector
{
/**
* @var ClassRenameValueObject[]
* @var string[]
*/
private $classRenames = [];
private $oldToNewClass = [];

public function addClassRename(string $oldClass, string $newClass): void
{
$parentClasses = $this->getParentClasses($oldClass);

$this->classRenames[$oldClass] = new ClassRenameValueObject($oldClass, $newClass, $parentClasses);
}

/**
* @return string[]
*/
public function getOldToNewClassesSortedByHighestParentsAsString(): array
{
$oldToNewClasses = [];
foreach ($this->getClassRenamesSortedByHighestParents() as $classRename) {
$oldToNewClasses[$classRename->getOldClass()] = $classRename->getNewClass();
}

return $oldToNewClasses;
}

/**
* @return ClassRenameValueObject[]
*/
public function getClassRenamesSortedByHighestParents(): array
{
$this->filterOutParentsThatAreNotCollected();

$leftClassPriorityStack = $this->createLeftClassPriorityStack();

return $this->sortClassRenamedByLeftClassPriorityStack($this->classRenames, $leftClassPriorityStack);
}

public function hasClassRenames(): bool
{
return $this->classRenames !== [];
}

/**
* Returns all parent classes, implemented interfaces and used traits by specific class
*
* @return string[]
*/
private function getParentClasses(string $className): array
{
$parentClasses = class_parents($className) + class_implements($className) + class_uses($className);

return array_values($parentClasses);
}

/**
* We don't need to sort classes that are not here.
*/
private function filterOutParentsThatAreNotCollected(): void
{
foreach ($this->classRenames as $classRename) {
foreach ($classRename->getParentClasses() as $parent) {
if (isset($this->classRenames[$parent])) {
continue;
}

$classRename->removeParent($parent);
}
}
$this->oldToNewClass[$oldClass] = $newClass;
}

/**
* @return string[]
*/
private function createLeftClassPriorityStack(): array
public function getOldToNewClasses(): array
{
$leftClassPriorityStack = [];
foreach ($this->classRenames as $classRename) {
foreach ($classRename->getParentClasses() as $parentClass) {
$leftClassPriorityStack[$parentClass] = $classRename->getOldClass();
}
}

return $leftClassPriorityStack;
}

/**
* @param ClassRenameValueObject[] $classRenames
* @param string[] $leftClassPriorityStack
* @return ClassRenameValueObject[]
*/
private function sortClassRenamedByLeftClassPriorityStack(array $classRenames, array $leftClassPriorityStack): array
{
usort($classRenames, function (
ClassRenameValueObject $firstClassRename,
ClassRenameValueObject $secondClassRename
) use ($leftClassPriorityStack): int {
if ($secondClassRename->getParentClasses() === []) {
// no parents, put first
return 1;
}

if (! isset($leftClassPriorityStack[$secondClassRename->getOldClass()])) {
return -1;
}

$lessPriorityClass = $leftClassPriorityStack[$secondClassRename->getOldClass()];
if ($lessPriorityClass === $firstClassRename->getOldClass()) {
// put class with higher priority first
return 1;
}

return -1;
});

return $classRenames;
return $this->oldToNewClass;
}
}
108 changes: 0 additions & 108 deletions rules/psr4/src/Extension/RenamedClassesReportExtension.php

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,13 @@ private function getExpectedNamespace(Node $node): ?string
foreach ($paths as $path) {
$path = rtrim($path, '/');

if (Strings::startsWith($smartFileInfo->getRelativeDirectoryPath(), $path)) {
$expectedNamespace = $namespace . $this->resolveExtraNamespace($smartFileInfo, $path);

return rtrim($expectedNamespace, '\\');
if (! Strings::startsWith($smartFileInfo->getRelativeDirectoryPath(), $path)) {
continue;
}

$expectedNamespace = $namespace . $this->resolveExtraNamespace($smartFileInfo, $path);

return rtrim($expectedNamespace, '\\');
}
}

Expand Down
Loading