diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector.php index da60b8800b5..37c7a678650 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector.php @@ -18,6 +18,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 +46,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 +104,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 +143,10 @@ 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 + // If parent method exists, skip adding docblock as it should inherit documentation from parent + return $this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($classMethod); + } }