From 760a069ab940b205ddb8971988c848ea3c811212 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 21:38:34 +0000 Subject: [PATCH 1/3] Initial plan From c34394f9c33c1e2ec05998b91ca235de32427078 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 21:43:17 +0000 Subject: [PATCH 2/3] Fix issue #9599: Skip adding docblock to overridden methods Co-authored-by: TomasVotruba <924196+TomasVotruba@users.noreply.github.com> --- ...turnArrayFromDirectArrayInstanceRector.php | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector.php index da60b8800b5..f5b3549f78e 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector.php @@ -10,6 +10,7 @@ use PhpParser\Node\Stmt\Return_; use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode; use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode; +use PHPStan\Reflection\MethodReflection; use PHPStan\Type\Constant\ConstantArrayType; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; @@ -18,6 +19,7 @@ use Rector\TypeDeclarationDocblocks\NodeFinder\ReturnNodeFinder; use Rector\TypeDeclarationDocblocks\TagNodeAnalyzer\UsefulArrayTagNodeAnalyzer; use Rector\TypeDeclarationDocblocks\TypeResolver\ConstantArrayTypeGeneralizer; +use Rector\VendorLocker\ParentClassMethodTypeOverrideGuard; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** @@ -45,13 +47,18 @@ final class DocblockReturnArrayFromDirectArrayInstanceRector extends AbstractRec * @readonly */ private UsefulArrayTagNodeAnalyzer $usefulArrayTagNodeAnalyzer; - public function __construct(PhpDocInfoFactory $phpDocInfoFactory, PhpDocTypeChanger $phpDocTypeChanger, ConstantArrayTypeGeneralizer $constantArrayTypeGeneralizer, ReturnNodeFinder $returnNodeFinder, UsefulArrayTagNodeAnalyzer $usefulArrayTagNodeAnalyzer) + /** + * @readonly + */ + private ParentClassMethodTypeOverrideGuard $parentClassMethodTypeOverrideGuard; + public function __construct(PhpDocInfoFactory $phpDocInfoFactory, PhpDocTypeChanger $phpDocTypeChanger, ConstantArrayTypeGeneralizer $constantArrayTypeGeneralizer, ReturnNodeFinder $returnNodeFinder, UsefulArrayTagNodeAnalyzer $usefulArrayTagNodeAnalyzer, ParentClassMethodTypeOverrideGuard $parentClassMethodTypeOverrideGuard) { $this->phpDocInfoFactory = $phpDocInfoFactory; $this->phpDocTypeChanger = $phpDocTypeChanger; $this->constantArrayTypeGeneralizer = $constantArrayTypeGeneralizer; $this->returnNodeFinder = $returnNodeFinder; $this->usefulArrayTagNodeAnalyzer = $usefulArrayTagNodeAnalyzer; + $this->parentClassMethodTypeOverrideGuard = $parentClassMethodTypeOverrideGuard; } public function getNodeTypes(): array { @@ -98,6 +105,10 @@ public function refactor(Node $node): ?Node if ($this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag($phpDocInfo->getReturnTagValue())) { return null; } + // skip if method overrides parent method with return docblock + if ($node instanceof ClassMethod && $this->shouldSkipOverriddenMethod($node)) { + return null; + } $soleReturn = $this->returnNodeFinder->findOnlyReturnWithExpr($node); if (!$soleReturn instanceof Return_) { return null; @@ -133,4 +144,14 @@ private function shouldSkipReturnMixedAndEmptyArray(PhpDocInfo $phpDocInfo, Arra // better than array{} return $returnTagValueNode->type instanceof ArrayTypeNode; } + private function shouldSkipOverriddenMethod(ClassMethod $classMethod): bool + { + // Check if this method overrides a parent method + $parentMethodReflection = $this->parentClassMethodTypeOverrideGuard->getParentClassMethod($classMethod); + if (!$parentMethodReflection instanceof MethodReflection) { + return \false; + } + // If parent method exists, skip adding docblock as it should inherit documentation from parent + return \true; + } } From 403f0c1757c5808e26c4c3dc61a5d3235a000996 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 21:44:41 +0000 Subject: [PATCH 3/3] Simplify shouldSkipOverriddenMethod to use hasParentClassMethod Co-authored-by: TomasVotruba <924196+TomasVotruba@users.noreply.github.com> --- .../DocblockReturnArrayFromDirectArrayInstanceRector.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector.php index f5b3549f78e..37c7a678650 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector.php @@ -10,7 +10,6 @@ use PhpParser\Node\Stmt\Return_; use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode; use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode; -use PHPStan\Reflection\MethodReflection; use PHPStan\Type\Constant\ConstantArrayType; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; @@ -147,11 +146,7 @@ private function shouldSkipReturnMixedAndEmptyArray(PhpDocInfo $phpDocInfo, Arra private function shouldSkipOverriddenMethod(ClassMethod $classMethod): bool { // Check if this method overrides a parent method - $parentMethodReflection = $this->parentClassMethodTypeOverrideGuard->getParentClassMethod($classMethod); - if (!$parentMethodReflection instanceof MethodReflection) { - return \false; - } // If parent method exists, skip adding docblock as it should inherit documentation from parent - return \true; + return $this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($classMethod); } }