diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Fixture/also_update_generic_collection_docblock.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Fixture/also_update_generic_collection_docblock.php.inc new file mode 100644 index 00000000000..bbdf8a63297 --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Fixture/also_update_generic_collection_docblock.php.inc @@ -0,0 +1,41 @@ + + */ + protected function build(): Collection + { + return new ArrayCollection([new stdClass()]); + } +} + +?> +----- + + */ + protected function build(): \Doctrine\Common\Collections\ArrayCollection + { + return new ArrayCollection([new stdClass()]); + } +} + +?> diff --git a/rules/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector.php b/rules/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector.php index 08da3729d4c..b4d4ef931c6 100644 --- a/rules/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector.php +++ b/rules/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector.php @@ -8,8 +8,14 @@ use PhpParser\Node\Identifier; use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Stmt\ClassMethod; +use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode; +use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode; use PHPStan\Reflection\ClassReflection; use PHPStan\Type\ObjectType; +use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; +use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; +use Rector\BetterPhpDocParser\ValueObject\Type\FullyQualifiedIdentifierTypeNode; +use Rector\Comments\NodeDocBlock\DocBlockUpdater; use Rector\PhpParser\AstResolver; use Rector\PhpParser\Node\BetterNodeFinder; use Rector\Rector\AbstractRector; @@ -28,6 +34,8 @@ public function __construct( private readonly BetterNodeFinder $betterNodeFinder, private readonly ReflectionResolver $reflectionResolver, private readonly AstResolver $astResolver, + private readonly PhpDocInfoFactory $phpDocInfoFactory, + private readonly DocBlockUpdater $docBlockUpdater ) { } @@ -140,9 +148,31 @@ public function refactor(Node $node): ?Node $node->returnType = new FullyQualified($actualReturnClass); + $this->updateDocblock($node, $actualReturnClass); + return $node; } + private function updateDocblock(ClassMethod $classMethod, string $actualReturnClass): void + { + $phpDocInfo = $this->phpDocInfoFactory->createFromNode($classMethod); + if (! $phpDocInfo instanceof PhpDocInfo) { + return; + } + + $returnTagValueNode = $phpDocInfo->getReturnTagValue(); + if (! $returnTagValueNode instanceof ReturnTagValueNode) { + return; + } + + if (! $returnTagValueNode->type instanceof GenericTypeNode) { + return; + } + + $returnTagValueNode->type->type = new FullyQualifiedIdentifierTypeNode($actualReturnClass); + $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($classMethod); + } + private function isDeclaredTypeFinal(string $declaredType): bool { if ($declaredType === 'object') {