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];
+ }
+}