From 751dd3c21fa7a359c55bb8cb4a239179ca40aa3f Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 1 Oct 2025 08:59:21 +0700 Subject: [PATCH 1/3] [TypeDeclarationDocblocks] Allow override dummy array var on DocblockVarArrayFromGetterReturnRector --- .../Fixture/override_dummy_array_var.php.inc | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 rules-tests/TypeDeclarationDocblocks/Rector/Class_/DocblockVarArrayFromGetterReturnRector/Fixture/override_dummy_array_var.php.inc diff --git a/rules-tests/TypeDeclarationDocblocks/Rector/Class_/DocblockVarArrayFromGetterReturnRector/Fixture/override_dummy_array_var.php.inc b/rules-tests/TypeDeclarationDocblocks/Rector/Class_/DocblockVarArrayFromGetterReturnRector/Fixture/override_dummy_array_var.php.inc new file mode 100644 index 00000000000..43ef36fd959 --- /dev/null +++ b/rules-tests/TypeDeclarationDocblocks/Rector/Class_/DocblockVarArrayFromGetterReturnRector/Fixture/override_dummy_array_var.php.inc @@ -0,0 +1,43 @@ +names; + } +} + +?> +----- +names; + } +} + +?> From dace7148bbb7a7e3169192f46351b80188646f65 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 1 Oct 2025 09:00:02 +0700 Subject: [PATCH 2/3] implemented :tada: --- .../NodeDocblockTypeDecorator.php | 4 +--- ...DocblockVarArrayFromGetterReturnRector.php | 21 ++++++++++++------- .../UsefulArrayTagNodeAnalyzer.php | 5 +++-- .../PhpDocManipulator/PhpDocTypeChanger.php | 15 ++++++++----- 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php b/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php index c24b5de0cf5..0c143b47ee2 100644 --- a/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php +++ b/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php @@ -94,9 +94,7 @@ public function decorateGenericIterableVarType(Type $type, PhpDocInfo $phpDocInf return false; } - $varTagValueNode = new VarTagValueNode($typeNode, '', ''); - - $this->addTagValueNodeAndUpdatePhpDocInfo($phpDocInfo, $varTagValueNode, $property); + $this->phpDocTypeChanger->changeVarTypeNode($property, $phpDocInfo, $typeNode); return true; } diff --git a/rules/TypeDeclarationDocblocks/Rector/Class_/DocblockVarArrayFromGetterReturnRector.php b/rules/TypeDeclarationDocblocks/Rector/Class_/DocblockVarArrayFromGetterReturnRector.php index ccad236cbbb..686fed4904b 100644 --- a/rules/TypeDeclarationDocblocks/Rector/Class_/DocblockVarArrayFromGetterReturnRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/Class_/DocblockVarArrayFromGetterReturnRector.php @@ -9,11 +9,11 @@ use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode; -use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; -use Rector\Comments\NodeDocBlock\DocBlockUpdater; use Rector\Rector\AbstractRector; +use Rector\TypeDeclarationDocblocks\NodeDocblockTypeDecorator; use Rector\TypeDeclarationDocblocks\NodeFinder\PropertyGetterFinder; +use Rector\TypeDeclarationDocblocks\TagNodeAnalyzer\UsefulArrayTagNodeAnalyzer; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -25,7 +25,8 @@ final class DocblockVarArrayFromGetterReturnRector extends AbstractRector public function __construct( private readonly PhpDocInfoFactory $phpDocInfoFactory, private readonly PropertyGetterFinder $propertyGetterFinder, - private readonly DocBlockUpdater $docBlockUpdater + private readonly UsefulArrayTagNodeAnalyzer $usefulArrayTagNodeAnalyzer, + private readonly NodeDocblockTypeDecorator $nodeDocblockTypeDecorator ) { } @@ -98,7 +99,7 @@ public function refactor(Node $node): ?Node $propertyPhpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property); // type is already known, skip it - if ($propertyPhpDocInfo->getVarTagValueNode() instanceof VarTagValueNode) { + if ($this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag($propertyPhpDocInfo->getVarTagValueNode())) { continue; } @@ -113,11 +114,15 @@ public function refactor(Node $node): ?Node continue; } - $varTagValeNode = new VarTagValueNode($returnTagValueNode->type, '', ''); + $isPropertyChanged = $this->nodeDocblockTypeDecorator->decorateGenericIterableVarType( + $classMethodDocInfo->getReturnType(), + $propertyPhpDocInfo, + $property + ); - // find matching getter and its @return docblock - $propertyPhpDocInfo->addTagValueNode($varTagValeNode); - $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($property); + if (! $isPropertyChanged) { + continue; + } $hasChanged = true; } diff --git a/rules/TypeDeclarationDocblocks/TagNodeAnalyzer/UsefulArrayTagNodeAnalyzer.php b/rules/TypeDeclarationDocblocks/TagNodeAnalyzer/UsefulArrayTagNodeAnalyzer.php index bff9f6a1f18..8f54666886e 100644 --- a/rules/TypeDeclarationDocblocks/TagNodeAnalyzer/UsefulArrayTagNodeAnalyzer.php +++ b/rules/TypeDeclarationDocblocks/TagNodeAnalyzer/UsefulArrayTagNodeAnalyzer.php @@ -6,13 +6,14 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode; use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode; +use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; final class UsefulArrayTagNodeAnalyzer { - public function isUsefulArrayTag(null|ReturnTagValueNode|ParamTagValueNode $tagValueNode): bool + public function isUsefulArrayTag(null|ReturnTagValueNode|ParamTagValueNode|VarTagValueNode $tagValueNode): bool { - if (! $tagValueNode instanceof ReturnTagValueNode && ! $tagValueNode instanceof ParamTagValueNode) { + if (! $tagValueNode instanceof ReturnTagValueNode && ! $tagValueNode instanceof ParamTagValueNode && ! $tagValueNode instanceof VarTagValueNode) { return false; } diff --git a/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php b/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php index 42acfaf2964..6e596d79c86 100644 --- a/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php +++ b/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php @@ -115,7 +115,7 @@ public function changeReturnTypeNode( } public function changeParamTypeNode( - ClassMethod $functionLike, + ClassMethod $classMethod, PhpDocInfo $phpDocInfo, Param $param, string $paramName, @@ -129,7 +129,7 @@ public function changeParamTypeNode( $phpDocInfo->addTagValueNode($paramTagValueNode); } - $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($functionLike); + $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($classMethod); } public function changeReturnType(FunctionLike $functionLike, PhpDocInfo $phpDocInfo, Type $newType): bool @@ -244,9 +244,14 @@ public function isAllowed(TypeNode $typeNode): bool */ public function changeVarTypeNode(Stmt $stmt, PhpDocInfo $phpDocInfo, TypeNode $typeNode): void { - // add completely new one - $varTagValueNode = new VarTagValueNode($typeNode, '', ''); - $phpDocInfo->addTagValueNode($varTagValueNode); + $existingVarTagValueNode = $phpDocInfo->getVarTagValueNode(); + if ($existingVarTagValueNode instanceof VarTagValueNode) { + $existingVarTagValueNode->type = $typeNode; + } else { + // add completely new one + $varTagValueNode = new VarTagValueNode($typeNode, '', ''); + $phpDocInfo->addTagValueNode($varTagValueNode); + } $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($stmt); } From d8b6c94cb8dc518e1a6bdfb025273de32c5de3dd Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Wed, 1 Oct 2025 02:02:39 +0000 Subject: [PATCH 3/3] [ci-review] Rector Rectify --- .../NodeDocblockTypeDecorator.php | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php b/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php index 0c143b47ee2..ec8845dc3ba 100644 --- a/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php +++ b/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php @@ -7,9 +7,6 @@ use PhpParser\Node\Param; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Property; -use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode; -use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode; -use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode; use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; @@ -20,7 +17,6 @@ use PHPStan\Type\Type; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger; -use Rector\Comments\NodeDocBlock\DocBlockUpdater; use Rector\Privatization\TypeManipulator\TypeNormalizer; use Rector\StaticTypeMapper\StaticTypeMapper; @@ -29,7 +25,6 @@ public function __construct( private TypeNormalizer $typeNormalizer, private StaticTypeMapper $staticTypeMapper, - private DocBlockUpdater $docBlockUpdater, private PhpDocTypeChanger $phpDocTypeChanger ) { } @@ -113,16 +108,6 @@ private function createTypeNode(Type $type): TypeNode return $typeNode; } - private function addTagValueNodeAndUpdatePhpDocInfo( - PhpDocInfo $phpDocInfo, - ParamTagValueNode|VarTagValueNode|ReturnTagValueNode $tagValueNode, - Property|ClassMethod $stmt - ): void { - $phpDocInfo->addTagValueNode($tagValueNode); - - $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($stmt); - } - private function isBareMixedType(Type $type): bool { if ($type instanceof MixedType) {