[Order] Deprecate rather coding standard related set, use OrderedClassElementsFixer instead (#1910)

This commit is contained in:
Tomas Votruba 2022-03-07 13:07:18 +01:00 committed by GitHub
parent 9660188944
commit 15c8106871
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 0 additions and 804 deletions

View File

@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
use Rector\Order\Rector\Class_\OrderPrivateMethodsByUseRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(OrderPrivateMethodsByUseRector::class);
};

View File

@ -68,11 +68,6 @@ final class SetList implements SetListInterface
*/
public const NAMING = __DIR__ . '/../../../config/set/naming.php';
/**
* @var string
*/
public const ORDER = __DIR__ . '/../../../config/set/order.php';
/**
* @var string
*/

View File

@ -1,44 +0,0 @@
<?php
namespace Rector\Tests\Order\Rector\Class_\OrderPrivateMethodsByUseRector\Fixture;
class Fixture
{
public function run()
{
$this->call1();
$this->call2();
}
private function call2()
{
}
private function call1()
{
}
}
?>
-----
<?php
namespace Rector\Tests\Order\Rector\Class_\OrderPrivateMethodsByUseRector\Fixture;
class Fixture
{
public function run()
{
$this->call1();
$this->call2();
}
private function call1()
{
}
private function call2()
{
}
}
?>

View File

@ -1,53 +0,0 @@
<?php
namespace Rector\Tests\Order\Rector\Class_\OrderPrivateMethodsByUseRector\Fixture;
class MultiCall
{
public function run()
{
$this->call3();
}
private function call2()
{
}
private function call1()
{
}
private function call3()
{
$this->call1();
$this->call2();
}
}
?>
-----
<?php
namespace Rector\Tests\Order\Rector\Class_\OrderPrivateMethodsByUseRector\Fixture;
class MultiCall
{
public function run()
{
$this->call3();
}
private function call3()
{
$this->call1();
$this->call2();
}
private function call1()
{
}
private function call2()
{
}
}
?>

View File

@ -1,155 +0,0 @@
<?php
namespace Rector\Tests\Order\Rector\Class_\OrderPrivateMethodsByUseRector\Fixture;
use PhpParser\Node;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\SmartFileSystem\SmartFileInfo;
class MultipleRunsClass
{
public function refactor(Node $node): ?Node
{
if ($this->shouldSkip($node)) {
return null;
}
$node->params = $this->getSortedParams($node);
return $node;
}
public function configure(array $configuration): void
{
}
private function getSortedParams(ClassMethod $classMethod): array
{
$params = $classMethod->getParams();
usort($params, function (Param $firstParam, Param $secondParam) {
$firstParamType = $this->getParamType($firstParam);
$secondParamType = $this->getParamType($secondParam);
return $this->getShortName($firstParamType) <=> $this->getShortName($secondParamType);
});
return $params;
}
private function hasPrimitiveDataTypeParam(ClassMethod $classMethod): bool
{
}
private function shouldSkip(ClassMethod $classMethod): bool
{
if ($this->hasPrimitiveDataTypeParam($classMethod)) {
return true;
}
return $this->hasParamWithNoType($classMethod);
}
private function getParamType(Param $param)
{
}
private function hasParamWithNoType(ClassMethod $classMethod): bool
{
}
private function isFileInfoMatch(SmartFileInfo $smartFileInfo): bool
{
foreach ($this->skipPatterns as $pattern) {
if (fnmatch($pattern, $smartFileInfo->getRelativeFilePath(), FNM_NOESCAPE)) {
return true;
}
}
return false;
}
}
?>
-----
<?php
namespace Rector\Tests\Order\Rector\Class_\OrderPrivateMethodsByUseRector\Fixture;
use PhpParser\Node;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\SmartFileSystem\SmartFileInfo;
class MultipleRunsClass
{
public function refactor(Node $node): ?Node
{
if ($this->shouldSkip($node)) {
return null;
}
$node->params = $this->getSortedParams($node);
return $node;
}
public function configure(array $configuration): void
{
}
private function shouldSkip(ClassMethod $classMethod): bool
{
if ($this->hasPrimitiveDataTypeParam($classMethod)) {
return true;
}
return $this->hasParamWithNoType($classMethod);
}
private function getSortedParams(ClassMethod $classMethod): array
{
$params = $classMethod->getParams();
usort($params, function (Param $firstParam, Param $secondParam) {
$firstParamType = $this->getParamType($firstParam);
$secondParamType = $this->getParamType($secondParam);
return $this->getShortName($firstParamType) <=> $this->getShortName($secondParamType);
});
return $params;
}
private function hasPrimitiveDataTypeParam(ClassMethod $classMethod): bool
{
}
private function hasParamWithNoType(ClassMethod $classMethod): bool
{
}
private function getParamType(Param $param)
{
}
private function isFileInfoMatch(SmartFileInfo $smartFileInfo): bool
{
foreach ($this->skipPatterns as $pattern) {
if (fnmatch($pattern, $smartFileInfo->getRelativeFilePath(), FNM_NOESCAPE)) {
return true;
}
}
return false;
}
}
?>

View File

@ -1,64 +0,0 @@
<?php
namespace Rector\Tests\Order\Rector\Class_\OrderPrivateMethodsByUseRector\Fixture;
class SkipDifferentAmountOfMethods
{
public function run()
{
$this->call1();
$this->call2();
$this->publicCall1();
}
public function publicCall1()
{
}
private function call2()
{
}
private function call1()
{
}
private function call3()
{
}
}
?>
-----
<?php
namespace Rector\Tests\Order\Rector\Class_\OrderPrivateMethodsByUseRector\Fixture;
class SkipDifferentAmountOfMethods
{
public function run()
{
$this->call1();
$this->call2();
$this->publicCall1();
}
public function publicCall1()
{
}
private function call1()
{
}
private function call2()
{
}
private function call3()
{
}
}
?>

View File

@ -1,33 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Tests\Order\Rector\Class_\OrderPrivateMethodsByUseRector;
use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
final class OrderPrivateMethodsByUseRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
/**
* @return Iterator<SmartFileInfo>
*/
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}

View File

@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
use Rector\Order\Rector\Class_\OrderPrivateMethodsByUseRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(OrderPrivateMethodsByUseRector::class);
};

View File

@ -1,113 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Tests\Order;
use Iterator;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\PropertyProperty;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\Order\StmtOrder;
use Rector\Testing\PHPUnit\AbstractTestCase;
final class StmtOrderTest extends AbstractTestCase
{
/**
* @var int[]
*/
private const OLD_TO_NEW_KEYS = [
0 => 0,
1 => 2,
2 => 1,
];
private StmtOrder $stmtOrder;
private NodeNameResolver $nodeNameResolver;
protected function setUp(): void
{
$this->boot();
$this->stmtOrder = $this->getService(StmtOrder::class);
$this->nodeNameResolver = $this->getService(NodeNameResolver::class);
}
/**
* @return Iterator<array<int, array<int|string>>>
*/
public function dataProvider(): Iterator
{
yield [
['first', 'second', 'third'],
['third', 'first', 'second'],
[
0 => 1,
1 => 2,
2 => 0,
],
];
yield [
['first', 'second', 'third'],
['third', 'second', 'first'],
[
0 => 2,
1 => 1,
2 => 0,
],
];
yield [
['first', 'second', 'third'],
['first', 'second', 'third'],
[
0 => 0,
1 => 1,
2 => 2,
],
];
}
/**
* @dataProvider dataProvider
* @param string[] $desiredStmtOrder
* @param string[] $currentStmtOrder
* @param int[] $expected
*/
public function testCreateOldToNewKeys(array $desiredStmtOrder, array $currentStmtOrder, array $expected): void
{
$actual = $this->stmtOrder->createOldToNewKeys($desiredStmtOrder, $currentStmtOrder);
$this->assertSame($expected, $actual);
}
public function testReorderClassStmtsByOldToNewKeys(): void
{
$class = $this->getTestClassNode();
$this->stmtOrder->reorderClassStmtsByOldToNewKeys($class, self::OLD_TO_NEW_KEYS);
$expectedClass = $this->getExpectedClassNode();
$this->assertTrue($this->nodeNameResolver->areNamesEqual($expectedClass->stmts[0], $class->stmts[0]));
$this->assertTrue($this->nodeNameResolver->areNamesEqual($expectedClass->stmts[1], $class->stmts[1]));
$this->assertTrue($this->nodeNameResolver->areNamesEqual($expectedClass->stmts[2], $class->stmts[2]));
}
private function getTestClassNode(): Class_
{
$class = new Class_('ClassUnderTest');
$class->stmts[] = new Property(Class_::MODIFIER_PRIVATE, [new PropertyProperty('name')]);
$class->stmts[] = new Property(Class_::MODIFIER_PRIVATE, [new PropertyProperty('service')]);
$class->stmts[] = new Property(Class_::MODIFIER_PRIVATE, [new PropertyProperty('price')]);
return $class;
}
private function getExpectedClassNode(): Class_
{
$expectedClass = new Class_('ExpectedClass');
$expectedClass->stmts[] = new Property(Class_::MODIFIER_PRIVATE, [new PropertyProperty('name')]);
$expectedClass->stmts[] = new Property(Class_::MODIFIER_PRIVATE, [new PropertyProperty('price')]);
$expectedClass->stmts[] = new Property(Class_::MODIFIER_PRIVATE, [new PropertyProperty('service')]);
return $expectedClass;
}
}

View File

@ -1,198 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Order\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Trait_;
use Rector\Core\Rector\AbstractRector;
use Rector\Order\StmtOrder;
use Rector\Order\ValueObject\SortedClassMethodsAndOriginalClassMethods;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\Order\Rector\Class_\OrderPrivateMethodsByUseRector\OrderPrivateMethodsByUseRectorTest
*/
final class OrderPrivateMethodsByUseRector extends AbstractRector
{
/**
* @var int
*/
private const MAX_ATTEMPTS = 5;
public function __construct(
private readonly StmtOrder $stmtOrder
) {
}
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'Order private methods in order of their use',
[
new CodeSample(
<<<'CODE_SAMPLE'
class SomeClass
{
public function run()
{
$this->call1();
$this->call2();
}
private function call2()
{
}
private function call1()
{
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
class SomeClass
{
public function run()
{
$this->call1();
$this->call2();
}
private function call1()
{
}
private function call2()
{
}
}
CODE_SAMPLE
),
]
);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [Class_::class, Trait_::class];
}
/**
* @param Class_|Trait_ $node
*/
public function refactor(Node $node): ?Node
{
$sortedAndOriginalClassMethods = $this->getSortedAndOriginalClassMethods($node);
// order is correct, nothing to change
if (! $sortedAndOriginalClassMethods->hasOrderChanged()) {
return null;
}
// different private method count, one of them is dead probably
$attempt = 0;
while (! $sortedAndOriginalClassMethods->hasOrderSame()) {
++$attempt;
if ($attempt >= self::MAX_ATTEMPTS) {
break;
}
$oldToNewKeys = $this->stmtOrder->createOldToNewKeys(
$sortedAndOriginalClassMethods->getSortedClassMethods(),
$sortedAndOriginalClassMethods->getOriginalClassMethods()
);
$this->stmtOrder->reorderClassStmtsByOldToNewKeys($node, $oldToNewKeys);
$sortedAndOriginalClassMethods = $this->getSortedAndOriginalClassMethods($node);
}
return $node;
}
private function getSortedAndOriginalClassMethods(
Class_ | Trait_ $classLike
): SortedClassMethodsAndOriginalClassMethods {
return new SortedClassMethodsAndOriginalClassMethods(
$this->getLocalPrivateMethodCallOrder($classLike),
$this->resolvePrivateClassMethods($classLike)
);
}
/**
* @return array<int, string>
*/
private function getLocalPrivateMethodCallOrder(Class_|Trait_ $classLike): array
{
$localPrivateMethodCallInOrder = [];
$this->traverseNodesWithCallable($classLike->getMethods(), function (Node $node) use (
&$localPrivateMethodCallInOrder,
$classLike
) {
if (! $node instanceof MethodCall) {
return null;
}
if (! $node->var instanceof Variable) {
return null;
}
if (! $this->nodeNameResolver->isName($node->var, 'this')) {
return null;
}
$methodName = $this->getName($node->name);
if ($methodName === null) {
return null;
}
$classMethod = $classLike->getMethod($methodName);
if (! $classMethod instanceof ClassMethod) {
return null;
}
if ($classMethod->isPrivate()) {
$localPrivateMethodCallInOrder[] = $methodName;
}
return null;
});
return array_unique($localPrivateMethodCallInOrder);
}
/**
* @return array<int, string>
*/
private function resolvePrivateClassMethods(Class_|Trait_ $classLike): array
{
/** @var array<int, string> $privateClassMethodNames */
$privateClassMethodNames = [];
foreach ($classLike->stmts as $key => $classStmt) {
if (! $classStmt instanceof ClassMethod) {
continue;
}
if (! $classStmt->isPrivate()) {
continue;
}
/** @var string $classMethodName */
$classMethodName = $this->getName($classStmt);
$privateClassMethodNames[$key] = $classMethodName;
}
return $privateClassMethodNames;
}
}

View File

@ -1,70 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Order;
use PhpParser\Node;
use PhpParser\Node\Stmt\ClassLike;
/**
* @see \Rector\Tests\Order\StmtOrderTest
*/
final class StmtOrder
{
/**
* @param array<int, string> $desiredStmtOrder
* @param array<int, string> $currentStmtOrder
* @return array<int, int>
*/
public function createOldToNewKeys(array $desiredStmtOrder, array $currentStmtOrder): array
{
$newKeys = [];
foreach ($desiredStmtOrder as $singleDesiredStmtOrder) {
foreach ($currentStmtOrder as $currentKey => $classMethodName) {
if ($classMethodName === $singleDesiredStmtOrder) {
$newKeys[] = $currentKey;
}
}
}
$oldKeys = array_values($newKeys);
sort($oldKeys);
/** @var array<int, int> $oldToNewKeys */
$oldToNewKeys = array_combine($oldKeys, $newKeys);
return $oldToNewKeys;
}
/**
* @param array<int, int> $oldToNewKeys
*/
public function reorderClassStmtsByOldToNewKeys(ClassLike $classLike, array $oldToNewKeys): void
{
/** @var array<int, Node\Stmt> $reorderedStmts */
$reorderedStmts = [];
$stmtCount = count($classLike->stmts);
foreach ($classLike->stmts as $key => $stmt) {
if (! array_key_exists($key, $oldToNewKeys)) {
$reorderedStmts[$key] = $stmt;
continue;
}
// reorder here
$newKey = $oldToNewKeys[$key];
$reorderedStmts[$key] = $classLike->stmts[$newKey];
}
for ($i = 0; $i < $stmtCount; ++$i) {
if (! array_key_exists($i, $reorderedStmts)) {
continue;
}
$classLike->stmts[$i] = $reorderedStmts[$i];
}
}
}

View File

@ -1,47 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Order\ValueObject;
final class SortedClassMethodsAndOriginalClassMethods
{
/**
* @param array<int, string> $sortedClassMethods
* @param array<int, string> $originalClassMethods
*/
public function __construct(
private readonly array $sortedClassMethods,
private readonly array $originalClassMethods
) {
}
/**
* @return array<int, string>
*/
public function getSortedClassMethods(): array
{
return $this->sortedClassMethods;
}
/**
* @return array<int, string>
*/
public function getOriginalClassMethods(): array
{
return $this->originalClassMethods;
}
public function hasOrderChanged(): bool
{
return $this->sortedClassMethods !== $this->originalClassMethods;
}
public function hasOrderSame(): bool
{
$sortedClassMethodValues = array_values($this->sortedClassMethods);
$originalClassMethodValues = array_values($this->originalClassMethods);
return $sortedClassMethodValues === $originalClassMethodValues;
}
}