From f330cce82141a7edd5a4b6e9464de2d2530840a4 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Wed, 9 Sep 2026 09:45:41 +0200 Subject: [PATCH 1/2] [Php70] Deprecate ListSwapArrayOrderRector, can turn valid code into broken code Claude-Session: https://claude.ai/code/session_015VSEwd6ef1TqwYumj3R1jn --- config/set/php-version-based.php | 2 - config/set/php70.php | 2 - .../Fixture/fixture.php.inc | 27 -------- .../Fixture/missing_list_item.php.inc | 27 -------- .../Fixture/skip.php.inc | 16 ----- .../skip_already_array_reverse.php.inc | 11 ---- .../Fixture/skip_array_dim.php.inc | 11 ---- .../ListSwapArrayOrderRectorTest.php | 28 --------- .../config/configured_rule.php | 9 --- .../Assign/ListSwapArrayOrderRector.php | 61 +++---------------- 10 files changed, 8 insertions(+), 186 deletions(-) delete mode 100644 rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/Fixture/fixture.php.inc delete mode 100644 rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/Fixture/missing_list_item.php.inc delete mode 100644 rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/Fixture/skip.php.inc delete mode 100644 rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/Fixture/skip_already_array_reverse.php.inc delete mode 100644 rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/Fixture/skip_array_dim.php.inc delete mode 100644 rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/ListSwapArrayOrderRectorTest.php delete mode 100644 rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/config/configured_rule.php diff --git a/config/set/php-version-based.php b/config/set/php-version-based.php index 37cf0f579ed..79ea60b7562 100644 --- a/config/set/php-version-based.php +++ b/config/set/php-version-based.php @@ -34,7 +34,6 @@ use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector; use Rector\Php56\Rector\FuncCall\PowToExpRector; use Rector\Php70\Rector\Assign\ListSplitStringRector; -use Rector\Php70\Rector\Assign\ListSwapArrayOrderRector; use Rector\Php70\Rector\Break_\BreakNotInLoopOrSwitchToReturnRector; use Rector\Php70\Rector\ClassMethod\Php4ConstructorRector; use Rector\Php70\Rector\FuncCall\CallUserMethodRector; @@ -195,7 +194,6 @@ MultiDirnameRector::class, ListSplitStringRector::class, EmptyListRector::class, - ListSwapArrayOrderRector::class, CallUserMethodRector::class, EregToPregMatchRector::class, ReduceMultipleDefaultSwitchRector::class, diff --git a/config/set/php70.php b/config/set/php70.php index 6288dbe56cd..a7cc1ddeae0 100644 --- a/config/set/php70.php +++ b/config/set/php70.php @@ -4,7 +4,6 @@ use Rector\Config\RectorConfig; use Rector\Php70\Rector\Assign\ListSplitStringRector; -use Rector\Php70\Rector\Assign\ListSwapArrayOrderRector; use Rector\Php70\Rector\Break_\BreakNotInLoopOrSwitchToReturnRector; use Rector\Php70\Rector\ClassMethod\Php4ConstructorRector; use Rector\Php70\Rector\FuncCall\CallUserMethodRector; @@ -31,7 +30,6 @@ MultiDirnameRector::class, ListSplitStringRector::class, EmptyListRector::class, - ListSwapArrayOrderRector::class, CallUserMethodRector::class, EregToPregMatchRector::class, ReduceMultipleDefaultSwitchRector::class, diff --git a/rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/Fixture/fixture.php.inc b/rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/Fixture/fixture.php.inc deleted file mode 100644 index b7786115875..00000000000 --- a/rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/Fixture/fixture.php.inc +++ /dev/null @@ -1,27 +0,0 @@ - ------ - diff --git a/rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/Fixture/missing_list_item.php.inc b/rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/Fixture/missing_list_item.php.inc deleted file mode 100644 index d4b1366efb2..00000000000 --- a/rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/Fixture/missing_list_item.php.inc +++ /dev/null @@ -1,27 +0,0 @@ - ------ - diff --git a/rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/Fixture/skip.php.inc b/rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/Fixture/skip.php.inc deleted file mode 100644 index 4219a5f108c..00000000000 --- a/rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/Fixture/skip.php.inc +++ /dev/null @@ -1,16 +0,0 @@ -doTestFile($filePath); - } - - public static function provideData(): Iterator - { - return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); - } - - public function provideConfigFilePath(): string - { - return __DIR__ . '/config/configured_rule.php'; - } -} diff --git a/rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/config/configured_rule.php b/rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/config/configured_rule.php deleted file mode 100644 index 276a2b2869e..00000000000 --- a/rules-tests/Php70/Rector/Assign/ListSwapArrayOrderRector/config/configured_rule.php +++ /dev/null @@ -1,9 +0,0 @@ -withRules([ListSwapArrayOrderRector::class]); diff --git a/rules/Php70/Rector/Assign/ListSwapArrayOrderRector.php b/rules/Php70/Rector/Assign/ListSwapArrayOrderRector.php index 4e58d56d31b..b56413fad78 100644 --- a/rules/Php70/Rector/Assign/ListSwapArrayOrderRector.php +++ b/rules/Php70/Rector/Assign/ListSwapArrayOrderRector.php @@ -5,13 +5,9 @@ namespace Rector\Php70\Rector\Assign; use PhpParser\Node; -use PhpParser\Node\ArrayItem; -use PhpParser\Node\Expr; -use PhpParser\Node\Expr\ArrayDimFetch; use PhpParser\Node\Expr\Assign; -use PhpParser\Node\Expr\FuncCall; -use PhpParser\Node\Expr\List_; -use Rector\PhpParser\Printer\BetterStandardPrinter; +use Rector\Configuration\Deprecation\Contract\DeprecatedInterface; +use Rector\Exception\ShouldNotHappenException; use Rector\Rector\AbstractRector; use Rector\ValueObject\PhpVersionFeature; use Rector\VersionBonding\Contract\MinPhpVersionInterface; @@ -19,15 +15,10 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** - * @see \Rector\Tests\Php70\Rector\Assign\ListSwapArrayOrderRector\ListSwapArrayOrderRectorTest + * @deprecated This rule is deprecated, as it can turn valid code into broken code. The reverse assign order only matters for the same array variable, but the rule cannot reliably tell apart independent assigns, so wrapping with array_reverse() can change correct behavior. */ -final class ListSwapArrayOrderRector extends AbstractRector implements MinPhpVersionInterface +final class ListSwapArrayOrderRector extends AbstractRector implements MinPhpVersionInterface, DeprecatedInterface { - public function __construct( - private readonly BetterStandardPrinter $betterStandardPrinter - ) { - } - public function getRuleDefinition(): RuleDefinition { return new RuleDefinition( @@ -49,50 +40,14 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - if ($this->shouldSkipAssign($node)) { - return null; - } - - /** @var List_ $list */ - $list = $node->var; - - $printedVariables = []; - foreach ($list->items as $arrayItem) { - if (! $arrayItem instanceof ArrayItem) { - continue; - } - - if ($arrayItem->value instanceof ArrayDimFetch && ! $arrayItem->value->dim instanceof Expr) { - $printedVariables[] = $this->betterStandardPrinter->print($arrayItem->value->var); - } else { - return null; - } - } - - // relevant only in 1 variable type - $uniqueVariables = array_unique($printedVariables); - if (count($uniqueVariables) !== 1) { - return null; - } - - // wrap with array_reverse, to reflect reverse assign order in left - $node->expr = $this->nodeFactory->createFuncCall('array_reverse', [$node->expr]); - - return $node; + throw new ShouldNotHappenException(sprintf( + '"%s" rule is deprecated, as it can turn valid code into broken code', + self::class + )); } public function provideMinPhpVersion(): int { return PhpVersionFeature::LIST_SWAP_ORDER; } - - private function shouldSkipAssign(Assign $assign): bool - { - if (! $assign->var instanceof List_) { - return true; - } - - // already converted - return $assign->expr instanceof FuncCall && $this->isName($assign->expr, 'array_reverse'); - } } From 3a69c9674c781631c5146a3684518ab4e65ae000 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Wed, 9 Sep 2026 09:49:35 +0200 Subject: [PATCH 2/2] null in case of array destructing --- src/PhpParser/Printer/BetterStandardPrinter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpParser/Printer/BetterStandardPrinter.php b/src/PhpParser/Printer/BetterStandardPrinter.php index 7747ddb3347..5c729f74990 100644 --- a/src/PhpParser/Printer/BetterStandardPrinter.php +++ b/src/PhpParser/Printer/BetterStandardPrinter.php @@ -565,7 +565,7 @@ private function unwrapFileNode(array $stmts): array } /** - * @param Node[] $nodes + * @param array $nodes Null in case of array destructuring */ private function containsNop(array $nodes): bool {