diff --git a/config/set/dead-code.php b/config/set/dead-code.php index a340ea6ece8..3c716ddc339 100644 --- a/config/set/dead-code.php +++ b/config/set/dead-code.php @@ -17,6 +17,7 @@ use Rector\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector; use Rector\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodRector; use Rector\DeadCode\Rector\ClassMethod\RemoveUnusedPromotedPropertyRector; use Rector\DeadCode\Rector\ClassMethod\RemoveUselessParamTagRector; +use Rector\DeadCode\Rector\ClassMethod\RemoveUselessReturnExprInConstructRector; use Rector\DeadCode\Rector\ClassMethod\RemoveUselessReturnTagRector; use Rector\DeadCode\Rector\Concat\RemoveConcatAutocastRector; use Rector\DeadCode\Rector\ConstFetch\RemovePhpVersionIdCheckRector; @@ -89,5 +90,6 @@ return static function (RectorConfig $rectorConfig) : void { RemoveAlwaysTrueIfConditionRector::class, RemoveDeadZeroAndOneOperationRector::class, RemovePhpVersionIdCheckRector::class, + RemoveUselessReturnExprInConstructRector::class, ]); }; diff --git a/docs/rector_rules_overview.md b/docs/rector_rules_overview.md index 3070aa41987..3f6fa376392 100644 --- a/docs/rector_rules_overview.md +++ b/docs/rector_rules_overview.md @@ -1,4 +1,4 @@ -# 354 Rules Overview +# 355 Rules Overview
@@ -10,7 +10,7 @@ - [CodingStyle](#codingstyle) (29) -- [DeadCode](#deadcode) (41) +- [DeadCode](#deadcode) (42) - [EarlyReturn](#earlyreturn) (9) @@ -2839,6 +2839,36 @@ Remove `@param` docblock with same type as parameter type
+### RemoveUselessReturnExprInConstructRector + +Remove useless return Expr in `__construct()` + +- class: [`Rector\DeadCode\Rector\ClassMethod\RemoveUselessReturnExprInConstructRector`](../rules/DeadCode/Rector/ClassMethod/RemoveUselessReturnExprInConstructRector.php) + +```diff + class SomeClass + { + public function __construct() + { + if (rand(0, 1)) { + $this->init(); +- return true; ++ return; + } + + if (rand(2, 3)) { +- return parent::construct(); ++ parent::construct(); ++ return; + } + + $this->execute(); + } + } +``` + +
+ ### RemoveUselessReturnTagRector Remove `@return` docblock with same type as defined in PHP diff --git a/packages/PhpDocParser/NodeTraverser/SimpleCallableNodeTraverser.php b/packages/PhpDocParser/NodeTraverser/SimpleCallableNodeTraverser.php index 183184aa2f4..3c173469978 100644 --- a/packages/PhpDocParser/NodeTraverser/SimpleCallableNodeTraverser.php +++ b/packages/PhpDocParser/NodeTraverser/SimpleCallableNodeTraverser.php @@ -12,7 +12,7 @@ use Rector\PhpDocParser\NodeVisitor\CallableNodeVisitor; final class SimpleCallableNodeTraverser { /** - * @param callable(Node $node): (int|Node|null) $callable + * @param callable(Node): (int|Node|null|Node[]) $callable * @param Node|Node[]|null $node */ public function traverseNodesWithCallable($node, callable $callable) : void diff --git a/packages/PhpDocParser/NodeVisitor/CallableNodeVisitor.php b/packages/PhpDocParser/NodeVisitor/CallableNodeVisitor.php index ae7318e6e9b..826426a3b0b 100644 --- a/packages/PhpDocParser/NodeVisitor/CallableNodeVisitor.php +++ b/packages/PhpDocParser/NodeVisitor/CallableNodeVisitor.php @@ -12,7 +12,7 @@ use PhpParser\NodeVisitorAbstract; final class CallableNodeVisitor extends NodeVisitorAbstract { /** - * @var callable(Node): (int|Node|null) + * @var callable(Node): (int|Node|null|Node[]) */ private $callable; /** @@ -20,7 +20,11 @@ final class CallableNodeVisitor extends NodeVisitorAbstract */ private $nodeIdToRemove; /** - * @param callable(Node $node): (int|Node|null) $callable + * @var array + */ + private $nodesToReturn = []; + /** + * @param callable(Node $node): (int|Node|null|Node[]) $callable */ public function __construct(callable $callable) { @@ -33,19 +37,24 @@ final class CallableNodeVisitor extends NodeVisitorAbstract { $originalNode = $node; $callable = $this->callable; - /** @var int|Node|null $newNode */ + /** @var int|Node|null|Node[] $newNode */ $newNode = $callable($node); if ($newNode === NodeTraverser::REMOVE_NODE) { $this->nodeIdToRemove = \spl_object_id($originalNode); return $originalNode; } + if (\is_array($newNode)) { + $nodeId = \spl_object_id($node); + $this->nodesToReturn[$nodeId] = $newNode; + return $node; + } if ($originalNode instanceof Stmt && $newNode instanceof Expr) { return new Expression($newNode); } return $newNode; } /** - * @return int|\PhpParser\Node + * @return int|Node|Node[] */ public function leaveNode(Node $node) { @@ -53,6 +62,9 @@ final class CallableNodeVisitor extends NodeVisitorAbstract $this->nodeIdToRemove = null; return NodeTraverser::REMOVE_NODE; } - return $node; + if ($this->nodesToReturn === []) { + return $node; + } + return $this->nodesToReturn[\spl_object_id($node)] ?? $node; } } diff --git a/rules/DeadCode/Rector/ClassMethod/RemoveUselessReturnExprInConstructRector.php b/rules/DeadCode/Rector/ClassMethod/RemoveUselessReturnExprInConstructRector.php new file mode 100644 index 00000000000..4851e475a4c --- /dev/null +++ b/rules/DeadCode/Rector/ClassMethod/RemoveUselessReturnExprInConstructRector.php @@ -0,0 +1,116 @@ +exprAnalyzer = $exprAnalyzer; + } + public function getRuleDefinition() : RuleDefinition + { + return new RuleDefinition('Remove useless return Expr in __construct()', [new CodeSample(<<<'CODE_SAMPLE' +class SomeClass +{ + public function __construct() + { + if (rand(0, 1)) { + $this->init(); + return true; + } + + if (rand(2, 3)) { + return parent::construct(); + } + + $this->execute(); + } +} +CODE_SAMPLE +, <<<'CODE_SAMPLE' +class SomeClass +{ + public function __construct() + { + if (rand(0, 1)) { + $this->init(); + return; + } + + if (rand(2, 3)) { + parent::construct(); + return; + } + + $this->execute(); + } +} +CODE_SAMPLE +)]); + } + /** + * @return array> + */ + public function getNodeTypes() : array + { + return [ClassMethod::class]; + } + /** + * @param ClassMethod $node + */ + public function refactor(Node $node) : ?Node + { + if ($node->stmts === null) { + return null; + } + if (!$this->isName($node, MethodName::CONSTRUCT)) { + return null; + } + $hasChanged = \false; + $this->traverseNodesWithCallable($node->stmts, function (Node $subNode) use(&$hasChanged) { + if ($subNode instanceof Class_ || $subNode instanceof Function_ || $subNode instanceof Closure) { + return NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN; + } + if (!$subNode instanceof Return_) { + return null; + } + if (!$subNode->expr instanceof Expr) { + return null; + } + $hasChanged = \true; + if ($this->exprAnalyzer->isDynamicExpr($subNode->expr)) { + return [new Expression($subNode->expr), new Return_()]; + } + $subNode->expr = null; + return $subNode; + }); + if ($hasChanged) { + return $node; + } + return null; + } +} diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index 67fce7a99d8..477891704d2 100644 --- a/src/Application/VersionResolver.php +++ b/src/Application/VersionResolver.php @@ -19,12 +19,12 @@ final class VersionResolver * @api * @var string */ - public const PACKAGE_VERSION = '444bc59e559a1c8b65117f992a489208946661dd'; + public const PACKAGE_VERSION = 'b7a5fefedc9d1a32c1f238a6a8c9b89b88e7d21c'; /** * @api * @var string */ - public const RELEASE_DATE = '2023-10-12 01:22:06'; + public const RELEASE_DATE = '2023-10-12 17:22:32'; /** * @var int */ diff --git a/src/Rector/AbstractRector.php b/src/Rector/AbstractRector.php index a6c7cc737ff..6e383467597 100644 --- a/src/Rector/AbstractRector.php +++ b/src/Rector/AbstractRector.php @@ -242,7 +242,7 @@ CODE_SAMPLE; } /** * @param Node|Node[] $nodes - * @param callable(Node $node): (Node|null|int) $callable + * @param callable(Node): (int|Node|null|Node[]) $callable */ protected function traverseNodesWithCallable($nodes, callable $callable) : void { diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index ed8bcd88220..300222af02b 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -1322,6 +1322,7 @@ return array( 'Rector\\DeadCode\\Rector\\ClassMethod\\RemoveUnusedPrivateMethodRector' => $baseDir . '/rules/DeadCode/Rector/ClassMethod/RemoveUnusedPrivateMethodRector.php', 'Rector\\DeadCode\\Rector\\ClassMethod\\RemoveUnusedPromotedPropertyRector' => $baseDir . '/rules/DeadCode/Rector/ClassMethod/RemoveUnusedPromotedPropertyRector.php', 'Rector\\DeadCode\\Rector\\ClassMethod\\RemoveUselessParamTagRector' => $baseDir . '/rules/DeadCode/Rector/ClassMethod/RemoveUselessParamTagRector.php', + 'Rector\\DeadCode\\Rector\\ClassMethod\\RemoveUselessReturnExprInConstructRector' => $baseDir . '/rules/DeadCode/Rector/ClassMethod/RemoveUselessReturnExprInConstructRector.php', 'Rector\\DeadCode\\Rector\\ClassMethod\\RemoveUselessReturnTagRector' => $baseDir . '/rules/DeadCode/Rector/ClassMethod/RemoveUselessReturnTagRector.php', 'Rector\\DeadCode\\Rector\\Concat\\RemoveConcatAutocastRector' => $baseDir . '/rules/DeadCode/Rector/Concat/RemoveConcatAutocastRector.php', 'Rector\\DeadCode\\Rector\\ConstFetch\\RemovePhpVersionIdCheckRector' => $baseDir . '/rules/DeadCode/Rector/ConstFetch/RemovePhpVersionIdCheckRector.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 2f1f5cd3289..abf6fb34af5 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -1540,6 +1540,7 @@ class ComposerStaticInit46a0b0ac2ea1371bb06be09a20f71c2b 'Rector\\DeadCode\\Rector\\ClassMethod\\RemoveUnusedPrivateMethodRector' => __DIR__ . '/../..' . '/rules/DeadCode/Rector/ClassMethod/RemoveUnusedPrivateMethodRector.php', 'Rector\\DeadCode\\Rector\\ClassMethod\\RemoveUnusedPromotedPropertyRector' => __DIR__ . '/../..' . '/rules/DeadCode/Rector/ClassMethod/RemoveUnusedPromotedPropertyRector.php', 'Rector\\DeadCode\\Rector\\ClassMethod\\RemoveUselessParamTagRector' => __DIR__ . '/../..' . '/rules/DeadCode/Rector/ClassMethod/RemoveUselessParamTagRector.php', + 'Rector\\DeadCode\\Rector\\ClassMethod\\RemoveUselessReturnExprInConstructRector' => __DIR__ . '/../..' . '/rules/DeadCode/Rector/ClassMethod/RemoveUselessReturnExprInConstructRector.php', 'Rector\\DeadCode\\Rector\\ClassMethod\\RemoveUselessReturnTagRector' => __DIR__ . '/../..' . '/rules/DeadCode/Rector/ClassMethod/RemoveUselessReturnTagRector.php', 'Rector\\DeadCode\\Rector\\Concat\\RemoveConcatAutocastRector' => __DIR__ . '/../..' . '/rules/DeadCode/Rector/Concat/RemoveConcatAutocastRector.php', 'Rector\\DeadCode\\Rector\\ConstFetch\\RemovePhpVersionIdCheckRector' => __DIR__ . '/../..' . '/rules/DeadCode/Rector/ConstFetch/RemovePhpVersionIdCheckRector.php',