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; + } +} + +?> diff --git a/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php b/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php index c24b5de0cf5..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 ) { } @@ -94,9 +89,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; } @@ -115,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) { 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); }