rector/packages/phpstan-static-type-mapper/src/TypeMapper/ObjectTypeMapper.php

146 lines
4.6 KiB
PHP
Raw Normal View History

2020-01-14 17:59:15 +00:00
<?php
declare(strict_types=1);
namespace Rector\PHPStanStaticTypeMapper\TypeMapper;
use Nette\Utils\Strings;
2020-01-14 17:59:15 +00:00
use PhpParser\Node;
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Reflection\ReflectionProvider;
2020-01-14 17:59:15 +00:00
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
2020-01-15 02:16:22 +00:00
use PHPStan\Type\VerbosityLevel;
use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareGenericTypeNode;
use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareIdentifierTypeNode;
use Rector\PHPStanStaticTypeMapper\Contract\PHPStanStaticTypeMapperAwareInterface;
2020-01-14 17:59:15 +00:00
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
use Rector\StaticTypeMapper\ValueObject\Type\AliasedObjectType;
use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType;
use Rector\StaticTypeMapper\ValueObject\Type\SelfObjectType;
use Rector\StaticTypeMapper\ValueObject\Type\ShortenedObjectType;
2020-01-14 17:59:15 +00:00
final class ObjectTypeMapper implements TypeMapperInterface, PHPStanStaticTypeMapperAwareInterface
2020-01-14 17:59:15 +00:00
{
/**
* @var PHPStanStaticTypeMapper
*/
private $phpStanStaticTypeMapper;
/**
* @var ReflectionProvider
*/
private $reflectionProvider;
public function __construct(ReflectionProvider $reflectionProvider)
{
$this->reflectionProvider = $reflectionProvider;
}
2020-01-14 17:59:15 +00:00
public function getNodeClass(): string
{
return ObjectType::class;
}
/**
* @param ObjectType $type
*/
public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode
{
2020-02-02 18:15:36 +00:00
if ($type instanceof ShortenedObjectType) {
return new AttributeAwareIdentifierTypeNode($type->getClassName());
2020-02-02 18:15:36 +00:00
}
if ($type instanceof AliasedObjectType) {
return new AttributeAwareIdentifierTypeNode($type->getClassName());
2020-02-02 18:15:36 +00:00
}
if ($type instanceof GenericObjectType) {
if (Strings::contains($type->getClassName(), '\\')) {
$name = '\\' . $type->getClassName();
} else {
$name = $type->getClassName();
}
$identifierTypeNode = new IdentifierTypeNode($name);
$genericTypeNodes = [];
foreach ($type->getTypes() as $genericType) {
$typeNode = $this->phpStanStaticTypeMapper->mapToPHPStanPhpDocTypeNode($genericType);
$genericTypeNodes[] = $typeNode;
}
return new AttributeAwareGenericTypeNode($identifierTypeNode, $genericTypeNodes);
}
return new AttributeAwareIdentifierTypeNode('\\' . $type->getClassName());
2020-01-14 17:59:15 +00:00
}
/**
* @param ObjectType $type
*/
public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node
{
2020-01-15 02:16:22 +00:00
if ($type instanceof SelfObjectType) {
2020-05-10 21:02:46 +00:00
return new Name('self');
2020-01-15 02:16:22 +00:00
}
2020-01-14 17:59:15 +00:00
if ($type instanceof ShortenedObjectType) {
return new FullyQualified($type->getFullyQualifiedName());
}
if ($type instanceof AliasedObjectType) {
return new Name($type->getClassName());
}
if ($type instanceof FullyQualifiedObjectType) {
return new FullyQualified($type->getClassName());
}
if (! $type instanceof GenericObjectType) {
// fallback
return new FullyQualified($type->getClassName());
2020-01-14 17:59:15 +00:00
}
if ($type->getClassName() !== 'object') {
// fallback
return new FullyQualified($type->getClassName());
}
return new Name('object');
2020-01-14 17:59:15 +00:00
}
2020-01-15 02:16:22 +00:00
/**
* @param ObjectType $type
*/
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
if ($type instanceof AliasedObjectType) {
// no preslash for alias
return $type->getClassName();
}
if ($type instanceof ShortenedObjectType) {
return '\\' . $type->getFullyQualifiedName();
}
if ($type instanceof FullyQualifiedObjectType) {
// always prefixed with \\
return '\\' . $type->getClassName();
}
if ($this->reflectionProvider->hasClass($type->getClassName())) {
2020-01-15 02:16:22 +00:00
// FQN by default
return '\\' . $type->describe(VerbosityLevel::typeOnly());
}
return $type->getClassName();
}
public function setPHPStanStaticTypeMapper(PHPStanStaticTypeMapper $phpStanStaticTypeMapper): void
{
$this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper;
}
2020-01-14 17:59:15 +00:00
}