![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/cartforge.co/vendor/rector/rector/rules/Php70/Rector/If_/ |
<?php declare (strict_types=1); namespace Rector\Php70\Rector\If_; use PhpParser\Node; use PhpParser\Node\Expr; use PhpParser\Node\Expr\BinaryOp\Equal; use PhpParser\Node\Expr\BinaryOp\Identical; use PhpParser\Node\Expr\BinaryOp\Spaceship; use PhpParser\Node\Expr\Ternary; use PhpParser\Node\Stmt\Else_; use PhpParser\Node\Stmt\If_; use PhpParser\Node\Stmt\Return_; use Rector\Contract\PhpParser\Node\StmtsAwareInterface; use Rector\Php70\Enum\BattleshipCompareOrder; use Rector\Php70\NodeAnalyzer\BattleshipTernaryAnalyzer; use Rector\Php70\ValueObject\ComparedExprs; use Rector\PhpParser\Node\Value\ValueResolver; use Rector\Rector\AbstractRector; use Rector\ValueObject\PhpVersionFeature; use Rector\VersionBonding\Contract\MinPhpVersionInterface; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** * @see \Rector\Tests\Php70\Rector\If_\IfToSpaceshipRector\IfToSpaceshipRectorTest */ final class IfToSpaceshipRector extends AbstractRector implements MinPhpVersionInterface { /** * @readonly * @var \Rector\Php70\NodeAnalyzer\BattleshipTernaryAnalyzer */ private $battleshipTernaryAnalyzer; /** * @readonly * @var \Rector\PhpParser\Node\Value\ValueResolver */ private $valueResolver; public function __construct(BattleshipTernaryAnalyzer $battleshipTernaryAnalyzer, ValueResolver $valueResolver) { $this->battleshipTernaryAnalyzer = $battleshipTernaryAnalyzer; $this->valueResolver = $valueResolver; } public function getRuleDefinition() : RuleDefinition { return new RuleDefinition('Changes if/else to spaceship <=> where useful', [new CodeSample(<<<'CODE_SAMPLE' usort($languages, function ($first, $second) { if ($first[0] === $second[0]) { return 0; } return ($first[0] < $second[0]) ? 1 : -1; }); CODE_SAMPLE , <<<'CODE_SAMPLE' usort($languages, function ($first, $second) { return $second[0] <=> $first[0]; }); CODE_SAMPLE )]); } /** * @return array<class-string<Node>> */ public function getNodeTypes() : array { return [StmtsAwareInterface::class, If_::class]; } /** * @param StmtsAwareInterface|If_ $node */ public function refactor(Node $node) : ?Node { if ($node instanceof If_) { return $this->refactorIf($node); } if ($node->stmts === null) { return null; } foreach ($node->stmts as $key => $stmt) { if (!$stmt instanceof Return_) { continue; } if (!$stmt->expr instanceof Ternary) { continue; } // preceeded by if $prevStmt = $node->stmts[$key - 1] ?? null; if (!$prevStmt instanceof If_) { continue; } $comparedExprs = $this->matchExprComparedExprsReturnZero($prevStmt); if (!$comparedExprs instanceof ComparedExprs) { continue; } $battleshipCompareOrder = $this->battleshipTernaryAnalyzer->isGreaterLowerCompareReturnOneAndMinusOne($stmt->expr, $comparedExprs); $returnSpaceship = $this->createReturnSpaceship($battleshipCompareOrder, $comparedExprs); if (!$returnSpaceship instanceof Return_) { continue; } unset($node->stmts[$key - 1]); $node->stmts[$key] = $returnSpaceship; return $node; } return null; } public function provideMinPhpVersion() : int { return PhpVersionFeature::SPACESHIP; } private function refactorIf(If_ $if) : ?Return_ { if ($if->elseifs !== []) { return null; } if (!$if->else instanceof Else_) { return null; } $comparedExprs = $this->matchExprComparedExprsReturnZero($if); if (!$comparedExprs instanceof ComparedExprs) { return null; } $ternary = $this->matchElseOnlyStmtTernary($if->else); if (!$ternary instanceof Ternary) { return null; } $battleshipCompareOrder = $this->battleshipTernaryAnalyzer->isGreaterLowerCompareReturnOneAndMinusOne($ternary, $comparedExprs); return $this->createReturnSpaceship($battleshipCompareOrder, $comparedExprs); } /** * We look for: * * if ($firstValue === $secondValue) { * return 0; * } */ private function matchExprComparedExprsReturnZero(If_ $if) : ?ComparedExprs { if (!$if->cond instanceof Equal && !$if->cond instanceof Identical) { return null; } $binaryOp = $if->cond; if (\count($if->stmts) !== 1) { return null; } $onlyStmt = $if->stmts[0]; if (!$onlyStmt instanceof Return_) { return null; } if (!$onlyStmt->expr instanceof Expr) { return null; } if (!$this->valueResolver->isValue($onlyStmt->expr, 0)) { return null; } return new ComparedExprs($binaryOp->left, $binaryOp->right); } /** * @param BattleshipCompareOrder::*|null $battleshipCompareOrder */ private function createReturnSpaceship(?string $battleshipCompareOrder, ComparedExprs $comparedExprs) : ?Return_ { if ($battleshipCompareOrder === null) { return null; } if ($battleshipCompareOrder === BattleshipCompareOrder::DESC) { $spaceship = new Spaceship($comparedExprs->getFirstExpr(), $comparedExprs->getSecondExpr()); } else { $spaceship = new Spaceship($comparedExprs->getSecondExpr(), $comparedExprs->getFirstExpr()); } return new Return_($spaceship); } private function matchElseOnlyStmtTernary(Else_ $else) : ?\PhpParser\Node\Expr\Ternary { if (\count($else->stmts) !== 1) { return null; } $onlyElseStmt = $else->stmts[0]; if (!$onlyElseStmt instanceof Return_) { return null; } if (!$onlyElseStmt->expr instanceof Ternary) { return null; } return $onlyElseStmt->expr; } }