77use PhpParser \Node ;
88use PhpParser \Node \Expr \MethodCall ;
99use PhpParser \Node \Expr \StaticCall ;
10- use PhpParser \Node \Identifier ;
1110use PhpParser \Node \Stmt \ClassMethod ;
1211use PhpParser \Node \Stmt \Return_ ;
13- use PHPStan \PhpDocParser \Ast \PhpDoc \ReturnTagValueNode ;
12+ use PHPStan \Reflection \MethodReflection ;
13+ use PHPStan \Reflection \ParametersAcceptorSelector ;
14+ use PHPStan \Type \MixedType ;
1415use PHPStan \Type \ObjectType ;
1516use Rector \BetterPhpDocParser \PhpDocInfo \PhpDocInfoFactory ;
1617use Rector \BetterPhpDocParser \PhpDocManipulator \PhpDocTypeChanger ;
1718use Rector \Doctrine \Enum \DoctrineClass ;
18- use Rector \PhpParser \AstResolver ;
1919use Rector \Rector \AbstractRector ;
20+ use Rector \Reflection \ReflectionResolver ;
2021use Rector \TypeDeclarationDocblocks \NodeFinder \ReturnNodeFinder ;
2122use Rector \TypeDeclarationDocblocks \TagNodeAnalyzer \UsefulArrayTagNodeAnalyzer ;
2223use Symplify \RuleDocGenerator \ValueObject \CodeSample \CodeSample ;
@@ -31,7 +32,7 @@ public function __construct(
3132 private readonly PhpDocInfoFactory $ phpDocInfoFactory ,
3233 private readonly ReturnNodeFinder $ returnNodeFinder ,
3334 private readonly UsefulArrayTagNodeAnalyzer $ usefulArrayTagNodeAnalyzer ,
34- private readonly AstResolver $ astResolver ,
35+ private readonly ReflectionResolver $ reflectionResolver ,
3536 private readonly PhpDocTypeChanger $ phpDocTypeChanger ,
3637 ) {
3738 }
@@ -130,31 +131,25 @@ public function refactor(Node $node): ?Node
130131 return null ;
131132 }
132133
133- $ calledClassMethod = $ this ->astResolver -> resolveClassMethodFromCall ($ returnedMethodCall );
134- if (! $ calledClassMethod instanceof ClassMethod ) {
134+ $ calledMethodReflection = $ this ->reflectionResolver -> resolveFunctionLikeReflectionFromCall ($ returnedMethodCall );
135+ if (! $ calledMethodReflection instanceof MethodReflection ) {
135136 return null ;
136137 }
137138
138- if (! $ calledClassMethod ->returnType instanceof Identifier) {
139- return null ;
140- }
141-
142- if (! $ this ->isName ($ calledClassMethod ->returnType , 'array ' )) {
143- return null ;
144- }
145-
146- $ calledClassMethodPhpDocInfo = $ this ->phpDocInfoFactory ->createFromNodeOrEmpty ($ calledClassMethod );
139+ $ extendedParametersAcceptor = ParametersAcceptorSelector::combineAcceptors ($ calledMethodReflection ->getVariants ());
147140
148- $ calledReturnTagValue = $ calledClassMethodPhpDocInfo -> getReturnTagValue ();
149- if (! $ calledReturnTagValue instanceof ReturnTagValueNode ) {
141+ // native return type must be a plain array
142+ if (! $ extendedParametersAcceptor -> getNativeReturnType ()-> isArray ()-> yes () ) {
150143 return null ;
151144 }
152145
153- if (! $ this ->usefulArrayTagNodeAnalyzer ->isUsefulArrayTag ($ calledReturnTagValue )) {
146+ // docblock must carry a more specific array value type, e.g. SomeEntity[]
147+ $ calledReturnType = $ extendedParametersAcceptor ->getReturnType ();
148+ if ($ calledReturnType ->getIterableValueType () instanceof MixedType) {
154149 return null ;
155150 }
156151
157- $ this ->phpDocTypeChanger ->changeReturnType ($ node , $ phpDocInfo , $ calledClassMethodPhpDocInfo -> getReturnType () );
152+ $ this ->phpDocTypeChanger ->changeReturnType ($ node , $ phpDocInfo , $ calledReturnType );
158153
159154 return $ node ;
160155 }
0 commit comments