diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 268fafe4..1a0b76f5 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -25,6 +25,6 @@ jobs: coverage: none ini-values: zend.assertions=1 - - uses: "ramsey/composer-install@v1" + - uses: "ramsey/composer-install@v2" - run: vendor/bin/phpunit diff --git a/rules-tests/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector/Fixture/multiple_coalesce.php.inc b/rules-tests/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector/Fixture/multiple_coalesce.php.inc new file mode 100644 index 00000000..6a7bfdd5 --- /dev/null +++ b/rules-tests/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector/Fixture/multiple_coalesce.php.inc @@ -0,0 +1,30 @@ +getInternalId() ?? $content->getId() ?? throw new \LogicException('content id is required for ackVersion'); + } +} + +?> +----- +getInternalId() ?? $content->getId(); + if ($contentId === null) { + throw new \LogicException('content id is required for ackVersion'); + } + } +} + +?> diff --git a/rules/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector.php b/rules/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector.php index 57aad9e9..7719a15b 100644 --- a/rules/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector.php +++ b/rules/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector.php @@ -180,9 +180,30 @@ private function refactorTernary(Ternary $ternary, ?Assign $assign): If_|null|ar private function refactorCoalesce(Coalesce $coalesce, ?Assign $assign): If_|null|array { if (! $coalesce->right instanceof Throw_) { + $rightCoalesce = $coalesce->right; + $leftCoalesce = $coalesce->left; + + while ($rightCoalesce instanceof Coalesce) { + $leftCoalesce = new Coalesce($leftCoalesce, $rightCoalesce->left); + $rightCoalesce = $rightCoalesce->right; + } + + if ($rightCoalesce instanceof Throw_) { + $coalesce = new Coalesce($leftCoalesce, $rightCoalesce); + return $this->processCoalesce($coalesce, $assign, true); + } + return null; } + return $this->processCoalesce($coalesce, $assign); + } + + /** + * @return If_|Stmt[]|null + */ + private function processCoalesce(Coalesce $coalesce, ?Assign $assign, bool $assignEarly = false): If_|null|array + { if (! $this->coalesceAnalyzer->hasIssetableLeft($coalesce)) { return null; } @@ -198,6 +219,13 @@ private function refactorCoalesce(Coalesce $coalesce, ?Assign $assign): If_|null $assign->expr = $coalesce->left; + if ($assignEarly && $if->cond instanceof Identical) { + $expression = new Expression(new Assign($assign->var, $if->cond->left)); + $if->cond->left = $assign->var; + + return [$expression, $if]; + } + return [$if, new Expression($assign)]; } diff --git a/src/NodeAnalyzer/CoalesceAnalyzer.php b/src/NodeAnalyzer/CoalesceAnalyzer.php index 1e5d1eb2..f29b8982 100644 --- a/src/NodeAnalyzer/CoalesceAnalyzer.php +++ b/src/NodeAnalyzer/CoalesceAnalyzer.php @@ -25,6 +25,10 @@ final class CoalesceAnalyzer public function hasIssetableLeft(Coalesce $coalesce): bool { + if ($coalesce->left instanceof Coalesce) { + return true; + } + $leftClass = $coalesce->left::class; return in_array($leftClass, self::ISSETABLE_EXPR, true); }