diff --git a/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForCommonObjectDenominatorRector/Fixture/with_string_key.php.inc b/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForCommonObjectDenominatorRector/Fixture/with_string_key.php.inc new file mode 100644 index 00000000000..fc6e7ecd09d --- /dev/null +++ b/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForCommonObjectDenominatorRector/Fixture/with_string_key.php.inc @@ -0,0 +1,42 @@ + new FirstExtension(), + 'b' => new SecondExtension() + ]; + } +} + +?> +----- + + */ + public function getExtensions(): array + { + return [ + 'a' => new FirstExtension(), + 'b' => new SecondExtension() + ]; + } +} + +?> diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForCommonObjectDenominatorRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForCommonObjectDenominatorRector.php index b699c423dbc..b12e0b160d4 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForCommonObjectDenominatorRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForCommonObjectDenominatorRector.php @@ -12,7 +12,11 @@ use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\ArrayType; use PHPStan\Type\Constant\ConstantArrayType; +use PHPStan\Type\IntegerType; use PHPStan\Type\MixedType; +use PHPStan\Type\StringType; +use PHPStan\Type\Type; +use PHPStan\Type\UnionType; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger; use Rector\Rector\AbstractRector; @@ -30,7 +34,7 @@ public function __construct( private readonly PhpDocInfoFactory $phpDocInfoFactory, private readonly ReturnNodeFinder $returnNodeFinder, private readonly ReflectionProvider $reflectionProvider, - private readonly PhpDocTypeChanger $phpDocTypeChanger, + private readonly PhpDocTypeChanger $phpDocTypeChanger ) { } @@ -167,7 +171,10 @@ public function refactor(Node $node): ?Node return null; } - $objectTypeArrayType = new ArrayType(new MixedType(), new FullyQualifiedObjectType($firstSharedType)); + $objectTypeArrayType = new ArrayType( + $this->resolveKeyType($returnedType), + new FullyQualifiedObjectType($firstSharedType) + ); $hasChanged = $this->phpDocTypeChanger->changeReturnType($node, $phpDocInfo, $objectTypeArrayType); if (! $hasChanged) { return null; @@ -176,6 +183,36 @@ public function refactor(Node $node): ?Node return $node; } + /** + * @return UnionType|IntegerType|StringType|MixedType + */ + private function resolveKeyType(ConstantArrayType $constantArrayType): Type + { + $keyType = $constantArrayType->getKeyType(); + + if ($keyType instanceof UnionType) { + $types = []; + foreach ($keyType->getTypes() as $type) { + if ($type->isString()->yes()) { + $types[] = new StringType(); + } elseif ($type->isInteger()->yes()) { + $types[] = new IntegerType(); + } else { + return new MixedType(); + } + } + + $uniqueKeyTypes = array_unique($types, SORT_REGULAR); + if (count($uniqueKeyTypes) === 1) { + return $uniqueKeyTypes[0]; + } + + return new UnionType($uniqueKeyTypes); + } + + return new MixedType(); + } + /** * @return string[] */