Skip to content

Commit

Permalink
[DeadCode] Handle repetitive jump equal case stmts on RemoveDuplicate…
Browse files Browse the repository at this point in the history
…dCaseInSwitchRector (#5239)

* [DeadCode] Handle repetitive jump equal case stmts on RemoveDuplicatedCaseInSwitchRector

* Fixed 🎉

* fix missing-in-set config

* fix @return

* clean up
  • Loading branch information
samsonasik committed Nov 10, 2023
1 parent eac58be commit 2f74b02
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 39 deletions.
@@ -0,0 +1,59 @@
<?php

namespace Rector\Tests\DeadCode\Rector\Switch_\RemoveDuplicatedCaseInSwitchRector\Fixture;

class DiffrentIndirectDuplicated3
{
public function run($name)
{
switch ($name) {
case 'a':
return 'A';
case 'b':
return 'B';
case 'c';
return 'C';
case 'd':
return 'A';
case 'e':
return 'B';
case 'f':
return 'C';
case 'g':
return 'A';
case 'h':
return 'B';
case 'i':
return 'C';
}
}
}

?>
-----
<?php

namespace Rector\Tests\DeadCode\Rector\Switch_\RemoveDuplicatedCaseInSwitchRector\Fixture;

class DiffrentIndirectDuplicated3
{
public function run($name)
{
switch ($name) {
case 'a':
case 'd':
case 'g':
return 'A';
case 'b':
case 'e':
case 'h':
return 'B';
case 'c':
case 'f':
case 'i':
return 'C';
}
}
}

?>
Expand Up @@ -86,72 +86,48 @@ public function refactor(Node $node): ?Node

$this->hasChanged = false;

$insertByKeys = $this->resolveInsertedByKeys($node);
$this->insertCaseByKeys($node, $insertByKeys);

$this->removeDuplicatedCases($node);
if (! $this->hasChanged) {
return null;
}

return $node;
}

/**
* @return array<int, array<int, Case_>>
*/
private function resolveInsertedByKeys(Switch_ $switch): array
private function removeDuplicatedCases(Switch_ $switch): void
{
$totalKeys = count($switch->cases);
$insertByKeys = [];
$appendKey = 0;
/** @var Case_|null $previousCase */
$previousCase = null;

foreach ($switch->cases as $key => $case) {
if ($previousCase instanceof Case_ && $this->areSwitchStmtsEqualsAndWithBreak($case, $previousCase)) {
$previousCase->stmts = [];
$this->hasChanged = true;
}

$previousCase = $case;

for ($jumpToKey = $key + 2; $jumpToKey < $totalKeys; ++$jumpToKey) {
foreach (array_keys($switch->cases) as $key) {
$nextCases = [];
for ($jumpToKey = $key + 1; $jumpToKey < $totalKeys; ++$jumpToKey) {
if (! isset($switch->cases[$jumpToKey])) {
continue;
}

if (! $this->areSwitchStmtsEqualsAndWithBreak($case, $switch->cases[$jumpToKey])) {
if (! $this->areSwitchStmtsEqualsAndWithBreak($switch->cases[$key], $switch->cases[$jumpToKey])) {
continue;
}

$nextCase = $switch->cases[$jumpToKey];

unset($switch->cases[$jumpToKey]);

$insertByKeys[$key + $appendKey][] = $nextCase;
$nextCases[] = $nextCase;

$this->hasChanged = true;
}

$appendKey = isset($insertByKeys[$key]) ? count($insertByKeys[$key]) : 0;
}

return $insertByKeys;
}

/**
* @param array<int, array<int, Case_>> $insertByKeys
*/
private function insertCaseByKeys(Switch_ $switch, array $insertByKeys): void
{
foreach ($insertByKeys as $key => $insertByKey) {
$nextKey = $key + 1;
if ($nextCases === []) {
continue;
}

array_splice($switch->cases, $nextKey, 0, $insertByKey);
array_splice($switch->cases, $key + 1, 0, $nextCases);

$switch->cases[$key]->stmts = [];
for ($jumpToKey = $key; $jumpToKey < $key + count($nextCases); ++$jumpToKey) {
$switch->cases[$jumpToKey]->stmts = [];
}

$this->hasChanged = true;
$key += count($nextCases);
}
}

Expand Down
4 changes: 4 additions & 0 deletions utils/Command/MissingInSetCommand.php
Expand Up @@ -8,6 +8,7 @@
use Rector\CodingStyle\Rector\Switch_\BinarySwitchToIfElseRector;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Php71\Rector\FuncCall\CountOnNullRector;
use Rector\PHPUnit\CodeQuality\Rector\MethodCall\RemoveSetMethodsMethodCallRector;
use Rector\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenCollectorRector;
use Rector\TypeDeclaration\Rector\BooleanAnd\BinaryOpNullableToInstanceofRector;
use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromStrictConstructorReadonlyClassRector;
Expand Down Expand Up @@ -38,6 +39,9 @@ final class MissingInSetCommand extends Command
TypedPropertyFromStrictConstructorReadonlyClassRector::class,
BinarySwitchToIfElseRector::class,
CountOnNullRector::class,

// namespace to be moved from CodeQuality to PHPUnit100
RemoveSetMethodsMethodCallRector::class,
];

public function __construct(
Expand Down

0 comments on commit 2f74b02

Please sign in to comment.