diff --git a/build/target-repository/docs/rector_rules_overview.md b/build/target-repository/docs/rector_rules_overview.md index cab0c7384ff..96bde2ae9b0 100644 --- a/build/target-repository/docs/rector_rules_overview.md +++ b/build/target-repository/docs/rector_rules_overview.md @@ -1,4 +1,4 @@ -# 403 Rules Overview +# 404 Rules Overview
@@ -34,7 +34,7 @@ - [Php56](#php56) (2) -- [Php70](#php70) (18) +- [Php70](#php70) (19) - [Php71](#php71) (9) @@ -4675,31 +4675,50 @@ Change typehint from `Exception` to `Throwable`.
-### IfToSpaceshipRector +### IfIssetToCoalescingRector -Changes if/else to spaceship <=> where useful +Change if with isset and return to coalesce -- class: [`Rector\Php70\Rector\If_\IfToSpaceshipRector`](../rules/Php70/Rector/If_/IfToSpaceshipRector.php) +- class: [`Rector\Php70\Rector\StmtsAwareInterface\IfIssetToCoalescingRector`](../rules/Php70/Rector/StmtsAwareInterface/IfIssetToCoalescingRector.php) ```diff class SomeClass { - public function run() + private $items = []; + + public function resolve($key) { - usort($languages, function ($a, $b) { -- if ($a[0] === $b[0]) { -- return 0; -- } +- if (isset($this->items[$key])) { +- return $this->items[$key]; +- } - -- return ($a[0] < $b[0]) ? 1 : -1; -+ return $b[0] <=> $a[0]; - }); +- return 'fallback value'; ++ return $this->items[$key] ?? 'fallback value'; } } ```
+### IfToSpaceshipRector + +Changes if/else to spaceship <=> where useful + +- class: [`Rector\Php70\Rector\If_\IfToSpaceshipRector`](../rules/Php70/Rector/If_/IfToSpaceshipRector.php) + +```diff + usort($languages, function ($first, $second) { +-if ($first[0] === $second[0]) { +- return 0; +-} +- +-return ($first[0] < $second[0]) ? 1 : -1; ++return $second[0] <=> $first[0]; + }); +``` + +
+ ### ListSplitStringRector `list()` cannot split string directly anymore, use `str_split()` diff --git a/config/set/php70.php b/config/set/php70.php index 8ddd4d5fc39..b16c79ef7a4 100644 --- a/config/set/php70.php +++ b/config/set/php70.php @@ -17,6 +17,7 @@ use Rector\Php70\Rector\List_\EmptyListRector; use Rector\Php70\Rector\MethodCall\ThisCallOnStaticMethodToStaticCallRector; use Rector\Php70\Rector\StaticCall\StaticCallOnNonStaticToInstanceCallRector; +use Rector\Php70\Rector\StmtsAwareInterface\IfIssetToCoalescingRector; use Rector\Php70\Rector\Switch_\ReduceMultipleDefaultSwitchRector; use Rector\Php70\Rector\Ternary\TernaryToNullCoalescingRector; use Rector\Php70\Rector\Ternary\TernaryToSpaceshipRector; @@ -43,5 +44,6 @@ ThisCallOnStaticMethodToStaticCallRector::class, BreakNotInLoopOrSwitchToReturnRector::class, RenameMktimeWithoutArgsToTimeRector::class, + IfIssetToCoalescingRector::class, ]); }; diff --git a/rules-tests/Php70/Rector/StmtsAwareInterface/IfIssetToCoalescingRector/Fixture/some_class.php.inc b/rules-tests/Php70/Rector/StmtsAwareInterface/IfIssetToCoalescingRector/Fixture/some_class.php.inc new file mode 100644 index 00000000000..adc1b2c84df --- /dev/null +++ b/rules-tests/Php70/Rector/StmtsAwareInterface/IfIssetToCoalescingRector/Fixture/some_class.php.inc @@ -0,0 +1,35 @@ +items[$key])) { + return $this->items[$key]; + } + + return 'fallback value'; + } +} + +?> +----- +items[$key] ?? 'fallback value'; + } +} + +?> diff --git a/rules-tests/Php70/Rector/StmtsAwareInterface/IfIssetToCoalescingRector/IfIssetToCoalescingRectorTest.php b/rules-tests/Php70/Rector/StmtsAwareInterface/IfIssetToCoalescingRector/IfIssetToCoalescingRectorTest.php new file mode 100644 index 00000000000..af655029023 --- /dev/null +++ b/rules-tests/Php70/Rector/StmtsAwareInterface/IfIssetToCoalescingRector/IfIssetToCoalescingRectorTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/configured_rule.php'; + } +} diff --git a/rules-tests/Php70/Rector/StmtsAwareInterface/IfIssetToCoalescingRector/config/configured_rule.php b/rules-tests/Php70/Rector/StmtsAwareInterface/IfIssetToCoalescingRector/config/configured_rule.php new file mode 100644 index 00000000000..59bdc1e740e --- /dev/null +++ b/rules-tests/Php70/Rector/StmtsAwareInterface/IfIssetToCoalescingRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(IfIssetToCoalescingRector::class); +}; diff --git a/rules/Php70/Rector/StmtsAwareInterface/IfIssetToCoalescingRector.php b/rules/Php70/Rector/StmtsAwareInterface/IfIssetToCoalescingRector.php new file mode 100644 index 00000000000..feb8cf72a9c --- /dev/null +++ b/rules/Php70/Rector/StmtsAwareInterface/IfIssetToCoalescingRector.php @@ -0,0 +1,144 @@ +items[$key])) { + return $this->items[$key]; + } + + return 'fallback value'; + } +} +CODE_SAMPLE + + , + <<<'CODE_SAMPLE' +class SomeClass +{ + private $items = []; + + public function resolve($key) + { + return $this->items[$key] ?? 'fallback value'; + } +} +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; + } + + foreach ($node->stmts as $key => $stmt) { + if (! $stmt instanceof Return_) { + continue; + } + + if (! $stmt->expr instanceof Expr) { + continue; + } + + $previousStmt = $node->stmts[$key - 1] ?? null; + + if (! $previousStmt instanceof If_) { + continue; + } + + if (! $previousStmt->cond instanceof Isset_) { + continue; + } + + $ifOnlyStmt = $this->matchBareIfOnlyStmt($previousStmt); + + if (! $ifOnlyStmt instanceof Return_) { + continue; + } + + if (! $ifOnlyStmt->expr instanceof Expr) { + continue; + } + + $ifIsset = $previousStmt->cond; + if (! $this->nodeComparator->areNodesEqual($ifOnlyStmt->expr, $ifIsset->vars[0])) { + continue; + } + + unset($node->stmts[$key - 1]); + + $stmt->expr = new Coalesce($ifOnlyStmt->expr, $stmt->expr); + return $node; + } + + return null; + } + + public function provideMinPhpVersion(): int + { + return PhpVersionFeature::NULL_COALESCE; + } + + private function matchBareIfOnlyStmt(If_ $if): ?Stmt + { + if ($if->else instanceof Else_) { + return null; + } + + if ($if->elseifs !== []) { + return null; + } + + if (count($if->stmts) !== 1) { + return null; + } + + return $if->stmts[0]; + } +}