rector/packages/PHPStanStaticTypeMapper/TypeMapper/ArrayShapeTypeMapper.php

60 lines
2.2 KiB
PHP

<?php
declare (strict_types=1);
namespace Rector\PHPStanStaticTypeMapper\TypeMapper;
use PHPStan\PhpDocParser\Ast\Type\ArrayShapeItemNode;
use PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\ArrayType;
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\Constant\ConstantStringType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NeverType;
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
final class ArrayShapeTypeMapper
{
/**
* @readonly
* @var \Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper
*/
private $phpStanStaticTypeMapper;
/**
* @readonly
* @var \PHPStan\Reflection\ReflectionProvider
*/
private $reflectionProvider;
public function __construct(PHPStanStaticTypeMapper $phpStanStaticTypeMapper, ReflectionProvider $reflectionProvider)
{
$this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper;
$this->reflectionProvider = $reflectionProvider;
}
/**
* @return \PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode|\PHPStan\Type\ArrayType|null
*/
public function mapConstantArrayType(ConstantArrayType $constantArrayType)
{
// empty array
if ($constantArrayType->getKeyType() instanceof NeverType) {
return new ArrayType(new MixedType(), new MixedType());
}
$arrayShapeItemNodes = [];
foreach ($constantArrayType->getKeyTypes() as $index => $keyType) {
// not real array shape
if (!$keyType instanceof ConstantStringType) {
return null;
}
$keyValue = $keyType->getValue();
if ($this->reflectionProvider->hasClass($keyValue)) {
return null;
}
$keyDocTypeNode = new IdentifierTypeNode($keyValue);
$valueType = $constantArrayType->getValueTypes()[$index];
$valueDocTypeNode = $this->phpStanStaticTypeMapper->mapToPHPStanPhpDocTypeNode($valueType);
$arrayShapeItemNodes[] = new ArrayShapeItemNode($keyDocTypeNode, $constantArrayType->isOptionalKey($index), $valueDocTypeNode);
}
return new ArrayShapeNode($arrayShapeItemNodes);
}
}