assignAndBinaryMap = $assignAndBinaryMap;
$this->callAnalyzer = $callAnalyzer;
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Changes Single return of || to early returns', [new CodeSample(<<<'CODE_SAMPLE'
class SomeClass
{
public function accept()
{
return $this->something() || $this->somethingElse();
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class SomeClass
{
public function accept()
{
if ($this->something()) {
return true;
}
return (bool) $this->somethingElse();
}
}
CODE_SAMPLE
)]);
}
/**
* @return array>
*/
public function getNodeTypes() : array
{
return [StmtsAwareInterface::class];
}
/**
* @param StmtsAwareInterface $node
*/
public function refactor(Node $node) : ?Node
{
if ($node->stmts === null) {
return null;
}
$hasChanged = \false;
foreach ($node->stmts as $key => $stmt) {
if (!$stmt instanceof Return_) {
continue;
}
if (!$stmt->expr instanceof BooleanOr) {
continue;
}
/** @var BooleanOr $booleanOr */
$booleanOr = $stmt->expr;
$left = $booleanOr->left;
$ifs = $this->createMultipleIfs($left, $stmt, []);
// ensure ifs not removed by other rules
if ($ifs === []) {
continue;
}
if (!$this->callAnalyzer->doesIfHasObjectCall($ifs)) {
continue;
}
$this->mirrorComments($ifs[0], $stmt);
$lastReturnExpr = $this->assignAndBinaryMap->getTruthyExpr($booleanOr->right);
$ifsWithLastIf = \array_merge($ifs, [new Return_($lastReturnExpr)]);
\array_splice($node->stmts, $key, 1, $ifsWithLastIf);
$hasChanged = \true;
}
if ($hasChanged) {
return $node;
}
return null;
}
/**
* @param If_[] $ifs
* @return If_[]
*/
private function createMultipleIfs(Expr $expr, Return_ $return, array $ifs) : array
{
while ($expr instanceof BooleanOr) {
$ifs = \array_merge($ifs, $this->collectLeftBooleanOrToIfs($expr, $return, $ifs));
$ifs[] = new If_($expr->right, ['stmts' => [new Return_($this->nodeFactory->createTrue())]]);
$expr = $expr->right;
if ($expr instanceof BooleanAnd) {
return [];
}
if (!$expr instanceof BooleanOr) {
continue;
}
return [];
}
$lastIf = new If_($expr, ['stmts' => [new Return_($this->nodeFactory->createTrue())]]);
// if empty, fallback to last if
if ($ifs === []) {
return [$lastIf];
}
return $ifs;
}
/**
* @param If_[] $ifs
* @return If_[]
*/
private function collectLeftBooleanOrToIfs(BooleanOr $booleanOr, Return_ $return, array $ifs) : array
{
$left = $booleanOr->left;
if (!$left instanceof BooleanOr) {
$returnTrueIf = new If_($left, ['stmts' => [new Return_($this->nodeFactory->createTrue())]]);
return [$returnTrueIf];
}
return $this->createMultipleIfs($left, $return, $ifs);
}
}