mirror of
https://github.com/rectorphp/rector.git
synced 2024-05-28 23:10:51 +00:00
[CodeQuality] Add SplitListScalarAssignToSeparateLineRector
This commit is contained in:
parent
75593950ab
commit
00797bbce3
|
@ -54,3 +54,4 @@ services:
|
|||
Rector\CodeQuality\Rector\Foreach_\ForeachItemsAssignToEmptyArrayToAssignRector: null
|
||||
Rector\CodeQuality\Rector\BinaryOp\InlineIfToExplicitIfRector: null
|
||||
Rector\CodeQuality\Rector\FuncCall\ArrayKeysAndInArrayToArrayKeyExistsRector: null
|
||||
Rector\CodeQuality\Rector\Assign\SplitListAssignToSeparateLineRector: null
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# All 497 Rectors Overview
|
||||
# All 498 Rectors Overview
|
||||
|
||||
- [Projects](#projects)
|
||||
- [General](#general)
|
||||
|
@ -1726,6 +1726,27 @@ Changes in_array() with single element to ===
|
|||
|
||||
<br>
|
||||
|
||||
### `SplitListAssignToSeparateLineRector`
|
||||
|
||||
- class: [`Rector\CodeQuality\Rector\Assign\SplitListAssignToSeparateLineRector`](/../master/rules/code-quality/src/Rector/Assign/SplitListAssignToSeparateLineRector.php)
|
||||
- [test fixtures](/../master/rules/code-quality/tests/Rector/Assign/SplitListAssignToSeparateLineRector/Fixture)
|
||||
|
||||
Splits [$a, $b] = [5, 10] scalar assign to standalone lines
|
||||
|
||||
```diff
|
||||
final class SomeClass
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
- [$a, $b] = [1, 2];
|
||||
+ $a = 1;
|
||||
+ $b = 2;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### `StrlenZeroToIdenticalEmptyStringRector`
|
||||
|
||||
- class: [`Rector\CodeQuality\Rector\FuncCall\StrlenZeroToIdenticalEmptyStringRector`](/../master/rules/code-quality/src/Rector/FuncCall/StrlenZeroToIdenticalEmptyStringRector.php)
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\CodeQuality\Rector\Assign;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\List_;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\RectorDefinition\CodeSample;
|
||||
use Rector\Core\RectorDefinition\RectorDefinition;
|
||||
|
||||
/**
|
||||
* @see https://mobile.twitter.com/ivanhoe011/status/1246376872931401728
|
||||
*
|
||||
* @see \Rector\CodeQuality\Tests\Rector\Assign\SplitListAssignToSeparateLineRector\SplitListAssignToSeparateLineRectorTest
|
||||
*/
|
||||
final class SplitListAssignToSeparateLineRector extends AbstractRector
|
||||
{
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition('Splits [$a, $b] = [5, 10] scalar assign to standalone lines', [
|
||||
new CodeSample(
|
||||
<<<'PHP'
|
||||
final class SomeClass
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
[$a, $b] = [1, 2];
|
||||
}
|
||||
}
|
||||
PHP
|
||||
,
|
||||
<<<'PHP'
|
||||
final class SomeClass
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$a = 1;
|
||||
$b = 2;
|
||||
}
|
||||
}
|
||||
PHP
|
||||
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Assign::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Assign $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if ($this->shouldSkip($node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var Array_|List_ $leftArray */
|
||||
$leftArray = $node->var;
|
||||
|
||||
/** @var Array_ $rightArray */
|
||||
$rightArray = $node->expr;
|
||||
|
||||
$standaloneAssigns = $this->createStandaloneAssigns($leftArray, $rightArray);
|
||||
foreach ($standaloneAssigns as $standaloneAssign) {
|
||||
$this->addNodeAfterNode($standaloneAssign, $node);
|
||||
}
|
||||
|
||||
$this->removeNode($node);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
private function shouldSkip($node): bool
|
||||
{
|
||||
if (! $node->var instanceof Array_ && ! $node->var instanceof List_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! $node->expr instanceof Array_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (count($node->var->items) !== count($node->expr->items)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// is value swap
|
||||
return $this->isValueSwap($node->var, $node->expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Array_|List_ $node
|
||||
* @return Assign[]
|
||||
*/
|
||||
private function createStandaloneAssigns(Node $node, Array_ $rightArray): array
|
||||
{
|
||||
$standaloneAssigns = [];
|
||||
foreach ($node->items as $key => $leftArrayItem) {
|
||||
$rightArrayItem = $rightArray->items[$key];
|
||||
|
||||
$standaloneAssigns[] = new Assign($leftArrayItem->value, $rightArrayItem);
|
||||
}
|
||||
|
||||
return $standaloneAssigns;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Array_|List_ $node
|
||||
*/
|
||||
private function getArrayItemsHash(Node $node): string
|
||||
{
|
||||
$arrayItemsHashes = [];
|
||||
foreach ($node->items as $arrayItem) {
|
||||
$arrayItemsHashes[] = $this->printWithoutComments($arrayItem);
|
||||
}
|
||||
|
||||
sort($arrayItemsHashes);
|
||||
|
||||
$arrayItemsHash = implode('', $arrayItemsHashes);
|
||||
|
||||
return sha1($arrayItemsHash);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Array_|List_ $firstArray
|
||||
* @param Array_|List_ $secondArray
|
||||
*/
|
||||
private function isValueSwap($firstArray, $secondArray): bool
|
||||
{
|
||||
$firstArrayItemsHash = $this->getArrayItemsHash($firstArray);
|
||||
$secondArrayItemsHash = $this->getArrayItemsHash($secondArray);
|
||||
|
||||
return $firstArrayItemsHash === $secondArrayItemsHash;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\CodeQuality\Tests\Rector\Assign\SplitListAssignToSeparateLineRector\Fixture;
|
||||
|
||||
final class SomeClass
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
[$a, $b] = [1, 2];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\CodeQuality\Tests\Rector\Assign\SplitListAssignToSeparateLineRector\Fixture;
|
||||
|
||||
final class SomeClass
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$a = 1;
|
||||
$b = 2;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\CodeQuality\Tests\Rector\Assign\SplitListAssignToSeparateLineRector\Fixture;
|
||||
|
||||
final class NotScalar
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$itemCount = 100;
|
||||
[$a, $b] = [1, $itemCount];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\CodeQuality\Tests\Rector\Assign\SplitListAssignToSeparateLineRector\Fixture;
|
||||
|
||||
final class NotScalar
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$itemCount = 100;
|
||||
$a = 1;
|
||||
$b = $itemCount;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\CodeQuality\Tests\Rector\Assign\SplitListAssignToSeparateLineRector\Fixture;
|
||||
|
||||
final class SkipSplitOfArray
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$moreItems = [1, 2];
|
||||
[$a, $b] = $moreItems;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\CodeQuality\Tests\Rector\Assign\SplitListAssignToSeparateLineRector\Fixture;
|
||||
|
||||
final class SkipSwap
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$a = 1;
|
||||
$b = 5;
|
||||
[$a, $b] = [$b, $a];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\CodeQuality\Tests\Rector\Assign\SplitListAssignToSeparateLineRector\Fixture;
|
||||
|
||||
final class WithListFunction
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
list($a, $b) = [1, 2];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\CodeQuality\Tests\Rector\Assign\SplitListAssignToSeparateLineRector\Fixture;
|
||||
|
||||
final class WithListFunction
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$a = 1;
|
||||
$b = 2;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\CodeQuality\Tests\Rector\Assign\SplitListAssignToSeparateLineRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\CodeQuality\Rector\Assign\SplitListAssignToSeparateLineRector;
|
||||
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
|
||||
final class SplitListAssignToSeparateLineRectorTest 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 SplitListAssignToSeparateLineRector::class;
|
||||
}
|
||||
}
|
|
@ -53,9 +53,11 @@ final class TernaryToNullCoalescingRector extends AbstractRector
|
|||
}
|
||||
|
||||
if ($node->cond instanceof Identical) {
|
||||
[$checkedNode, $fallbackNode] = [$node->else, $node->if];
|
||||
$checkedNode = $node->else;
|
||||
$fallbackNode = $node->if;
|
||||
} elseif ($node->cond instanceof NotIdentical) {
|
||||
[$checkedNode, $fallbackNode] = [$node->if, $node->else];
|
||||
$checkedNode = $node->if;
|
||||
$fallbackNode = $node->else;
|
||||
} else {
|
||||
// not a match
|
||||
return null;
|
||||
|
|
Loading…
Reference in New Issue
Block a user