From e93e9ccfde85b801bce6e2ea84753b3a375efc73 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 13 Oct 2025 13:59:37 +0200 Subject: [PATCH 1/3] add return fixture to mimic var int key --- .../Fixture/respect_int_string_key.php.inc | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector/Fixture/respect_int_string_key.php.inc diff --git a/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector/Fixture/respect_int_string_key.php.inc b/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector/Fixture/respect_int_string_key.php.inc new file mode 100644 index 00000000000..f647df2a06c --- /dev/null +++ b/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector/Fixture/respect_int_string_key.php.inc @@ -0,0 +1,43 @@ + + */ + private array $names = []; + + /** + * @return array + */ + public function getNames(): array + { + return $this->names; + } +} + +?> +----- + + */ + private array $names = []; + + /** + * @return array + */ + public function getNames(): array + { + return $this->names; + } +} + +?> From cfab7c9233a401e4b29c2809f5074b3dbe21525d Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 13 Oct 2025 14:18:07 +0200 Subject: [PATCH 2/3] keep int keys in already known array shapes in DocblockGetterReturnArrayFromPropertyDocblockVarRector --- .../Fixture/add_prefix_backslash.php.inc | 2 +- .../NodeDocblockTypeDecorator.php | 31 +++-- ...turnArrayFromPropertyDocblockVarRector.php | 115 ++++++++++++------ ...ArrayDocblockParamFromLocalCallsRector.php | 1 + .../PhpDocManipulator/PhpDocTypeChanger.php | 4 + .../TypeMapper/ArrayTypeMapper.php | 13 +- 6 files changed, 118 insertions(+), 48 deletions(-) diff --git a/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector/Fixture/add_prefix_backslash.php.inc b/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector/Fixture/add_prefix_backslash.php.inc index 76a5ed639c9..68ac1f1a894 100644 --- a/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector/Fixture/add_prefix_backslash.php.inc +++ b/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector/Fixture/add_prefix_backslash.php.inc @@ -43,7 +43,7 @@ class AddPrefixBackslash extends LogicException } /** - * @return array[]> + * @return array>> */ public function getDuplicateNames(): array { diff --git a/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php b/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php index 6e552bf8ba7..a6280dc8f61 100644 --- a/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php +++ b/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php @@ -43,7 +43,7 @@ public function decorateGenericIterableParamType( $typeNode = $this->createTypeNode($type); - // no value iterable type + // no value iterable typeOrTypeNode if ($typeNode instanceof IdentifierTypeNode) { return false; } @@ -54,18 +54,28 @@ public function decorateGenericIterableParamType( } public function decorateGenericIterableReturnType( - Type $type, - PhpDocInfo $classMethodPhpDocInfo, - FunctionLike $functionLike + Type|TypeNode $typeOrTypeNode, + PhpDocInfo $classMethodPhpDocInfo, + FunctionLike $functionLike ): bool { + if ($typeOrTypeNode instanceof TypeNode) { + $type = $this->staticTypeMapper->mapPHPStanPhpDocTypeNodeToPHPStanType($typeOrTypeNode, $functionLike); + } else { + $type = $typeOrTypeNode; + } + if ($this->isBareMixedType($type)) { // no value return false; } - $typeNode = $this->createTypeNode($type); + if ($typeOrTypeNode instanceof TypeNode) { + $typeNode = $typeOrTypeNode; + } else { + $typeNode = $this->createTypeNode($typeOrTypeNode); + } - // no value iterable type + // no value iterable typeOrTypeNode if ($typeNode instanceof IdentifierTypeNode) { return false; } @@ -84,7 +94,7 @@ public function decorateGenericIterableVarType(Type $type, PhpDocInfo $phpDocInf return false; } - // no value iterable type + // no value iterable typeOrTypeNode if ($typeNode instanceof IdentifierTypeNode) { return false; } @@ -96,11 +106,10 @@ public function decorateGenericIterableVarType(Type $type, PhpDocInfo $phpDocInf private function createTypeNode(Type $type): TypeNode { - $generalizedReturnType = $this->typeNormalizer->generalizeConstantTypes($type); - - // turn into rather generic short return type, to keep it open to extension later and readable to human - $typeNode = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($generalizedReturnType); + $generalizedType = $this->typeNormalizer->generalizeConstantTypes($type); + // turn into rather generic short return typeOrTypeNode, to keep it open to extension later and readable to human + $typeNode = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($generalizedType); if ($typeNode instanceof IdentifierTypeNode && $typeNode->name === 'mixed') { return new ArrayTypeNode($typeNode); } diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector.php index 195b15ab5c7..0e8fac1343b 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector.php @@ -4,6 +4,12 @@ namespace Rector\TypeDeclarationDocblocks\Rector\ClassMethod; +use PhpParser\Node\Stmt\Class_; +use PhpParser\Node\Stmt\Property; +use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode; +use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode; +use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode; +use PHPStan\Type\Type; use PhpParser\Node; use PhpParser\Node\Expr\PropertyFetch; use PhpParser\Node\Stmt\ClassMethod; @@ -30,9 +36,12 @@ public function __construct( ) { } + /** + * @return array> + */ public function getNodeTypes(): array { - return [ClassMethod::class]; + return [Class_::class]; } public function getRuleDefinition(): RuleDefinition @@ -76,53 +85,67 @@ public function getItems(): array } /** - * @param ClassMethod $node + * @param Class_ $node */ public function refactor(Node $node): ?Node { - if (! $node->returnType instanceof Node) { - return null; - } - - if (! $this->isName($node->returnType, 'array')) { - return null; - } - - $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node); - - if ($this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag($phpDocInfo->getReturnTagValue())) { - return null; - } - - $propertyFetch = $this->matchReturnLocalPropertyFetch($node); - if (! $propertyFetch instanceof PropertyFetch) { - return null; - } - - $propertyFetchType = $this->getType($propertyFetch); - if ($propertyFetchType instanceof ArrayType - && $propertyFetchType->getKeyType() instanceof MixedType - && $propertyFetchType->getItemType() instanceof MixedType - ) { + if ($node->isAnonymous()) { return null; } - if ($propertyFetchType instanceof UnionType) { - return null; + $hasChanged = false; + foreach ($node->getMethods() as $classMethod) { + if (! $classMethod->returnType instanceof Node) { + continue; + } + + if (! $this->isName($classMethod->returnType, 'array')) { + continue; + } + + $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod); + if ($this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag($phpDocInfo->getReturnTagValue())) { + continue; + } + + // @todo add promoted proeprty + $property = $this->matchReturnLocalPropertyFetch($classMethod, $node); + if (! $property instanceof Property) { + continue; + } + + $propertyDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property); + + $varTagValueNode = $propertyDocInfo->getVarTagValueNode(); + + if (! $varTagValueNode instanceof VarTagValueNode) { + continue; + } + + // is type useful? + if (! $varTagValueNode->type instanceof GenericTypeNode && ! $varTagValueNode->type instanceof ArrayTypeNode) { + continue; + } + + if (! $this->nodeDocblockTypeDecorator->decorateGenericIterableReturnType( + $varTagValueNode->type, + $phpDocInfo, + $classMethod + )) { + continue; + } + + $hasChanged = true; } - if (! $this->nodeDocblockTypeDecorator->decorateGenericIterableReturnType( - $propertyFetchType, - $phpDocInfo, - $node - )) { + if (! $hasChanged) { return null; } return $node; } - private function matchReturnLocalPropertyFetch(ClassMethod $classMethod): ?PropertyFetch + private function matchReturnLocalPropertyFetch(ClassMethod $classMethod, Class_ $class): ?Property { // we need exactly one statement of return if ($classMethod->stmts === null || count($classMethod->stmts) !== 1) { @@ -143,6 +166,28 @@ private function matchReturnLocalPropertyFetch(ClassMethod $classMethod): ?Prope return null; } - return $propertyFetch; + $propertyName = $this->getName($propertyFetch->name); + if (! is_string($propertyName)) { + return null; + } + + return $class->getProperty($propertyName); + } + + private function isUsefulType(Type $type): bool + { + if ($type instanceof UnionType) { + return false; + } + + if (! $type instanceof ArrayType) { + return true; + } + + if (! $type->getKeyType() instanceof MixedType) { + return true; + } + + return ! $type->getItemType() instanceof MixedType; } } diff --git a/rules/TypeDeclarationDocblocks/Rector/Class_/ClassMethodArrayDocblockParamFromLocalCallsRector.php b/rules/TypeDeclarationDocblocks/Rector/Class_/ClassMethodArrayDocblockParamFromLocalCallsRector.php index 3e1749681e2..5757210532b 100644 --- a/rules/TypeDeclarationDocblocks/Rector/Class_/ClassMethodArrayDocblockParamFromLocalCallsRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/Class_/ClassMethodArrayDocblockParamFromLocalCallsRector.php @@ -115,6 +115,7 @@ public function refactor(Node $node): ?Node } $resolvedParameterType = $classMethodParameterTypes[$parameterPosition] ?? $classMethodParameterTypes[$parameterName] ?? null; + if (! $resolvedParameterType instanceof Type) { continue; } diff --git a/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php b/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php index 4a4df6812cf..6b1f638df8c 100644 --- a/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php +++ b/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php @@ -28,6 +28,7 @@ use Rector\BetterPhpDocParser\ValueObject\Type\SpacingAwareArrayTypeNode; use Rector\BetterPhpDocParser\ValueObject\Type\SpacingAwareCallableTypeNode; use Rector\Comments\NodeDocBlock\DocBlockUpdater; +use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\NodeTypeResolver\TypeComparator\TypeComparator; use Rector\StaticTypeMapper\StaticTypeMapper; use Rector\TypeDeclaration\PhpDocParser\ParamPhpDocNodeFactory; @@ -104,6 +105,9 @@ public function changeReturnTypeNode( ): void { $existingReturnTagValueNode = $phpDocInfo->getReturnTagValue(); if ($existingReturnTagValueNode instanceof ReturnTagValueNode) { + // enforce reprint of copied type node + $newTypeNode->setAttribute('orig_node', null); + $existingReturnTagValueNode->type = $newTypeNode; } else { $returnTagValueNode = new ReturnTagValueNode($newTypeNode, ''); diff --git a/src/PHPStanStaticTypeMapper/TypeMapper/ArrayTypeMapper.php b/src/PHPStanStaticTypeMapper/TypeMapper/ArrayTypeMapper.php index 38349e2e2bf..4b1d91f49a3 100644 --- a/src/PHPStanStaticTypeMapper/TypeMapper/ArrayTypeMapper.php +++ b/src/PHPStanStaticTypeMapper/TypeMapper/ArrayTypeMapper.php @@ -13,6 +13,7 @@ use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\Constant\ConstantIntegerType; use PHPStan\Type\Generic\GenericClassStringType; +use PHPStan\Type\IntegerType; use PHPStan\Type\MixedType; use PHPStan\Type\NeverType; use PHPStan\Type\Type; @@ -75,7 +76,6 @@ public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode } if ($itemType instanceof ArrayType && $this->isGenericArrayCandidate($itemType)) { - return $this->createGenericArrayType($type, true); } @@ -83,6 +83,17 @@ public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode return $this->createGenericArrayType($type, true); } + // keep "int" key in arary + if ($type->getKeyType() instanceof IntegerType) { + $keyTypeNode = $this->phpStanStaticTypeMapper->mapToPHPStanPhpDocTypeNode($type->getKeyType()); + + if (! $type->isList()->maybe()) { + $nestedTypeNode = $this->phpStanStaticTypeMapper->mapToPHPStanPhpDocTypeNode($type->getItemType()); + + return new GenericTypeNode(new IdentifierTypeNode('array'), [$keyTypeNode, $nestedTypeNode]); + } + } + $itemTypeNode = $this->phpStanStaticTypeMapper->mapToPHPStanPhpDocTypeNode($itemType); return new SpacingAwareArrayTypeNode($itemTypeNode); } From 8bbfa6b97521b8c8de2699beb5a9c69deed66b37 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 13 Oct 2025 16:03:10 +0200 Subject: [PATCH 3/3] fix promoted property --- .../Fixture/add_prefix_backslash.php.inc | 2 +- .../NodeDocblockTypeDecorator.php | 10 +-- .../GetterClassMethodPropertyFinder.php | 74 +++++++++++++++++++ ...turnArrayFromPropertyDocblockVarRector.php | 67 ++--------------- .../PhpDocManipulator/PhpDocTypeChanger.php | 1 - 5 files changed, 87 insertions(+), 67 deletions(-) create mode 100644 rules/TypeDeclarationDocblocks/NodeFinder/GetterClassMethodPropertyFinder.php diff --git a/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector/Fixture/add_prefix_backslash.php.inc b/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector/Fixture/add_prefix_backslash.php.inc index 68ac1f1a894..9df08812ee7 100644 --- a/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector/Fixture/add_prefix_backslash.php.inc +++ b/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector/Fixture/add_prefix_backslash.php.inc @@ -43,7 +43,7 @@ class AddPrefixBackslash extends LogicException } /** - * @return array>> + * @return array>> */ public function getDuplicateNames(): array { diff --git a/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php b/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php index a6280dc8f61..1f626242910 100644 --- a/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php +++ b/rules/TypeDeclarationDocblocks/NodeDocblockTypeDecorator.php @@ -43,7 +43,7 @@ public function decorateGenericIterableParamType( $typeNode = $this->createTypeNode($type); - // no value iterable typeOrTypeNode + // no value iterable type if ($typeNode instanceof IdentifierTypeNode) { return false; } @@ -55,8 +55,8 @@ public function decorateGenericIterableParamType( public function decorateGenericIterableReturnType( Type|TypeNode $typeOrTypeNode, - PhpDocInfo $classMethodPhpDocInfo, - FunctionLike $functionLike + PhpDocInfo $classMethodPhpDocInfo, + FunctionLike $functionLike ): bool { if ($typeOrTypeNode instanceof TypeNode) { $type = $this->staticTypeMapper->mapPHPStanPhpDocTypeNodeToPHPStanType($typeOrTypeNode, $functionLike); @@ -75,7 +75,7 @@ public function decorateGenericIterableReturnType( $typeNode = $this->createTypeNode($typeOrTypeNode); } - // no value iterable typeOrTypeNode + // no value iterable type if ($typeNode instanceof IdentifierTypeNode) { return false; } @@ -94,7 +94,7 @@ public function decorateGenericIterableVarType(Type $type, PhpDocInfo $phpDocInf return false; } - // no value iterable typeOrTypeNode + // no value iterable type if ($typeNode instanceof IdentifierTypeNode) { return false; } diff --git a/rules/TypeDeclarationDocblocks/NodeFinder/GetterClassMethodPropertyFinder.php b/rules/TypeDeclarationDocblocks/NodeFinder/GetterClassMethodPropertyFinder.php new file mode 100644 index 00000000000..c1ddfefe86a --- /dev/null +++ b/rules/TypeDeclarationDocblocks/NodeFinder/GetterClassMethodPropertyFinder.php @@ -0,0 +1,74 @@ +stmts === null || count($classMethod->stmts) !== 1) { + return null; + } + + $onlyStmt = $classMethod->stmts[0]; + if (! $onlyStmt instanceof Return_) { + return null; + } + + if (! $onlyStmt->expr instanceof PropertyFetch) { + return null; + } + + $propertyFetch = $onlyStmt->expr; + if (! $this->nodeNameResolver->isName($propertyFetch->var, 'this')) { + return null; + } + + $propertyName = $this->nodeNameResolver->getName($propertyFetch->name); + if (! is_string($propertyName)) { + return null; + } + + $property = $class->getProperty($propertyName); + if ($property instanceof Property) { + return $property; + } + + // try also promoted property in constructor + $constructClassMethod = $class->getMethod(MethodName::CONSTRUCT); + if (! $constructClassMethod instanceof ClassMethod) { + return null; + } + + foreach ($constructClassMethod->getParams() as $param) { + if (! $param->isPromoted()) { + continue; + } + + if (! $this->nodeNameResolver->isName($param, $propertyName)) { + continue; + } + + return $param; + } + + return null; + } +} diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector.php index 0e8fac1343b..fc2a1dd214e 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector.php @@ -4,22 +4,15 @@ namespace Rector\TypeDeclarationDocblocks\Rector\ClassMethod; +use PhpParser\Node; use PhpParser\Node\Stmt\Class_; -use PhpParser\Node\Stmt\Property; use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode; use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode; use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode; -use PHPStan\Type\Type; -use PhpParser\Node; -use PhpParser\Node\Expr\PropertyFetch; -use PhpParser\Node\Stmt\ClassMethod; -use PhpParser\Node\Stmt\Return_; -use PHPStan\Type\ArrayType; -use PHPStan\Type\MixedType; -use PHPStan\Type\UnionType; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; use Rector\Rector\AbstractRector; use Rector\TypeDeclarationDocblocks\NodeDocblockTypeDecorator; +use Rector\TypeDeclarationDocblocks\NodeFinder\GetterClassMethodPropertyFinder; use Rector\TypeDeclarationDocblocks\TagNodeAnalyzer\UsefulArrayTagNodeAnalyzer; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -32,7 +25,8 @@ final class DocblockGetterReturnArrayFromPropertyDocblockVarRector extends Abstr public function __construct( private readonly PhpDocInfoFactory $phpDocInfoFactory, private readonly UsefulArrayTagNodeAnalyzer $usefulArrayTagNodeAnalyzer, - private readonly NodeDocblockTypeDecorator $nodeDocblockTypeDecorator + private readonly NodeDocblockTypeDecorator $nodeDocblockTypeDecorator, + private readonly GetterClassMethodPropertyFinder $getterClassMethodPropertyFinder, ) { } @@ -108,13 +102,12 @@ public function refactor(Node $node): ?Node continue; } - // @todo add promoted proeprty - $property = $this->matchReturnLocalPropertyFetch($classMethod, $node); - if (! $property instanceof Property) { + $propertyOrParam = $this->getterClassMethodPropertyFinder->find($classMethod, $node); + if (! $propertyOrParam instanceof Node) { continue; } - $propertyDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property); + $propertyDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($propertyOrParam); $varTagValueNode = $propertyDocInfo->getVarTagValueNode(); @@ -144,50 +137,4 @@ public function refactor(Node $node): ?Node return $node; } - - private function matchReturnLocalPropertyFetch(ClassMethod $classMethod, Class_ $class): ?Property - { - // we need exactly one statement of return - if ($classMethod->stmts === null || count($classMethod->stmts) !== 1) { - return null; - } - - $onlyStmt = $classMethod->stmts[0]; - if (! $onlyStmt instanceof Return_) { - return null; - } - - if (! $onlyStmt->expr instanceof PropertyFetch) { - return null; - } - - $propertyFetch = $onlyStmt->expr; - if (! $this->isName($propertyFetch->var, 'this')) { - return null; - } - - $propertyName = $this->getName($propertyFetch->name); - if (! is_string($propertyName)) { - return null; - } - - return $class->getProperty($propertyName); - } - - private function isUsefulType(Type $type): bool - { - if ($type instanceof UnionType) { - return false; - } - - if (! $type instanceof ArrayType) { - return true; - } - - if (! $type->getKeyType() instanceof MixedType) { - return true; - } - - return ! $type->getItemType() instanceof MixedType; - } } diff --git a/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php b/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php index 6b1f638df8c..f5ec4ac1410 100644 --- a/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php +++ b/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php @@ -28,7 +28,6 @@ use Rector\BetterPhpDocParser\ValueObject\Type\SpacingAwareArrayTypeNode; use Rector\BetterPhpDocParser\ValueObject\Type\SpacingAwareCallableTypeNode; use Rector\Comments\NodeDocBlock\DocBlockUpdater; -use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\NodeTypeResolver\TypeComparator\TypeComparator; use Rector\StaticTypeMapper\StaticTypeMapper; use Rector\TypeDeclaration\PhpDocParser\ParamPhpDocNodeFactory;