From 38b2b48beed51a5e7bb0269c3e6aeae90ef6d166 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 25 Jun 2026 06:48:38 +0700 Subject: [PATCH 1/3] [DeadCode] Skip on clone on object with __clone() method --- .../Fixture/skip_clone_has_clone.php.inc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 rules-tests/DeadCode/Rector/Expression/RemoveDeadStmtRector/Fixture/skip_clone_has_clone.php.inc diff --git a/rules-tests/DeadCode/Rector/Expression/RemoveDeadStmtRector/Fixture/skip_clone_has_clone.php.inc b/rules-tests/DeadCode/Rector/Expression/RemoveDeadStmtRector/Fixture/skip_clone_has_clone.php.inc new file mode 100644 index 00000000000..2fe3ee83ed2 --- /dev/null +++ b/rules-tests/DeadCode/Rector/Expression/RemoveDeadStmtRector/Fixture/skip_clone_has_clone.php.inc @@ -0,0 +1,14 @@ + Date: Thu, 25 Jun 2026 06:54:23 +0700 Subject: [PATCH 2/3] fix --- .../NodeManipulator/LivingCodeManipulator.php | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/rules/DeadCode/NodeManipulator/LivingCodeManipulator.php b/rules/DeadCode/NodeManipulator/LivingCodeManipulator.php index 2b1313799c3..459dd49e0f9 100644 --- a/rules/DeadCode/NodeManipulator/LivingCodeManipulator.php +++ b/rules/DeadCode/NodeManipulator/LivingCodeManipulator.php @@ -30,13 +30,16 @@ use PhpParser\Node\Expr\UnaryPlus; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Scalar; +use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\ObjectType; use Rector\NodeTypeResolver\NodeTypeResolver; +use Rector\ValueObject\MethodName; final readonly class LivingCodeManipulator { public function __construct( - private NodeTypeResolver $nodeTypeResolver + private NodeTypeResolver $nodeTypeResolver, + private ReflectionProvider $reflectionProvider ) { } @@ -53,6 +56,14 @@ public function keepLivingCodeFromExpr(Node | int | string | null $expr): array return []; } + if ($expr instanceof Clone_) { + if ($this->hasCloneMagicMethod($expr)) { + return [$expr]; + } + + return $this->keepLivingCodeFromExpr($expr->expr); + } + if ($this->isNestedExpr($expr)) { return $this->keepLivingCodeFromExpr($expr->expr); } @@ -106,8 +117,24 @@ private function isNestedExpr(Expr $expr): bool $expr instanceof UnaryMinus || $expr instanceof UnaryPlus || $expr instanceof BitwiseNot || - $expr instanceof BooleanNot || - $expr instanceof Clone_; + $expr instanceof BooleanNot; + } + + private function hasCloneMagicMethod(Clone_ $clone): bool + { + $cloneObjectType = $this->nodeTypeResolver->getType($clone->expr); + + foreach ($cloneObjectType->getObjectClassNames() as $className) { + if (! $this->reflectionProvider->hasClass($className)) { + continue; + } + + if ($this->reflectionProvider->getClass($className)->hasNativeMethod(MethodName::CLONE)) { + return true; + } + } + + return false; } private function isBinaryOpWithoutChange(Expr $expr): bool From 9a4c89aeb281a8c041ee0e1997519f77b2fc8f0d Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 25 Jun 2026 06:58:49 +0700 Subject: [PATCH 3/3] clean up --- .../NodeManipulator/LivingCodeManipulator.php | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/rules/DeadCode/NodeManipulator/LivingCodeManipulator.php b/rules/DeadCode/NodeManipulator/LivingCodeManipulator.php index 459dd49e0f9..1b24ab7638f 100644 --- a/rules/DeadCode/NodeManipulator/LivingCodeManipulator.php +++ b/rules/DeadCode/NodeManipulator/LivingCodeManipulator.php @@ -56,12 +56,8 @@ public function keepLivingCodeFromExpr(Node | int | string | null $expr): array return []; } - if ($expr instanceof Clone_) { - if ($this->hasCloneMagicMethod($expr)) { - return [$expr]; - } - - return $this->keepLivingCodeFromExpr($expr->expr); + if ($expr instanceof Clone_ && $this->hasCloneMagicMethod($expr)) { + return [$expr]; } if ($this->isNestedExpr($expr)) { @@ -117,7 +113,8 @@ private function isNestedExpr(Expr $expr): bool $expr instanceof UnaryMinus || $expr instanceof UnaryPlus || $expr instanceof BitwiseNot || - $expr instanceof BooleanNot; + $expr instanceof BooleanNot || + $expr instanceof Clone_; } private function hasCloneMagicMethod(Clone_ $clone): bool