2525use PhpParser \Node \Expr \Variable ;
2626use PhpParser \Node \FunctionLike ;
2727use PhpParser \Node \Param ;
28+ use PhpParser \Node \Stmt \ClassMethod ;
2829use PhpParser \Node \Stmt \Foreach_ ;
2930use PHPStan \PhpDocParser \Ast \PhpDoc \ParamTagValueNode ;
31+ use PHPStan \Reflection \ClassReflection ;
3032use Rector \BetterPhpDocParser \PhpDocInfo \PhpDocInfo ;
3133use Rector \BetterPhpDocParser \PhpDocInfo \PhpDocInfoFactory ;
3234use Rector \BetterPhpDocParser \ValueObject \PhpDocAttributeKey ;
3335use Rector \Comments \NodeDocBlock \DocBlockUpdater ;
3436use Rector \DeadCode \NodeAnalyzer \ExprUsedInNodeAnalyzer ;
3537use Rector \PhpParser \Enum \NodeGroup ;
3638use Rector \PhpParser \Node \BetterNodeFinder ;
39+ use Rector \PHPStan \ScopeFetcher ;
3740use Symplify \RuleDocGenerator \ValueObject \CodeSample \CodeSample ;
3841
3942/**
@@ -204,6 +207,9 @@ private function refactorForeach(Foreach_ $foreachNode): ?Foreach_
204207 )) ? $ foreachNode : null ;
205208 }
206209
210+ /**
211+ * @throws \Rector\Exception\ShouldNotHappenException
212+ */
207213 private function refactorFunctionLike (FunctionLike $ functionLikeNode ): ?FunctionLike
208214 {
209215 $ hasChanged = false ;
@@ -214,6 +220,8 @@ private function refactorFunctionLike(FunctionLike $functionLikeNode): ?Function
214220 foreach ($ functionLikeNode ->getParams () as $ paramNode ) {
215221 if (
216222 !$ paramNode ->var instanceof Variable
223+ || $ paramNode ->isPromoted ()
224+ || $ this ->hasPrototypeMethod ($ functionLikeNode )
217225 || $ this ->isUsedVariable ($ functionLikeNode , $ paramNode ->var )
218226 ) {
219227 continue ;
@@ -235,6 +243,28 @@ private function refactorFunctionLike(FunctionLike $functionLikeNode): ?Function
235243 return $ hasChanged ? $ functionLikeNode : null ;
236244 }
237245
246+ /**
247+ * @throws \Rector\Exception\ShouldNotHappenException
248+ */
249+ private function hasPrototypeMethod (FunctionLike $ functionLikeNode ): bool
250+ {
251+ if (!$ functionLikeNode instanceof ClassMethod) {
252+ return false ;
253+ }
254+
255+ $ classReflection = ScopeFetcher::fetch ($ functionLikeNode )->getClassReflection ();
256+
257+ if (!$ classReflection instanceof ClassReflection) {
258+ return false ;
259+ }
260+
261+ try {
262+ return $ classReflection ->getNativeReflection ()->getMethod ($ this ->getName ($ functionLikeNode ))->hasPrototype ();
263+ } catch (\ReflectionException $ reflectionException ) {
264+ return false ;
265+ }
266+ }
267+
238268 private function isUsedVariable (FunctionLike $ node , Variable $ variableNode ): bool
239269 {
240270 // Skip abstract, interface, empty body function like and foreach.
0 commit comments