2929use PhpParser \Node \Expr \UnaryPlus ;
3030use PhpParser \Node \Expr \Variable ;
3131use PhpParser \Node \Scalar ;
32+ use PHPStan \Reflection \ReflectionProvider ;
3233use PHPStan \Type \ObjectType ;
3334use Rector \NodeTypeResolver \NodeTypeResolver ;
35+ use Rector \ValueObject \MethodName ;
3436final class LivingCodeManipulator
3537{
3638 /**
3739 * @readonly
3840 */
3941 private NodeTypeResolver $ nodeTypeResolver ;
40- public function __construct (NodeTypeResolver $ nodeTypeResolver )
42+ /**
43+ * @readonly
44+ */
45+ private ReflectionProvider $ reflectionProvider ;
46+ public function __construct (NodeTypeResolver $ nodeTypeResolver , ReflectionProvider $ reflectionProvider )
4147 {
4248 $ this ->nodeTypeResolver = $ nodeTypeResolver ;
49+ $ this ->reflectionProvider = $ reflectionProvider ;
4350 }
4451 /**
4552 * @return Expr[]|mixed[]
@@ -53,6 +60,9 @@ public function keepLivingCodeFromExpr($expr): array
5360 if ($ expr instanceof Closure || $ expr instanceof Scalar || $ expr instanceof ConstFetch) {
5461 return [];
5562 }
63+ if ($ expr instanceof Clone_ && $ this ->hasCloneMagicMethod ($ expr )) {
64+ return [$ expr ];
65+ }
5666 if ($ this ->isNestedExpr ($ expr )) {
5767 return $ this ->keepLivingCodeFromExpr ($ expr ->expr );
5868 }
@@ -92,6 +102,19 @@ private function isNestedExpr(Expr $expr): bool
92102 {
93103 return $ expr instanceof Cast || $ expr instanceof Empty_ || $ expr instanceof UnaryMinus || $ expr instanceof UnaryPlus || $ expr instanceof BitwiseNot || $ expr instanceof BooleanNot || $ expr instanceof Clone_;
94104 }
105+ private function hasCloneMagicMethod (Clone_ $ clone ): bool
106+ {
107+ $ cloneObjectType = $ this ->nodeTypeResolver ->getType ($ clone ->expr );
108+ foreach ($ cloneObjectType ->getObjectClassNames () as $ className ) {
109+ if (!$ this ->reflectionProvider ->hasClass ($ className )) {
110+ continue ;
111+ }
112+ if ($ this ->reflectionProvider ->getClass ($ className )->hasNativeMethod (MethodName::CLONE )) {
113+ return \true;
114+ }
115+ }
116+ return \false;
117+ }
95118 private function isBinaryOpWithoutChange (Expr $ expr ): bool
96119 {
97120 if (!$ expr instanceof BinaryOp) {
0 commit comments