diff --git a/rules/DowngradePhp72/NodeManipulator/JsonConstCleaner.php b/rules/DowngradePhp72/NodeManipulator/JsonConstCleaner.php index 7fadc85e..0bbed1f9 100644 --- a/rules/DowngradePhp72/NodeManipulator/JsonConstCleaner.php +++ b/rules/DowngradePhp72/NodeManipulator/JsonConstCleaner.php @@ -4,14 +4,12 @@ namespace Rector\DowngradePhp72\NodeManipulator; -use PhpParser\Node; use PhpParser\Node\Expr; use PhpParser\Node\Expr\BinaryOp\BitwiseOr; use PhpParser\Node\Expr\ConstFetch; use PhpParser\Node\Scalar\Int_; use Rector\Enum\JsonConstant; use Rector\NodeNameResolver\NodeNameResolver; -use Rector\NodeTypeResolver\Node\AttributeKey; final readonly class JsonConstCleaner { @@ -47,35 +45,56 @@ private function cleanByConstFetch(ConstFetch $constFetch, array $constants): ?I /** * @param array $constants */ - private function cleanByBitwiseOr(BitwiseOr $bitwiseOr, array $constants): null|Expr|Int_ + private function cleanByBitwiseOr(BitwiseOr $bitwiseOr, array $constants): ?Expr { - $isLeftTransformed = $this->isTransformed($bitwiseOr->left, $constants); - $isRightTransformed = $this->isTransformed($bitwiseOr->right, $constants); + $keptOperands = []; + $hasChanged = false; - if (! $isLeftTransformed && ! $isRightTransformed) { + foreach ($this->flattenOperands($bitwiseOr) as $operand) { + if ($operand instanceof ConstFetch && $this->nodeNameResolver->isNames($operand, $constants)) { + $hasChanged = true; + continue; + } + + $keptOperands[] = $operand; + } + + if (! $hasChanged) { return null; } - if (! $isLeftTransformed) { - return $bitwiseOr->left; + if ($keptOperands === []) { + return new Int_(0); } - if (! $isRightTransformed) { - return $bitwiseOr->right; + $result = array_shift($keptOperands); + foreach ($keptOperands as $keptOperand) { + $result = new BitwiseOr($result, $keptOperand); } - return new Int_(0); + return $result; } /** - * @param string[] $constants + * Flatten a left-associative bitwise-or chain into its operands. Structural, so dropping a + * target constant does not depend on the ORIGINAL_NODE attribute, which is not reliable on + * re-decorated nodes. + * + * @return Expr[] */ - private function isTransformed(Expr $expr, array $constants): bool + private function flattenOperands(BitwiseOr $bitwiseOr): array { - if ($expr instanceof ConstFetch && $this->nodeNameResolver->isNames($expr, $constants)) { - return true; + $operands = []; + + foreach ([$bitwiseOr->left, $bitwiseOr->right] as $operand) { + if ($operand instanceof BitwiseOr) { + $operands = [...$operands, ...$this->flattenOperands($operand)]; + continue; + } + + $operands[] = $operand; } - return ! $expr->getAttribute(AttributeKey::ORIGINAL_NODE) instanceof Node; + return $operands; } }