mirror of https://github.com/rectorphp/rector.git
95 lines
3.9 KiB
PHP
95 lines
3.9 KiB
PHP
<?php
|
|
|
|
declare (strict_types=1);
|
|
namespace Rector\StaticTypeMapper;
|
|
|
|
use PhpParser\Node;
|
|
use PhpParser\Node\ComplexType;
|
|
use PhpParser\Node\Identifier;
|
|
use PhpParser\Node\Name;
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\ThrowsTagValueNode;
|
|
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
|
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
|
use PHPStan\Type\MixedType;
|
|
use PHPStan\Type\Type;
|
|
use Rector\Exception\NotImplementedYetException;
|
|
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
|
|
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
|
|
use Rector\StaticTypeMapper\Mapper\PhpParserNodeMapper;
|
|
use Rector\StaticTypeMapper\Naming\NameScopeFactory;
|
|
use Rector\StaticTypeMapper\PhpDoc\PhpDocTypeMapper;
|
|
/**
|
|
* Maps PhpParser <=> PHPStan <=> PHPStan doc <=> string type nodes between all possible formats
|
|
* @see \Rector\Tests\NodeTypeResolver\StaticTypeMapper\StaticTypeMapperTest
|
|
*/
|
|
final class StaticTypeMapper
|
|
{
|
|
/**
|
|
* @readonly
|
|
* @var \Rector\StaticTypeMapper\Naming\NameScopeFactory
|
|
*/
|
|
private $nameScopeFactory;
|
|
/**
|
|
* @readonly
|
|
* @var \Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper
|
|
*/
|
|
private $phpStanStaticTypeMapper;
|
|
/**
|
|
* @readonly
|
|
* @var \Rector\StaticTypeMapper\PhpDoc\PhpDocTypeMapper
|
|
*/
|
|
private $phpDocTypeMapper;
|
|
/**
|
|
* @readonly
|
|
* @var \Rector\StaticTypeMapper\Mapper\PhpParserNodeMapper
|
|
*/
|
|
private $phpParserNodeMapper;
|
|
public function __construct(NameScopeFactory $nameScopeFactory, PHPStanStaticTypeMapper $phpStanStaticTypeMapper, PhpDocTypeMapper $phpDocTypeMapper, PhpParserNodeMapper $phpParserNodeMapper)
|
|
{
|
|
$this->nameScopeFactory = $nameScopeFactory;
|
|
$this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper;
|
|
$this->phpDocTypeMapper = $phpDocTypeMapper;
|
|
$this->phpParserNodeMapper = $phpParserNodeMapper;
|
|
}
|
|
public function mapPHPStanTypeToPHPStanPhpDocTypeNode(Type $phpStanType) : TypeNode
|
|
{
|
|
return $this->phpStanStaticTypeMapper->mapToPHPStanPhpDocTypeNode($phpStanType);
|
|
}
|
|
/**
|
|
* @param TypeKind::* $typeKind
|
|
* @return Name|ComplexType|Identifier|null
|
|
*/
|
|
public function mapPHPStanTypeToPhpParserNode(Type $phpStanType, string $typeKind) : ?Node
|
|
{
|
|
return $this->phpStanStaticTypeMapper->mapToPhpParserNode($phpStanType, $typeKind);
|
|
}
|
|
public function mapPhpParserNodePHPStanType(Node $node) : Type
|
|
{
|
|
return $this->phpParserNodeMapper->mapToPHPStanType($node);
|
|
}
|
|
public function mapPHPStanPhpDocTypeToPHPStanType(PhpDocTagValueNode $phpDocTagValueNode, Node $node) : Type
|
|
{
|
|
if ($phpDocTagValueNode instanceof TemplateTagValueNode) {
|
|
// special case
|
|
if (!$phpDocTagValueNode->bound instanceof TypeNode) {
|
|
return new MixedType();
|
|
}
|
|
$nameScope = $this->nameScopeFactory->createNameScopeFromNodeWithoutTemplateTypes($node);
|
|
return $this->phpDocTypeMapper->mapToPHPStanType($phpDocTagValueNode->bound, $node, $nameScope);
|
|
}
|
|
if ($phpDocTagValueNode instanceof ReturnTagValueNode || $phpDocTagValueNode instanceof ParamTagValueNode || $phpDocTagValueNode instanceof VarTagValueNode || $phpDocTagValueNode instanceof ThrowsTagValueNode) {
|
|
return $this->mapPHPStanPhpDocTypeNodeToPHPStanType($phpDocTagValueNode->type, $node);
|
|
}
|
|
throw new NotImplementedYetException(__METHOD__ . ' for ' . \get_class($phpDocTagValueNode));
|
|
}
|
|
public function mapPHPStanPhpDocTypeNodeToPHPStanType(TypeNode $typeNode, Node $node) : Type
|
|
{
|
|
$nameScope = $this->nameScopeFactory->createNameScopeFromNode($node);
|
|
return $this->phpDocTypeMapper->mapToPHPStanType($typeNode, $node, $nameScope);
|
|
}
|
|
}
|