77use PhpParser \Node \Identifier ;
88use PhpParser \Node \Name \FullyQualified ;
99use PhpParser \Node \Stmt \ClassMethod ;
10+ use PHPStan \PhpDocParser \Ast \PhpDoc \ReturnTagValueNode ;
11+ use PHPStan \PhpDocParser \Ast \Type \GenericTypeNode ;
1012use PHPStan \Reflection \ClassReflection ;
1113use PHPStan \Type \ObjectType ;
14+ use Rector \BetterPhpDocParser \PhpDocInfo \PhpDocInfo ;
15+ use Rector \BetterPhpDocParser \PhpDocInfo \PhpDocInfoFactory ;
16+ use Rector \BetterPhpDocParser \ValueObject \Type \FullyQualifiedIdentifierTypeNode ;
17+ use Rector \Comments \NodeDocBlock \DocBlockUpdater ;
1218use Rector \PhpParser \AstResolver ;
1319use Rector \PhpParser \Node \BetterNodeFinder ;
1420use Rector \Rector \AbstractRector ;
@@ -34,11 +40,21 @@ final class NarrowObjectReturnTypeRector extends AbstractRector
3440 * @readonly
3541 */
3642 private AstResolver $ astResolver ;
37- public function __construct (BetterNodeFinder $ betterNodeFinder , ReflectionResolver $ reflectionResolver , AstResolver $ astResolver )
43+ /**
44+ * @readonly
45+ */
46+ private PhpDocInfoFactory $ phpDocInfoFactory ;
47+ /**
48+ * @readonly
49+ */
50+ private DocBlockUpdater $ docBlockUpdater ;
51+ public function __construct (BetterNodeFinder $ betterNodeFinder , ReflectionResolver $ reflectionResolver , AstResolver $ astResolver , PhpDocInfoFactory $ phpDocInfoFactory , DocBlockUpdater $ docBlockUpdater )
3852 {
3953 $ this ->betterNodeFinder = $ betterNodeFinder ;
4054 $ this ->reflectionResolver = $ reflectionResolver ;
4155 $ this ->astResolver = $ astResolver ;
56+ $ this ->phpDocInfoFactory = $ phpDocInfoFactory ;
57+ $ this ->docBlockUpdater = $ docBlockUpdater ;
4258 }
4359 public function getRuleDefinition (): RuleDefinition
4460 {
@@ -124,8 +140,25 @@ public function refactor(Node $node): ?Node
124140 return null ;
125141 }
126142 $ node ->returnType = new FullyQualified ($ actualReturnClass );
143+ $ this ->updateDocblock ($ node , $ actualReturnClass );
127144 return $ node ;
128145 }
146+ private function updateDocblock (ClassMethod $ classMethod , string $ actualReturnClass ): void
147+ {
148+ $ phpDocInfo = $ this ->phpDocInfoFactory ->createFromNode ($ classMethod );
149+ if (!$ phpDocInfo instanceof PhpDocInfo) {
150+ return ;
151+ }
152+ $ returnTagValueNode = $ phpDocInfo ->getReturnTagValue ();
153+ if (!$ returnTagValueNode instanceof ReturnTagValueNode) {
154+ return ;
155+ }
156+ if (!$ returnTagValueNode ->type instanceof GenericTypeNode) {
157+ return ;
158+ }
159+ $ returnTagValueNode ->type ->type = new FullyQualifiedIdentifierTypeNode ($ actualReturnClass );
160+ $ this ->docBlockUpdater ->updateRefactoredNodeWithPhpDocInfo ($ classMethod );
161+ }
129162 private function isDeclaredTypeFinal (string $ declaredType ): bool
130163 {
131164 if ($ declaredType === 'object ' ) {
0 commit comments