From 9c116e41667aa2052e15bb6631ab5de4ee12b7be Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 14 Feb 2026 12:34:42 +0700 Subject: [PATCH] [DowngradePhp80] Fix on Arg and return ternary on DowngradeThrowExprRector --- .../Fixture/on_arg.php.inc | 31 +++++++++++ .../Fixture/return_ternary.php.inc | 30 +++++++++++ .../Expression/DowngradeThrowExprRector.php | 53 ++++++++++++++++--- src/NodeFactory/NamedVariableFactory.php | 3 +- 4 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 rules-tests/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector/Fixture/on_arg.php.inc create mode 100644 rules-tests/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector/Fixture/return_ternary.php.inc diff --git a/rules-tests/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector/Fixture/on_arg.php.inc b/rules-tests/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector/Fixture/on_arg.php.inc new file mode 100644 index 00000000..d2aeca91 --- /dev/null +++ b/rules-tests/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector/Fixture/on_arg.php.inc @@ -0,0 +1,31 @@ +setImageResource(imagecreatefromstring(ob_get_clean()) ?: throw new Nette\ShouldNotHappenException()); + } +} + +?> +----- +setImageResource($arg); + } +} + +?> diff --git a/rules-tests/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector/Fixture/return_ternary.php.inc b/rules-tests/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector/Fixture/return_ternary.php.inc new file mode 100644 index 00000000..c561f848 --- /dev/null +++ b/rules-tests/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector/Fixture/return_ternary.php.inc @@ -0,0 +1,30 @@ + +----- + diff --git a/rules/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector.php b/rules/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector.php index 7719a15b..3b48b98e 100644 --- a/rules/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector.php +++ b/rules/DowngradePhp80/Rector/Expression/DowngradeThrowExprRector.php @@ -12,6 +12,7 @@ use PhpParser\Node\Expr\BinaryOp\Coalesce; use PhpParser\Node\Expr\BinaryOp\Identical; use PhpParser\Node\Expr\BooleanNot; +use PhpParser\Node\Expr\CallLike; use PhpParser\Node\Expr\Closure; use PhpParser\Node\Expr\ConstFetch; use PhpParser\Node\Expr\Isset_; @@ -25,6 +26,7 @@ use PhpParser\Node\Stmt\If_; use PhpParser\Node\Stmt\Return_; use Rector\NodeAnalyzer\CoalesceAnalyzer; +use Rector\NodeFactory\NamedVariableFactory; use Rector\NodeManipulator\BinaryOpManipulator; use Rector\Php72\NodeFactory\AnonymousFunctionFactory; use Rector\PhpParser\Node\BetterNodeFinder; @@ -43,7 +45,8 @@ public function __construct( private readonly CoalesceAnalyzer $coalesceAnalyzer, private readonly BinaryOpManipulator $binaryOpManipulator, private readonly BetterNodeFinder $betterNodeFinder, - private readonly AnonymousFunctionFactory $anonymousFunctionFactory + private readonly AnonymousFunctionFactory $anonymousFunctionFactory, + private readonly NamedVariableFactory $namedVariableFactory ) { } @@ -100,6 +103,22 @@ public function refactor(Node $node): Node|array|null } } + if ($node->expr instanceof CallLike && ! $node->expr->isFirstClassCallable()) { + $args = $node->expr->getArgs(); + foreach ($args as $arg) { + if ($arg->value instanceof Ternary && $arg->value->else instanceof Throw_) { + $refactorTernary = $this->refactorTernary($arg->value, null, true); + if (is_array($refactorTernary) && $refactorTernary[0] instanceof Expression && $refactorTernary[0]->expr instanceof Assign) { + $arg->value = $refactorTernary[0]->expr->var; + + return [...$refactorTernary, $node]; + } + } + } + + return null; + } + if ($node->expr instanceof Coalesce) { return $this->refactorCoalesce($node->expr, null); } @@ -153,18 +172,36 @@ private function refactorAssign(Assign $assign): If_ | Expression | null | array /** * @return If_|Stmt[]|null */ - private function refactorTernary(Ternary $ternary, ?Assign $assign): If_|null|array + private function refactorTernary(Ternary $ternary, ?Assign $assign, bool $onArg = false): If_|null|array { - if (! $ternary->else instanceof Throw_) { + if ($ternary->if instanceof Throw_) { + $else = $ternary->if; + } elseif ($ternary->else instanceof Throw_) { + $else = $ternary->else; + } else { return null; } - $inversedTernaryExpr = $this->binaryOpManipulator->inverseNode($ternary->cond); + $inversedTernaryExpr = $ternary->if instanceof Throw_ + ? $ternary->cond + : $this->binaryOpManipulator->inverseNode($ternary->cond); $if = new If_($inversedTernaryExpr, [ - 'stmts' => [new Expression($ternary->else)], + 'stmts' => [new Expression($else)], ]); + if (! $assign instanceof Assign && $onArg) { + $tempVar = $this->namedVariableFactory->createVariable('arg', $ternary); + $assign = new Assign($tempVar, $ternary->if ?? $ternary->cond); + + $inversedTernaryExpr = $this->binaryOpManipulator->inverseNode($tempVar); + $if = new If_($inversedTernaryExpr, [ + 'stmts' => [new Expression($else)], + ]); + + return [new Expression($assign), $if]; + } + if (! $assign instanceof Assign) { return $if; } @@ -267,7 +304,11 @@ private function refactorReturn(Return_ $return): ?array return null; } - return [$if, new Return_($return->expr->cond)]; + $returnExpr = $return->expr->if instanceof Throw_ + ? $return->expr->else + : ($return->expr->if ?? $return->expr->cond); + + return [$if, new Return_($returnExpr)]; } return null; diff --git a/src/NodeFactory/NamedVariableFactory.php b/src/NodeFactory/NamedVariableFactory.php index 5b021c80..0bdad2cd 100644 --- a/src/NodeFactory/NamedVariableFactory.php +++ b/src/NodeFactory/NamedVariableFactory.php @@ -4,6 +4,7 @@ namespace Rector\NodeFactory; +use PhpParser\Node\Expr\Ternary; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Stmt\Expression; use Rector\Naming\Naming\VariableNaming; @@ -16,7 +17,7 @@ public function __construct( ) { } - public function createVariable(string $variableName, Expression $expression): Variable + public function createVariable(string $variableName, Expression|Ternary $expression): Variable { $scope = $expression->getAttribute(AttributeKey::SCOPE);