From cea94d1672e3e4e589194d46d70c8c17d5752b4e Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 30 Sep 2025 22:54:32 +0700 Subject: [PATCH 1/3] [TypeDeclarationDocblocks] Allow override dummy array return on AddReturnDocblockDataProviderRector --- .../override_dummy_array_return.php.inc | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 rules-tests/TypeDeclarationDocblocks/Rector/Class_/AddReturnDocblockDataProviderRector/Fixture/override_dummy_array_return.php.inc diff --git a/rules-tests/TypeDeclarationDocblocks/Rector/Class_/AddReturnDocblockDataProviderRector/Fixture/override_dummy_array_return.php.inc b/rules-tests/TypeDeclarationDocblocks/Rector/Class_/AddReturnDocblockDataProviderRector/Fixture/override_dummy_array_return.php.inc new file mode 100644 index 00000000000..3dbab25317e --- /dev/null +++ b/rules-tests/TypeDeclarationDocblocks/Rector/Class_/AddReturnDocblockDataProviderRector/Fixture/override_dummy_array_return.php.inc @@ -0,0 +1,55 @@ + +----- + From d6f9d59eff0ae329821d4e0dd968aab2a8ae8f5d Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 30 Sep 2025 23:06:54 +0700 Subject: [PATCH 2/3] Fix --- .../NodeDocblockTypeDecorator.php | 9 +++------ ...kFromAssignsParamToParamReferenceRector.php | 4 +--- .../AddReturnDocblockDataProviderRector.php | 5 +++-- .../PhpDocManipulator/PhpDocTypeChanger.php | 18 ++++++++++++++++++ 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php b/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php index 2bf77471cac..c24b5de0cf5 100644 --- a/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php +++ b/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php @@ -46,15 +46,14 @@ public function decorateGenericIterableParamType( return false; } - $normalizedType = $this->typeNormalizer->generalizeConstantTypes($type); - $typeNode = $this->createTypeNode($normalizedType); + $typeNode = $this->createTypeNode($type); // no value iterable type if ($typeNode instanceof IdentifierTypeNode) { return false; } - $this->phpDocTypeChanger->changeParamType($classMethod, $phpDocInfo, $normalizedType, $param, $parameterName); + $this->phpDocTypeChanger->changeParamTypeNode($classMethod, $phpDocInfo, $param, $parameterName, $typeNode); return true; } @@ -76,9 +75,7 @@ public function decorateGenericIterableReturnType( return false; } - $returnTagValueNode = new ReturnTagValueNode($typeNode, ''); - - $this->addTagValueNodeAndUpdatePhpDocInfo($classMethodPhpDocInfo, $returnTagValueNode, $classMethod); + $this->phpDocTypeChanger->changeReturnTypeNode($classMethod, $classMethodPhpDocInfo, $typeNode); return true; } diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php index 97e4cbf7c72..70de92dddc4 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php @@ -102,9 +102,7 @@ public function refactor(Node $node): ?Node $paramTagValueNode = $phpDocInfo->getParamTagValueByName($paramName); // already defined, lets skip it - if ($this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag( - $paramTagValueNode - )) { + if ($this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag($paramTagValueNode)) { continue; } diff --git a/rules/TypeDeclarationDocblocks/Rector/Class_/AddReturnDocblockDataProviderRector.php b/rules/TypeDeclarationDocblocks/Rector/Class_/AddReturnDocblockDataProviderRector.php index 72672677702..007b9c971ef 100644 --- a/rules/TypeDeclarationDocblocks/Rector/Class_/AddReturnDocblockDataProviderRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/Class_/AddReturnDocblockDataProviderRector.php @@ -8,7 +8,6 @@ use PhpParser\Node\Expr; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\Return_; -use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer; use Rector\Rector\AbstractRector; @@ -17,6 +16,7 @@ use Rector\TypeDeclarationDocblocks\NodeFinder\DataProviderMethodsFinder; use Rector\TypeDeclarationDocblocks\NodeFinder\ReturnNodeFinder; use Rector\TypeDeclarationDocblocks\NodeFinder\YieldNodeFinder; +use Rector\TypeDeclarationDocblocks\TagNodeAnalyzer\UsefulArrayTagNodeAnalyzer; use Rector\TypeDeclarationDocblocks\TypeResolver\YieldTypeResolver; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -33,6 +33,7 @@ public function __construct( private readonly ReturnNodeFinder $returnNodeFinder, private readonly YieldTypeResolver $yieldTypeResolver, private readonly YieldNodeFinder $yieldNodeFinder, + private readonly UsefulArrayTagNodeAnalyzer $usefulArrayTagNodeAnalyzer, private readonly NodeDocblockTypeDecorator $nodeDocblockTypeDecorator, ) { } @@ -118,7 +119,7 @@ public function refactor(Node $node): ?Node $returnTagValueNode = $classMethodPhpDocInfo->getReturnTagValue(); // already set - if ($returnTagValueNode instanceof ReturnTagValueNode) { + if ($this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag($returnTagValueNode)) { continue; } diff --git a/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php b/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php index 8760126acd1..58cb9aae6cf 100644 --- a/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php +++ b/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php @@ -113,6 +113,24 @@ public function changeReturnTypeNode( $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($functionLike); } + public function changeParamTypeNode( + FunctionLike $functionLike, + PhpDocInfo $phpDocInfo, + Param $param, + string $paramName, + TypeNode $newTypeNode + ): void { + $existingParamTagValueNode = $phpDocInfo->getParamTagValueByName($paramName); + if ($existingParamTagValueNode instanceof ParamTagValueNode) { + $existingParamTagValueNode->type = $newTypeNode; + } else { + $paramTagValueNode = $this->paramPhpDocNodeFactory->create($newTypeNode, $param); + $phpDocInfo->addTagValueNode($paramTagValueNode); + } + + $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($functionLike); + } + public function changeReturnType(FunctionLike $functionLike, PhpDocInfo $phpDocInfo, Type $newType): bool { // better not touch this, can crash From be6ec9f15e3da25e0b03fc359257528e19c465cc Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 30 Sep 2025 23:11:36 +0700 Subject: [PATCH 3/3] fix --- src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php b/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php index 58cb9aae6cf..42acfaf2964 100644 --- a/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php +++ b/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php @@ -7,6 +7,7 @@ use PhpParser\Node\FunctionLike; use PhpParser\Node\Param; use PhpParser\Node\Stmt; +use PhpParser\Node\Stmt\ClassMethod; use PHPStan\PhpDocParser\Ast\ConstExpr\ConstFetchNode; use PHPStan\PhpDocParser\Ast\Node; use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode; @@ -114,7 +115,7 @@ public function changeReturnTypeNode( } public function changeParamTypeNode( - FunctionLike $functionLike, + ClassMethod $functionLike, PhpDocInfo $phpDocInfo, Param $param, string $paramName,