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); } }