diff --git a/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/fixture.php.inc b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/fixture.php.inc new file mode 100644 index 00000000000..866d950a398 --- /dev/null +++ b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/fixture.php.inc @@ -0,0 +1,52 @@ + +----- + diff --git a/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/if_else_no_stmt.php.inc b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/if_else_no_stmt.php.inc new file mode 100644 index 00000000000..fd98c086a0a --- /dev/null +++ b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/if_else_no_stmt.php.inc @@ -0,0 +1,32 @@ + +----- + diff --git a/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/if_elseif_no_stmt.php.inc b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/if_elseif_no_stmt.php.inc new file mode 100644 index 00000000000..bc7334cbb66 --- /dev/null +++ b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/if_elseif_no_stmt.php.inc @@ -0,0 +1,36 @@ + +----- + diff --git a/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/if_no_stmt_with_else.php.inc b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/if_no_stmt_with_else.php.inc new file mode 100644 index 00000000000..41f562f1c9e --- /dev/null +++ b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/if_no_stmt_with_else.php.inc @@ -0,0 +1,32 @@ + +----- + diff --git a/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/if_no_stmt_with_else_no_stmt.php.inc b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/if_no_stmt_with_else_no_stmt.php.inc new file mode 100644 index 00000000000..3969df58f78 --- /dev/null +++ b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/if_no_stmt_with_else_no_stmt.php.inc @@ -0,0 +1,28 @@ + +----- + diff --git a/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/side_effect_checks.php.inc b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/side_effect_checks.php.inc new file mode 100644 index 00000000000..1d8200fa22f --- /dev/null +++ b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/side_effect_checks.php.inc @@ -0,0 +1,33 @@ + +----- + diff --git a/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/skip_if_comment.php.inc b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/skip_if_comment.php.inc new file mode 100644 index 00000000000..a8bbd1cf214 --- /dev/null +++ b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/skip_if_comment.php.inc @@ -0,0 +1,19 @@ + diff --git a/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/skip_property_fetch.php.inc b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/skip_property_fetch.php.inc new file mode 100644 index 00000000000..b5ac0366184 --- /dev/null +++ b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/skip_property_fetch.php.inc @@ -0,0 +1,17 @@ +v) { + echo '2'; + } + } +} + +?> diff --git a/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/skip_used_in_next_stmt.php.inc b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/skip_used_in_next_stmt.php.inc new file mode 100644 index 00000000000..83fefcf31ed --- /dev/null +++ b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/skip_used_in_next_stmt.php.inc @@ -0,0 +1,19 @@ += 0 && $result[$i] === '0'; $i--) { + ; + } + + if ($i >= 0 && $result[$i] === $decimalSep) { + $i--; + } + + $result = substr($result, 0, $i + 1); + } +} diff --git a/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/skip_used_in_next_stmt2.php.inc b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/skip_used_in_next_stmt2.php.inc new file mode 100644 index 00000000000..7479fe30f59 --- /dev/null +++ b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/Fixture/skip_used_in_next_stmt2.php.inc @@ -0,0 +1,19 @@ + $value) { + ; + } + + if ($i >= 0 && $result[$i] === $decimalSep) { + $i--; + } + + $result = substr($result, 0, $i + 1); + } +} diff --git a/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/RemoveDeadIfBlockRectorTest.php b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/RemoveDeadIfBlockRectorTest.php new file mode 100644 index 00000000000..60d139a16de --- /dev/null +++ b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/RemoveDeadIfBlockRectorTest.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/DeadCode/Rector/If_/RemoveDeadIfBlockRector/config/configured_rule.php b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/config/configured_rule.php new file mode 100644 index 00000000000..5cd1fadda4c --- /dev/null +++ b/rules-tests/DeadCode/Rector/If_/RemoveDeadIfBlockRector/config/configured_rule.php @@ -0,0 +1,9 @@ +withRules([RemoveDeadIfBlockRector::class]); diff --git a/rules/DeadCode/Rector/If_/RemoveDeadIfBlockRector.php b/rules/DeadCode/Rector/If_/RemoveDeadIfBlockRector.php new file mode 100644 index 00000000000..87456f68511 --- /dev/null +++ b/rules/DeadCode/Rector/If_/RemoveDeadIfBlockRector.php @@ -0,0 +1,156 @@ +> + */ + public function getNodeTypes(): array + { + return [If_::class]; + } + + /** + * @param If_ $node + * @return NodeVisitor::REMOVE_NODE|null|If_ + */ + public function refactor(Node $node): int|null|If_ + { + if ($node->else instanceof Else_ && $node->else->stmts === []) { + $node->else = null; + return $this->refactor($node) ?? $node; + } + + if ($node->elseifs !== []) { + foreach ($node->elseifs as $elseif) { + $keep_elseifs = array_filter( + $node->elseifs, + fn ($elseif) => $elseif->stmts !== [] || $this->sideEffectNodeDetector->detect($elseif->cond) + ); + if (count($node->elseifs) !== count($keep_elseifs)) { + $node->elseifs = $keep_elseifs; + return $this->refactor($node) ?? $node; + } + } + } + + if ($node->stmts !== []) { + return null; + } + + // Skip commented blocks because we can't know + // if the comment will make sense after merging. + if ($node->getComments() !== []) { + return null; + } + + if ($this->sideEffectNodeDetector->detect($node->cond)) { + return null; + } + + // When the if body is blank but it has an elseif, + // merge the negated if condition with the elseif condition + if ($node->elseifs !== []) { + $firstElseIf = $node->elseifs[0]; + $cond = new BooleanAnd( + $this->conditionInverter->createInvertedCondition($node->cond), + $firstElseIf->cond + ); + $if = new If_($cond, [ + 'stmts' => $firstElseIf->stmts, + ]); + if (count($node->elseifs) > 1) { + $if->elseifs = \array_slice($node->elseifs, 1); + } + return $this->refactor($if) ?? $if; + } + + if ($node->else instanceof Else_) { + $node->cond = $this->conditionInverter->createInvertedCondition($node->cond); + $node->stmts = $node->else->stmts; + $node->else = null; + return $node; + } + + return NodeVisitor::REMOVE_NODE; + } +} diff --git a/src/Config/Level/DeadCodeLevel.php b/src/Config/Level/DeadCodeLevel.php index 71c5f42f0ae..67c47c30c88 100644 --- a/src/Config/Level/DeadCodeLevel.php +++ b/src/Config/Level/DeadCodeLevel.php @@ -40,6 +40,7 @@ use Rector\DeadCode\Rector\FunctionLike\RemoveDeadReturnRector; use Rector\DeadCode\Rector\If_\ReduceAlwaysFalseIfOrRector; use Rector\DeadCode\Rector\If_\RemoveAlwaysTrueIfConditionRector; +use Rector\DeadCode\Rector\If_\RemoveDeadIfBlockRector; use Rector\DeadCode\Rector\If_\RemoveDeadInstanceOfRector; use Rector\DeadCode\Rector\If_\RemoveTypedPropertyDeadInstanceOfRector; use Rector\DeadCode\Rector\If_\RemoveUnusedNonEmptyArrayBeforeForeachRector; @@ -124,6 +125,7 @@ final class DeadCodeLevel RemoveDeadCatchRector::class, RemoveDeadTryCatchRector::class, + RemoveDeadIfBlockRector::class, RemoveDeadIfForeachForRector::class, RemoveConditionExactReturnRector::class, RemoveDeadStmtRector::class,