55namespace Rector \DeadCode \Rector \ClassMethod ;
66
77use PhpParser \Node ;
8+ use PhpParser \Node \Expr \Array_ ;
89use PhpParser \Node \Expr \MethodCall ;
910use PhpParser \Node \Expr \Variable ;
1011use PhpParser \Node \Name \FullyQualified ;
1516use Rector \BetterPhpDocParser \PhpDocInfo \PhpDocInfoFactory ;
1617use Rector \DeadCode \NodeManipulator \ControllerClassMethodManipulator ;
1718use Rector \NodeAnalyzer \ParamAnalyzer ;
19+ use Rector \NodeCollector \NodeAnalyzer \ArrayCallableMethodMatcher ;
1820use Rector \NodeManipulator \ClassMethodManipulator ;
1921use Rector \PhpParser \Node \BetterNodeFinder ;
22+ use Rector \PHPStan \ScopeFetcher ;
2023use Rector \Rector \AbstractRector ;
2124use Rector \ValueObject \MethodName ;
2225use Symplify \RuleDocGenerator \ValueObject \CodeSample \CodeSample ;
@@ -32,7 +35,8 @@ public function __construct(
3235 private readonly ControllerClassMethodManipulator $ controllerClassMethodManipulator ,
3336 private readonly ParamAnalyzer $ paramAnalyzer ,
3437 private readonly PhpDocInfoFactory $ phpDocInfoFactory ,
35- private readonly BetterNodeFinder $ betterNodeFinder
38+ private readonly BetterNodeFinder $ betterNodeFinder ,
39+ private readonly ArrayCallableMethodMatcher $ arrayCallableMethodMatcher
3640 ) {
3741 }
3842
@@ -132,14 +136,15 @@ private function shouldSkipNonFinalNonPrivateClassMethod(Class_ $class, ClassMet
132136 private function shouldSkipClassMethod (Class_ $ class , ClassMethod $ classMethod ): bool
133137 {
134138 $ desiredClassMethodName = $ this ->getName ($ classMethod );
139+ $ className = (string ) $ this ->getName ($ class );
135140
136141 // is method called somewhere else in the class?
137142 foreach ($ class ->getMethods () as $ anotherClassMethod ) {
138143 if ($ anotherClassMethod === $ classMethod ) {
139144 continue ;
140145 }
141146
142- if ($ this ->containsMethodCall ($ anotherClassMethod , $ desiredClassMethodName )) {
147+ if ($ this ->containsMethodCallOrArrayCallable ($ anotherClassMethod , $ desiredClassMethodName, $ className )) {
143148 return true ;
144149 }
145150 }
@@ -182,11 +187,22 @@ private function hasDeprecatedAnnotation(ClassMethod $classMethod): bool
182187 return $ phpDocInfo ->hasByType (DeprecatedTagValueNode::class);
183188 }
184189
185- private function containsMethodCall (ClassMethod $ anotherClassMethod , string $ desiredClassMethodName ): bool
190+ private function containsMethodCallOrArrayCallable (ClassMethod $ anotherClassMethod , string $ desiredClassMethodName, string $ className ): bool
186191 {
192+ $ scope = ScopeFetcher::fetch ($ anotherClassMethod );
187193 return (bool ) $ this ->betterNodeFinder ->findFirst ($ anotherClassMethod , function (Node $ node ) use (
188- $ desiredClassMethodName
194+ $ desiredClassMethodName ,
195+ $ className ,
196+ $ scope
189197 ): bool {
198+ if ($ node instanceof Array_) {
199+ return (bool ) $ this ->arrayCallableMethodMatcher ->match (
200+ $ node ,
201+ $ scope ,
202+ $ className
203+ );
204+ }
205+
190206 if (! $ node instanceof MethodCall) {
191207 return false ;
192208 }
0 commit comments