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',