From 219dfbc6e039226c8d2f98713adf099ac402408f Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 30 Sep 2025 19:48:48 +0700 Subject: [PATCH 1/5] [TypeDeclarationDocblocks] Allow override dummy array param on AddParamArrayDocblockFromAssignsParamToParamReferenceRector --- .../override_dummy_array_param.php.inc | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector/Fixture/override_dummy_array_param.php.inc diff --git a/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector/Fixture/override_dummy_array_param.php.inc b/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector/Fixture/override_dummy_array_param.php.inc new file mode 100644 index 00000000000..9c26cd1216f --- /dev/null +++ b/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector/Fixture/override_dummy_array_param.php.inc @@ -0,0 +1,33 @@ + +----- + From b0738f9f920d972be8637ef648d91c3d4150cd99 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 30 Sep 2025 20:04:58 +0700 Subject: [PATCH 2/5] implemented :tada: --- ...FromAssignsParamToParamReferenceRector.php | 25 +++++++++---------- .../UsefulArrayTagNodeAnalyzer.php | 7 +++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php index a67d880da1e..96e4c2b953e 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php @@ -11,9 +11,11 @@ use PHPStan\Type\ArrayType; use PHPStan\Type\MixedType; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; +use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger; +use Rector\Privatization\TypeManipulator\TypeNormalizer; use Rector\Rector\AbstractRector; -use Rector\TypeDeclarationDocblocks\NodeDocblockTypeDecorator; use Rector\TypeDeclarationDocblocks\NodeFinder\ArrayDimFetchFinder; +use Rector\TypeDeclarationDocblocks\TagNodeAnalyzer\UsefulArrayTagNodeAnalyzer; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -25,7 +27,9 @@ final class AddParamArrayDocblockFromAssignsParamToParamReferenceRector extends public function __construct( private readonly PhpDocInfoFactory $phpDocInfoFactory, private readonly ArrayDimFetchFinder $arrayDimFetchFinder, - private readonly NodeDocblockTypeDecorator $nodeDocblockTypeDecorator, + private readonly UsefulArrayTagNodeAnalyzer $usefulArrayTagNodeAnalyzer, + private readonly TypeNormalizer $typeNormalizer, + private readonly PhpDocTypeChanger $phpDocTypeChanger ) { } @@ -101,7 +105,9 @@ public function refactor(Node $node): ?Node $paramTagValueNode = $phpDocInfo->getParamTagValueByName($paramName); // already defined, lets skip it - if ($paramTagValueNode instanceof ParamTagValueNode) { + if ($paramTagValueNode instanceof ParamTagValueNode && $this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag( + $paramTagValueNode + )) { continue; } @@ -113,18 +119,11 @@ public function refactor(Node $node): ?Node } $assignedExprType = $this->getType($exprs[0]); - $iterableType = new ArrayType(new MixedType(), $assignedExprType); - - $hasParamTypeChanged = $this->nodeDocblockTypeDecorator->decorateGenericIterableParamType( - $iterableType, - $phpDocInfo, - $node, - $paramName + $iterableType = $this->typeNormalizer->generalizeConstantTypes( + new ArrayType(new MixedType(), $assignedExprType) ); - if (! $hasParamTypeChanged) { - continue; - } + $this->phpDocTypeChanger->changeParamType($node, $phpDocInfo, $iterableType, $param, $paramName); $hasChanged = true; } diff --git a/rules/TypeDeclarationDocblocks/TagNodeAnalyzer/UsefulArrayTagNodeAnalyzer.php b/rules/TypeDeclarationDocblocks/TagNodeAnalyzer/UsefulArrayTagNodeAnalyzer.php index e714fab753b..bff9f6a1f18 100644 --- a/rules/TypeDeclarationDocblocks/TagNodeAnalyzer/UsefulArrayTagNodeAnalyzer.php +++ b/rules/TypeDeclarationDocblocks/TagNodeAnalyzer/UsefulArrayTagNodeAnalyzer.php @@ -4,18 +4,19 @@ namespace Rector\TypeDeclarationDocblocks\TagNodeAnalyzer; +use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode; use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; final class UsefulArrayTagNodeAnalyzer { - public function isUsefulArrayTag(?ReturnTagValueNode $returnTagValueNode): bool + public function isUsefulArrayTag(null|ReturnTagValueNode|ParamTagValueNode $tagValueNode): bool { - if (! $returnTagValueNode instanceof ReturnTagValueNode) { + if (! $tagValueNode instanceof ReturnTagValueNode && ! $tagValueNode instanceof ParamTagValueNode) { return false; } - $type = $returnTagValueNode->type; + $type = $tagValueNode->type; if (! $type instanceof IdentifierTypeNode) { return true; } From 43bc16552abb3e2f09ca2e6706bfbbe1ea9396fe Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 30 Sep 2025 20:08:36 +0700 Subject: [PATCH 3/5] re use NodeDocblockTypeDecorator --- .../NodeDocblockTypeDecorator.php | 8 +++++--- ...ckFromAssignsParamToParamReferenceRector.php | 17 +++++++++-------- ...odArrayDocblockParamFromLocalCallsRector.php | 1 + 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php b/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php index 2178a14a9f6..a526ad68ee1 100644 --- a/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php +++ b/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php @@ -4,6 +4,7 @@ namespace Rector\TypeDeclarationDocblocks; +use PhpParser\Node\Param; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Property; use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode; @@ -18,6 +19,7 @@ use PHPStan\Type\NeverType; 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; @@ -28,6 +30,7 @@ public function __construct( private TypeNormalizer $typeNormalizer, private StaticTypeMapper $staticTypeMapper, private DocBlockUpdater $docBlockUpdater, + private PhpDocTypeChanger $phpDocTypeChanger ) { } @@ -35,6 +38,7 @@ public function decorateGenericIterableParamType( Type $type, PhpDocInfo $phpDocInfo, ClassMethod $classMethod, + Param $param, string $parameterName ): bool { if ($this->isBareMixedType($type)) { @@ -50,9 +54,7 @@ public function decorateGenericIterableParamType( return false; } - $paramTagValueNode = new ParamTagValueNode($typeNode, false, '$' . $parameterName, '', false); - - $this->addTagValueNodeAndUpdatePhpDocInfo($phpDocInfo, $paramTagValueNode, $classMethod); + $this->phpDocTypeChanger->changeParamType($classMethod, $phpDocInfo, $normalizedType, $param, $parameterName); return true; } diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php index 96e4c2b953e..83466c0d620 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php @@ -11,9 +11,8 @@ use PHPStan\Type\ArrayType; use PHPStan\Type\MixedType; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; -use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger; -use Rector\Privatization\TypeManipulator\TypeNormalizer; use Rector\Rector\AbstractRector; +use Rector\TypeDeclarationDocblocks\NodeDocblockTypeDecorator; use Rector\TypeDeclarationDocblocks\NodeFinder\ArrayDimFetchFinder; use Rector\TypeDeclarationDocblocks\TagNodeAnalyzer\UsefulArrayTagNodeAnalyzer; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; @@ -28,8 +27,7 @@ public function __construct( private readonly PhpDocInfoFactory $phpDocInfoFactory, private readonly ArrayDimFetchFinder $arrayDimFetchFinder, private readonly UsefulArrayTagNodeAnalyzer $usefulArrayTagNodeAnalyzer, - private readonly TypeNormalizer $typeNormalizer, - private readonly PhpDocTypeChanger $phpDocTypeChanger + private readonly NodeDocblockTypeDecorator $nodeDocblockTypeDecorator, ) { } @@ -119,12 +117,15 @@ public function refactor(Node $node): ?Node } $assignedExprType = $this->getType($exprs[0]); - $iterableType = $this->typeNormalizer->generalizeConstantTypes( - new ArrayType(new MixedType(), $assignedExprType) + $iterableType = new ArrayType(new MixedType(), $assignedExprType); + $this->nodeDocblockTypeDecorator->decorateGenericIterableParamType( + $iterableType, + $phpDocInfo, + $node, + $param, + $paramName ); - $this->phpDocTypeChanger->changeParamType($node, $phpDocInfo, $iterableType, $param, $paramName); - $hasChanged = true; } diff --git a/rules/TypeDeclarationDocblocks/Rector/Class_/ClassMethodArrayDocblockParamFromLocalCallsRector.php b/rules/TypeDeclarationDocblocks/Rector/Class_/ClassMethodArrayDocblockParamFromLocalCallsRector.php index 36408389a68..ddf5f25009d 100644 --- a/rules/TypeDeclarationDocblocks/Rector/Class_/ClassMethodArrayDocblockParamFromLocalCallsRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/Class_/ClassMethodArrayDocblockParamFromLocalCallsRector.php @@ -127,6 +127,7 @@ public function refactor(Node $node): ?Node $resolvedParameterType, $classMethodPhpDocInfo, $classMethod, + $param, $parameterName ); From f2551d0e5a28f6032b35703b425588cc6ef35bd8 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 30 Sep 2025 20:09:02 +0700 Subject: [PATCH 4/5] re use NodeDocblockTypeDecorator --- ...mArrayDocblockFromAssignsParamToParamReferenceRector.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php index 83466c0d620..63b48c40487 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php @@ -118,7 +118,7 @@ public function refactor(Node $node): ?Node $assignedExprType = $this->getType($exprs[0]); $iterableType = new ArrayType(new MixedType(), $assignedExprType); - $this->nodeDocblockTypeDecorator->decorateGenericIterableParamType( + $hasParamTypeChanged = $this->nodeDocblockTypeDecorator->decorateGenericIterableParamType( $iterableType, $phpDocInfo, $node, @@ -126,6 +126,10 @@ public function refactor(Node $node): ?Node $paramName ); + if (! $hasParamTypeChanged) { + continue; + } + $hasChanged = true; } From 51bf260e9e2efe9660af94d248d6b7ea482b7cd9 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 30 Sep 2025 20:11:31 +0700 Subject: [PATCH 5/5] Update rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php Co-authored-by: Tomas Votruba --- ...ParamArrayDocblockFromAssignsParamToParamReferenceRector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php index 63b48c40487..1805942e693 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromAssignsParamToParamReferenceRector.php @@ -103,7 +103,7 @@ public function refactor(Node $node): ?Node $paramTagValueNode = $phpDocInfo->getParamTagValueByName($paramName); // already defined, lets skip it - if ($paramTagValueNode instanceof ParamTagValueNode && $this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag( + if ($this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag( $paramTagValueNode )) { continue;