[Order] Add OrderClassConstantsByIntegerValueRector

This commit is contained in:
TomasVotruba 2020-06-15 16:40:19 +02:00
parent 375f30db22
commit 654d97c602
6 changed files with 246 additions and 2 deletions

View File

@ -2,3 +2,4 @@ services:
Rector\Order\Rector\Class_\OrderPrivateMethodsByUseRector: null
Rector\Order\Rector\Class_\OrderPublicInterfaceMethodRector: null
Rector\Order\Rector\Class_\OrderPropertyByComplexityRector: null
Rector\Order\Rector\Class_\OrderClassConstantsByIntegerValueRector: null

View File

@ -1,4 +1,4 @@
# All 510 Rectors Overview
# All 511 Rectors Overview
- [Projects](#projects)
- [General](#general)
@ -30,7 +30,7 @@
- [NetteTesterToPHPUnit](#nettetestertophpunit) (3)
- [NetteToSymfony](#nettetosymfony) (9)
- [NetteUtilsCodeQuality](#netteutilscodequality) (1)
- [Order](#order) (3)
- [Order](#order) (4)
- [PHPOffice](#phpoffice) (14)
- [PHPStan](#phpstan) (3)
- [PHPUnit](#phpunit) (37)
@ -5153,6 +5153,28 @@ Replace time numbers with Nette\Utils\DateTime constants
## Order
### `OrderClassConstantsByIntegerValueRector`
- class: [`Rector\Order\Rector\Class_\OrderClassConstantsByIntegerValueRector`](/../master/rules/order/src/Rector/Class_/OrderClassConstantsByIntegerValueRector.php)
- [test fixtures](/../master/rules/order/tests/Rector/Class_/OrderClassConstantsByIntegerValueRector/Fixture)
Order class constant order by their integer value
```diff
class SomeClass
{
const MODE_ON = 0;
+ const MODE_MAYBE = 1;
+
const MODE_OFF = 2;
-
- const MODE_MAYBE = 1;
}
```
<br>
### `OrderPrivateMethodsByUseRector`
- class: [`Rector\Order\Rector\Class_\OrderPrivateMethodsByUseRector`](/../master/rules/order/src/Rector/Class_/OrderPrivateMethodsByUseRector.php)

View File

@ -0,0 +1,136 @@
<?php
declare(strict_types=1);
namespace Rector\Order\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassConst;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\Order\StmtOrder;
/**
* @see \Rector\Order\Tests\Rector\Class_\OrderClassConstantsByIntegerValueRector\OrderClassConstantsByIntegerValueRectorTest
*/
final class OrderClassConstantsByIntegerValueRector extends AbstractRector
{
/**
* @var StmtOrder
*/
private $stmtOrder;
public function __construct(StmtOrder $stmtOrder)
{
$this->stmtOrder = $stmtOrder;
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Order class constant order by their integer value', [
new CodeSample(
<<<'PHP'
class SomeClass
{
const MODE_ON = 0;
const MODE_OFF = 2;
const MODE_MAYBE = 1;
}
PHP
,
<<<'PHP'
class SomeClass
{
const MODE_ON = 0;
const MODE_MAYBE = 1;
const MODE_OFF = 2;
}
PHP
),
]);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [Class_::class];
}
/**
* @param Class_ $node
*/
public function refactor(Node $node): ?Node
{
$numericClassConstsByKey = $this->resolveClassConstByPosition($node);
if ($numericClassConstsByKey === []) {
return null;
}
$classConstConstsByValue = $this->resolveClastConstConstByUniqueValue($numericClassConstsByKey);
$sortedClassConstConstsByValue = $classConstConstsByValue;
asort($sortedClassConstConstsByValue);
$oldToNewKeys = $this->stmtOrder->createOldToNewKeys($sortedClassConstConstsByValue, $classConstConstsByValue);
$this->stmtOrder->reorderClassStmtsByOldToNewKeys($node, $oldToNewKeys);
return $node;
}
/**
* @return ClassConst[]
*/
private function resolveClassConstByPosition(Node\Stmt\Class_ $class): array
{
$classConstConstsByValue = [];
foreach ($class->stmts as $key => $classStmt) {
if (! $classStmt instanceof ClassConst) {
continue;
}
if (count($classStmt->consts) !== 1) {
continue;
}
$classConstConst = $classStmt->consts[0];
if (! $classConstConst->value instanceof LNumber) {
continue;
}
$classConstConstsByValue[$key] = $classStmt;
}
return $classConstConstsByValue;
}
private function resolveClastConstConstByUniqueValue(array $numericClassConstsByKey): array
{
$classConstConstsByValue = [];
foreach ($numericClassConstsByKey as $position => $numericClassConst) {
$constantValue = $this->getValue($numericClassConst->consts[0]->value);
$classConstConstsByValue[$position] = $constantValue;
}
$arrayCountValue = array_count_values($classConstConstsByValue);
// work only with unique constants
foreach ($classConstConstsByValue as $position => $constantValue) {
if ($arrayCountValue[$constantValue] > 1) {
unset($classConstConstsByValue[$position]);
continue;
}
}
return $classConstConstsByValue;
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Rector\Order\Tests\Rector\Class_\OrderClassConstantsByIntegerValueRector\Fixture;
class SomeClass
{
const MODE_ON = 100;
const MODE_OFF = 250;
const MODE_MAYBE = 125;
}
?>
-----
<?php
namespace Rector\Order\Tests\Rector\Class_\OrderClassConstantsByIntegerValueRector\Fixture;
class SomeClass
{
const MODE_ON = 100;
const MODE_MAYBE = 125;
const MODE_OFF = 250;
}
?>

View File

@ -0,0 +1,27 @@
<?php
namespace Rector\Order\Tests\Rector\Class_\OrderClassConstantsByIntegerValueRector\Fixture;
class FromZero
{
const MODE_ON = 100;
const MODE_OFF = 0;
const MODE_MAYBE = 125;
}
?>
-----
<?php
namespace Rector\Order\Tests\Rector\Class_\OrderClassConstantsByIntegerValueRector\Fixture;
class FromZero
{
const MODE_OFF = 0;
const MODE_ON = 100;
const MODE_MAYBE = 125;
}
?>

View File

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace Rector\Order\Tests\Rector\Class_\OrderClassConstantsByIntegerValueRector;
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\Order\Rector\Class_\OrderClassConstantsByIntegerValueRector;
final class OrderClassConstantsByIntegerValueRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(string $file): void
{
$this->doTestFile($file);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
protected function getRectorClass(): string
{
return OrderClassConstantsByIntegerValueRector::class;
}
}