Remove mapToDocString() and use describe() instead (#6095)

This commit is contained in:
Tomas Votruba 2021-04-11 01:28:08 +02:00 committed by GitHub
parent c4870c4a8d
commit b121d8e10a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 134 additions and 410 deletions

View File

@ -372,7 +372,6 @@ final class PhpDocInfo
foreach ($this->phpDocNode->getParamTagValues() as $paramTagValueNode) {
$parameterName = $paramTagValueNode->parameterName;
$paramTypesByName[$parameterName] = $this->staticTypeMapper->mapPHPStanPhpDocTypeToPHPStanType(
$paramTagValueNode,
$this->node

View File

@ -13,7 +13,6 @@ use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\BinaryOp;
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\PropertyFetch;
@ -178,16 +177,6 @@ final class NodeRepository
return $this->functionsByName[$name] ?? null;
}
public function findFunctionByFuncCall(FuncCall $funcCall): ?Function_
{
$functionName = $this->nodeNameResolver->getName($funcCall);
if ($functionName === null) {
return null;
}
return $this->findFunction($functionName);
}
/**
* @return array<string, MethodCall[]|StaticCall[]>
*/

View File

@ -260,7 +260,6 @@ final class NodeNameResolver
/**
* @param mixed[] $backtrace
* @return mixed[]|null
*/
private function matchRectorBacktraceCall(array $backtrace): ?array
{

View File

@ -170,6 +170,7 @@ final class NodeTypeResolver
}
$scope = $node->getAttribute(AttributeKey::SCOPE);
if (! $scope instanceof Scope) {
if ($node instanceof ConstFetch && $node->name instanceof Name) {
$name = (string) $node->name;

View File

@ -5,29 +5,22 @@ declare(strict_types=1);
namespace Rector\NodeTypeResolver\PHPStan;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\ConstantType;
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeTraverser;
use PHPStan\Type\TypeWithClassName;
use PHPStan\Type\UnionType;
use PHPStan\Type\UnionTypeHelper;
use PHPStan\Type\VerbosityLevel;
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
use Rector\StaticTypeMapper\ValueObject\Type\AliasedObjectType;
use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType;
use Rector\StaticTypeMapper\ValueObject\Type\ShortenedObjectType;
final class TypeHasher
{
/**
* @var PHPStanStaticTypeMapper
*/
private $phpStanStaticTypeMapper;
public function __construct(PHPStanStaticTypeMapper $phpStanStaticTypeMapper)
{
$this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper;
}
public function areTypesEqual(Type $firstType, Type $secondType): bool
{
return $this->createTypeHash($firstType) === $this->createTypeHash($secondType);
@ -45,7 +38,6 @@ final class TypeHasher
if ($type instanceof GenericObjectType) {
return $type->describe(VerbosityLevel::precise());
// return $this->phpStanStaticTypeMapper->mapToDocString($type);
}
if ($type instanceof TypeWithClassName) {
@ -60,7 +52,7 @@ final class TypeHasher
return $this->createUnionTypeHash($type);
}
return $this->phpStanStaticTypeMapper->mapToDocString($type);
return $type->describe(VerbosityLevel::value());
}
private function resolveUniqueTypeWithClassNameHash(TypeWithClassName $typeWithClassName): string
@ -78,14 +70,23 @@ final class TypeHasher
private function createUnionTypeHash(UnionType $unionType): string
{
$unionedTypesHashes = [];
foreach ($unionType->getTypes() as $unionedType) {
$unionedTypesHashes[] = $this->createTypeHash($unionedType);
$sortedTypes = UnionTypeHelper::sortTypes($unionType->getTypes());
$sortedUnionType = new UnionType($sortedTypes);
$booleanType = new BooleanType();
if ($booleanType->isSuperTypeOf($unionType)->yes()) {
return $booleanType->describe(VerbosityLevel::precise());
}
sort($unionedTypesHashes);
$unionedTypesHashes = array_unique($unionedTypesHashes);
// change alias to non-alias
$sortedUnionType = TypeTraverser::map($sortedUnionType, function (Type $type, callable $callable): Type {
if (! $type instanceof AliasedObjectType) {
return $callable($type);
}
return implode('|', $unionedTypesHashes);
return new FullyQualifiedObjectType($type->getFullyQualifiedClass());
});
return $sortedUnionType->describe(VerbosityLevel::cache());
}
}

View File

@ -7,11 +7,14 @@ namespace Rector\NodeTypeResolver\TypeComparator;
use PhpParser\Node;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\Constant\ConstantBooleanType;
use PHPStan\Type\Generic\GenericClassStringType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeTraverser;
use PHPStan\Type\UnionType;
use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory;
use Rector\NodeTypeResolver\PHPStan\TypeHasher;
@ -104,6 +107,10 @@ final class TypeComparator
$node
);
// normalize bool union types
$phpParserNodeType = $this->normalizeConstantBooleanType($phpParserNodeType);
$phpStanDocType = $this->normalizeConstantBooleanType($phpStanDocType);
return $this->areTypesEqual($phpParserNodeType, $phpStanDocType);
}
@ -229,4 +236,15 @@ final class TypeComparator
return $this->areTypesEqual($firstArrayType, $secondArrayType);
}
private function normalizeConstantBooleanType(Type $type): Type
{
return TypeTraverser::map($type, function (Type $type, callable $callable): Type {
if ($type instanceof ConstantBooleanType) {
return new BooleanType();
}
return $callable($type);
});
}
}

View File

@ -24,6 +24,4 @@ interface TypeMapperInterface
* @return Name|NullableType|UnionType|null
*/
public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node;
public function mapToDocString(Type $type, ?Type $parentType = null): string;
}

View File

@ -63,17 +63,4 @@ final class PHPStanStaticTypeMapper
throw new NotImplementedYetException(__METHOD__ . ' for ' . get_class($type));
}
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
foreach ($this->typeMappers as $typeMapper) {
if (! is_a($type, $typeMapper->getNodeClass(), true)) {
continue;
}
return $typeMapper->mapToDocString($type, $parentType);
}
throw new NotImplementedYetException(__METHOD__ . ' for ' . get_class($type));
}
}

View File

@ -26,7 +26,6 @@ use Rector\BetterPhpDocParser\ValueObject\Type\SpacingAwareArrayTypeNode;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
use Rector\PHPStanStaticTypeMapper\TypeAnalyzer\UnionTypeCommonTypeNarrower;
use Rector\TypeDeclaration\TypeNormalizer;
/**
* @see \Rector\PHPStanStaticTypeMapper\Tests\TypeMapper\ArrayTypeMapperTest
@ -43,11 +42,6 @@ final class ArrayTypeMapper implements TypeMapperInterface
*/
private $phpStanStaticTypeMapper;
/**
* @var TypeNormalizer
*/
private $typeNormalizer;
/**
* @var UnionTypeCommonTypeNarrower
*/
@ -64,12 +58,10 @@ final class ArrayTypeMapper implements TypeMapperInterface
*/
public function autowireArrayTypeMapper(
PHPStanStaticTypeMapper $phpStanStaticTypeMapper,
TypeNormalizer $typeNormalizer,
UnionTypeCommonTypeNarrower $unionTypeCommonTypeNarrower,
ReflectionProvider $reflectionProvider
): void {
$this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper;
$this->typeNormalizer = $typeNormalizer;
$this->unionTypeCommonTypeNarrower = $unionTypeCommonTypeNarrower;
$this->reflectionProvider = $reflectionProvider;
}
@ -119,21 +111,6 @@ final class ArrayTypeMapper implements TypeMapperInterface
return new Name('array');
}
/**
* @param ArrayType $type
*/
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
$itemType = $type->getItemType();
$normalizedType = $this->typeNormalizer->normalizeArrayOfUnionToUnionArray($type);
if ($normalizedType instanceof UnionType) {
return $this->mapArrayUnionTypeToDocString($type, $normalizedType);
}
return $this->phpStanStaticTypeMapper->mapToDocString($itemType, $parentType) . '[]';
}
private function createArrayTypeNodeFromUnionType(UnionType $unionType): ArrayTypeNode
{
$unionedArrayType = [];
@ -217,23 +194,6 @@ final class ArrayTypeMapper implements TypeMapperInterface
return new GenericTypeNode($identifierTypeNode, $genericTypes);
}
private function mapArrayUnionTypeToDocString(ArrayType $arrayType, UnionType $unionType): string
{
$unionedTypesAsString = [];
foreach ($unionType->getTypes() as $unionedArrayItemType) {
$unionedTypesAsString[] = $this->phpStanStaticTypeMapper->mapToDocString(
$unionedArrayItemType,
$arrayType
);
}
$unionedTypesAsString = array_values($unionedTypesAsString);
$unionedTypesAsString = array_unique($unionedTypesAsString);
return implode('|', $unionedTypesAsString);
}
private function isIntegerKeyAndNonNestedArray(ArrayType $arrayType): bool
{
if (! $arrayType->getKeyType() instanceof IntegerType) {

View File

@ -9,11 +9,11 @@ use PhpParser\Node\Name;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\BooleanType;
use PHPStan\Type\Constant\ConstantBooleanType;
use PHPStan\Type\Type;
use Rector\Core\Php\PhpVersionProvider;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\StaticTypeMapper\ValueObject\Type\FalseBooleanType;
final class BooleanTypeMapper implements TypeMapperInterface
{
@ -63,21 +63,13 @@ final class BooleanTypeMapper implements TypeMapperInterface
return new Name('bool');
}
/**
* @param BooleanType $type
*/
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
if ($this->isFalseBooleanTypeWithUnion($type)) {
return 'false';
}
return 'bool';
}
private function isFalseBooleanTypeWithUnion(Type $type): bool
{
if (! $type instanceof FalseBooleanType) {
if (! $type instanceof ConstantBooleanType) {
return false;
}
if ($type->getValue()) {
return false;
}

View File

@ -11,7 +11,6 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\CallableType;
use PHPStan\Type\ClosureType;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\BetterPhpDocParser\ValueObject\Type\SpacingAwareCallableTypeNode;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
@ -60,9 +59,4 @@ final class CallableTypeMapper implements TypeMapperInterface
return new Name('callable');
}
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return $type->describe(VerbosityLevel::typeOnly());
}
}

View File

@ -13,7 +13,6 @@ use PHPStan\Type\ClassStringType;
use PHPStan\Type\Generic\GenericClassStringType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\PHPStanStaticTypeMapper\Contract\PHPStanStaticTypeMapperAwareInterface;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
@ -63,14 +62,6 @@ final class ClassStringTypeMapper implements TypeMapperInterface, PHPStanStaticT
return null;
}
/**
* @param ClassStringType $type
*/
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return $type->describe(VerbosityLevel::typeOnly());
}
public function setPHPStanStaticTypeMapper(PHPStanStaticTypeMapper $phpStanStaticTypeMapper): void
{
$this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper;

View File

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Rector\PHPStanStaticTypeMapper\TypeMapper;
use Closure;
use PhpParser\Node;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
@ -60,11 +59,6 @@ final class ClosureTypeMapper implements TypeMapperInterface, PHPStanStaticTypeM
return $this->callableTypeMapper->mapToPhpParserNode($type, $kind);
}
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return '\\' . Closure::class;
}
public function setPHPStanStaticTypeMapper(PHPStanStaticTypeMapper $phpStanStaticTypeMapper): void
{
$this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper;

View File

@ -10,7 +10,6 @@ use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\FloatType;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\Core\Php\PhpVersionProvider;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
@ -54,9 +53,4 @@ final class FloatTypeMapper implements TypeMapperInterface
return new Name('float');
}
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return $type->describe(VerbosityLevel::typeOnly());
}
}

View File

@ -38,12 +38,4 @@ final class HasOffsetTypeMapper implements TypeMapperInterface
{
throw new ShouldNotHappenException();
}
/**
* @param HasOffsetType $type
*/
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return 'mixed[]';
}
}

View File

@ -10,7 +10,6 @@ use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\IntegerType;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\Core\Php\PhpVersionProvider;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
@ -54,9 +53,4 @@ final class IntegerTypeMapper implements TypeMapperInterface
return new Name('int');
}
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return $type->describe(VerbosityLevel::typeOnly());
}
}

View File

@ -59,22 +59,4 @@ final class IntersectionTypeMapper implements TypeMapperInterface
// intersection types in PHP are not yet supported
return null;
}
/**
* @param IntersectionType $type
*/
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
$stringTypes = [];
foreach ($type->getTypes() as $unionedType) {
$stringTypes[] = $this->phpStanStaticTypeMapper->mapToDocString($unionedType);
}
// remove empty values, e.g. void/iterable
$stringTypes = array_unique($stringTypes);
$stringTypes = array_filter($stringTypes);
return implode('&', $stringTypes);
}
}

View File

@ -11,11 +11,8 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode;
use PHPStan\Type\IterableType;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\BetterPhpDocParser\ValueObject\Type\BracketsAwareUnionTypeNode;
use Rector\BetterPhpDocParser\ValueObject\Type\SpacingAwareArrayTypeNode;
use Rector\Core\Php\PhpVersionProvider;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
@ -26,16 +23,6 @@ final class IterableTypeMapper implements TypeMapperInterface
*/
private $phpStanStaticTypeMapper;
/**
* @var PhpVersionProvider
*/
private $phpVersionProvider;
public function __construct(PhpVersionProvider $phpVersionProvider)
{
$this->phpVersionProvider = $phpVersionProvider;
}
/**
* @required
*/
@ -73,19 +60,6 @@ final class IterableTypeMapper implements TypeMapperInterface
return new Name('iterable');
}
/**
* @param IterableType $type
*/
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
if ($this->phpVersionProvider->isAtLeastPhpVersion(PhpVersionFeature::SCALAR_TYPES)) {
// iterable type is better done in PHP code, than in doc
return '';
}
return $type->describe(VerbosityLevel::typeOnly());
}
private function convertUnionArrayTypeNodesToArrayTypeOfUnionTypeNodes(
UnionTypeNode $unionTypeNode
): BracketsAwareUnionTypeNode {

View File

@ -9,7 +9,6 @@ use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
final class MixedTypeMapper implements TypeMapperInterface
@ -37,9 +36,4 @@ final class MixedTypeMapper implements TypeMapperInterface
{
return null;
}
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return $type->describe(VerbosityLevel::typeOnly());
}
}

View File

@ -36,9 +36,4 @@ final class NeverTypeMapper implements TypeMapperInterface
{
return null;
}
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return 'mixed';
}
}

View File

@ -38,12 +38,4 @@ final class NonEmptyArrayTypeMapper implements TypeMapperInterface
{
return new Name('array');
}
/**
* @param NonEmptyArrayType $type
*/
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return 'mixed[]';
}
}

View File

@ -10,7 +10,6 @@ use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\NullType;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\PHPStanStaticTypeMapper\ValueObject\TypeKind;
@ -43,9 +42,4 @@ final class NullTypeMapper implements TypeMapperInterface
return new Name('null');
}
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return $type->describe(VerbosityLevel::typeOnly());
}
}

View File

@ -11,12 +11,10 @@ use PhpParser\Node\Name\FullyQualified;
use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\PHPStanStaticTypeMapper\Contract\PHPStanStaticTypeMapperAwareInterface;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
@ -33,16 +31,6 @@ final class ObjectTypeMapper implements TypeMapperInterface, PHPStanStaticTypeMa
*/
private $phpStanStaticTypeMapper;
/**
* @var ReflectionProvider
*/
private $reflectionProvider;
public function __construct(ReflectionProvider $reflectionProvider)
{
$this->reflectionProvider = $reflectionProvider;
}
/**
* @return class-string<Type>
*/
@ -110,33 +98,6 @@ final class ObjectTypeMapper implements TypeMapperInterface, PHPStanStaticTypeMa
return new Name('object');
}
/**
* @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())) {
// FQN by default
return '\\' . $type->describe(VerbosityLevel::typeOnly());
}
return $type->getClassName();
}
public function setPHPStanStaticTypeMapper(PHPStanStaticTypeMapper $phpStanStaticTypeMapper): void
{
$this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper;

View File

@ -11,7 +11,6 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\Generic\TemplateObjectWithoutClassType;
use PHPStan\Type\ObjectWithoutClassType;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\BetterPhpDocParser\ValueObject\Type\EmptyGenericTypeNode;
use Rector\Core\Php\PhpVersionProvider;
use Rector\Core\ValueObject\PhpVersionFeature;
@ -74,11 +73,6 @@ final class ObjectWithoutClassTypeMapper implements TypeMapperInterface, PHPStan
return new Name('object');
}
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return $type->describe(VerbosityLevel::typeOnly());
}
public function setPHPStanStaticTypeMapper(PHPStanStaticTypeMapper $phpStanStaticTypeMapper): void
{
$this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper;

View File

@ -9,7 +9,6 @@ use PhpParser\Node\Name;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\StaticTypeMapper\ValueObject\Type\ParentStaticType;
@ -38,9 +37,4 @@ final class ParentStaticTypeMapper implements TypeMapperInterface
{
return new Name('parent');
}
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return $type->describe(VerbosityLevel::typeOnly());
}
}

View File

@ -9,7 +9,6 @@ use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\ResourceType;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
final class ResourceTypeMapper implements TypeMapperInterface
@ -37,9 +36,4 @@ final class ResourceTypeMapper implements TypeMapperInterface
{
return null;
}
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return $type->describe(VerbosityLevel::typeOnly());
}
}

View File

@ -9,7 +9,6 @@ use PhpParser\Node\Name;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\StaticTypeMapper\ValueObject\Type\SelfObjectType;
@ -38,12 +37,4 @@ final class SelfObjectTypeMapper implements TypeMapperInterface
{
return new Name('self');
}
/**
* @param SelfObjectType $type
*/
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return $type->describe(VerbosityLevel::typeOnly());
}
}

View File

@ -11,7 +11,6 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\StaticType;
use PHPStan\Type\ThisType;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\Core\Php\PhpVersionProvider;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
@ -63,12 +62,4 @@ final class StaticTypeMapper implements TypeMapperInterface
return null;
}
/**
* @param StaticType $type
*/
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return $type->describe(VerbosityLevel::typeOnly());
}
}

View File

@ -42,9 +42,4 @@ final class StrictMixedTypeMapper implements TypeMapperInterface
{
return new Name(self::MIXED);
}
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return self::MIXED;
}
}

View File

@ -10,7 +10,6 @@ use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\Core\Php\PhpVersionProvider;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
@ -51,9 +50,4 @@ final class StringTypeMapper implements TypeMapperInterface
return new Name('string');
}
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return $type->describe(VerbosityLevel::typeOnly());
}
}

View File

@ -10,7 +10,6 @@ use PHPStan\PhpDocParser\Ast\Type\ThisTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\ThisType;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
final class ThisTypeMapper implements TypeMapperInterface
@ -38,12 +37,4 @@ final class ThisTypeMapper implements TypeMapperInterface
{
return new Name('self');
}
/**
* @param ThisType $type
*/
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return $type->describe(VerbosityLevel::typeOnly());
}
}

View File

@ -9,7 +9,6 @@ use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\Type;
use PHPStan\Type\TypeWithClassName;
use PHPStan\Type\VerbosityLevel;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
final class TypeWithClassNameTypeMapper implements TypeMapperInterface
@ -47,12 +46,4 @@ final class TypeWithClassNameTypeMapper implements TypeMapperInterface
{
return $this->stringTypeMapper->mapToPhpParserNode($type, $kind);
}
/**
* @param TypeWithClassName $type
*/
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
return $type->describe(VerbosityLevel::typeOnly());
}
}

View File

@ -12,6 +12,7 @@ use PhpParser\Node\NullableType;
use PhpParser\Node\UnionType as PhpParserUnionType;
use PhpParser\NodeAbstract;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\Constant\ConstantBooleanType;
use PHPStan\Type\IterableType;
use PHPStan\Type\NullType;
use PHPStan\Type\ObjectType;
@ -131,6 +132,13 @@ final class UnionTypeMapper implements TypeMapperInterface
return new NullableType(new Name('bool'));
}
if (! $this->phpVersionProvider->isAtLeastPhpVersion(PhpVersionFeature::UNION_TYPES) && $this->isFalseBoolUnion(
$type
)) {
// return new Bool
return new Name('bool');
}
// special case for nullable
$nullabledType = $this->matchTypeForNullableUnionType($type);
if (! $nullabledType instanceof Type) {
@ -159,24 +167,6 @@ final class UnionTypeMapper implements TypeMapperInterface
return new NullableType($nullabledTypeNode);
}
/**
* @param UnionType $type
*/
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
$docStrings = [];
foreach ($type->getTypes() as $unionedType) {
$docStrings[] = $this->phpStanStaticTypeMapper->mapToDocString($unionedType);
}
// remove empty values, e.g. void/iterable
$docStrings = array_unique($docStrings);
$docStrings = array_filter($docStrings);
return implode('|', $docStrings);
}
private function shouldSkipIterable(UnionType $unionType): bool
{
$unionTypeAnalysis = $this->unionTypeAnalyzer->analyseForNullableAndIterable($unionType);
@ -342,4 +332,21 @@ final class UnionTypeMapper implements TypeMapperInterface
return $typeWithClassName;
}
private function isFalseBoolUnion(UnionType $unionType): bool
{
if (count($unionType->getTypes()) !== 2) {
return false;
}
foreach ($unionType->getTypes() as $unionedType) {
if ($unionedType instanceof ConstantBooleanType) {
continue;
}
return false;
}
return true;
}
}

View File

@ -62,15 +62,4 @@ final class VoidTypeMapper implements TypeMapperInterface
return new Name(self::VOID);
}
public function mapToDocString(Type $type, ?Type $parentType = null): string
{
if ($this->phpVersionProvider->isAtLeastPhpVersion(PhpVersionFeature::SCALAR_TYPES)) {
// the void type is better done in PHP code
return '';
}
// fallback for PHP 7.0 and older, where void type was only in docs
return self::VOID;
}
}

View File

@ -8,6 +8,7 @@ use Nette\Utils\Strings;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\CallableType;
use PHPStan\Type\Constant\ConstantBooleanType;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\IterableType;
@ -18,7 +19,6 @@ use PHPStan\Type\ResourceType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use PHPStan\Type\VoidType;
use Rector\StaticTypeMapper\ValueObject\Type\FalseBooleanType;
final class ScalarStringToTypeMapper
{
@ -29,8 +29,7 @@ final class ScalarStringToTypeMapper
StringType::class => ['string'],
FloatType::class => ['float', 'real', 'double'],
IntegerType::class => ['int', 'integer'],
FalseBooleanType::class => ['false'],
BooleanType::class => ['true', 'bool', 'boolean'],
BooleanType::class => ['bool', 'boolean'],
NullType::class => ['null'],
VoidType::class => ['void'],
ResourceType::class => ['resource'],
@ -42,6 +41,14 @@ final class ScalarStringToTypeMapper
{
$loweredScalarName = Strings::lower($scalarName);
if ($loweredScalarName === 'false') {
return new ConstantBooleanType(false);
}
if ($loweredScalarName === 'true') {
return new ConstantBooleanType(true);
}
foreach (self::SCALAR_NAME_BY_TYPE as $objectType => $scalarNames) {
if (! in_array($loweredScalarName, $scalarNames, true)) {
continue;

View File

@ -67,6 +67,7 @@ final class IdentifierTypeMapper implements PhpDocTypeMapperInterface
if (! $type instanceof MixedType) {
return $type;
}
if ($type->isExplicitMixed()) {
return $type;
}

View File

@ -57,6 +57,6 @@ final class UnionTypeMapper implements PhpDocTypeMapperInterface
}
// to prevent missing class error, e.g. in tests
return $this->typeFactory->createMixedPassedOrUnionType($unionedTypes);
return $this->typeFactory->createMixedPassedOrUnionTypeAndKeepConstant($unionedTypes);
}
}

View File

@ -9,6 +9,7 @@ use PhpParser\Node\Name;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\Constant\ConstantBooleanType;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\MixedType;
@ -19,7 +20,6 @@ use PHPStan\Type\Type;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PSR4\Collector\RenamedClassesCollector;
use Rector\StaticTypeMapper\Contract\PhpParser\PhpParserNodeMapperInterface;
use Rector\StaticTypeMapper\ValueObject\Type\FalseBooleanType;
use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType;
final class NameNodeMapper implements PhpParserNodeMapperInterface
@ -117,7 +117,7 @@ final class NameNodeMapper implements PhpParserNodeMapperInterface
}
if ($name === 'false') {
return new FalseBooleanType();
return new ConstantBooleanType(false);
}
if ($name === 'bool') {

View File

@ -77,11 +77,6 @@ final class StaticTypeMapper
return $this->phpStanStaticTypeMapper->mapToPhpParserNode($phpStanType, $kind);
}
public function mapPHPStanTypeToDocString(Type $phpStanType, ?Type $parentType = null): string
{
return $this->phpStanStaticTypeMapper->mapToDocString($phpStanType, $parentType);
}
public function mapPhpParserNodePHPStanType(Node $node): Type
{
return $this->phpParserNodeMapper->mapToPHPStanType($node);

View File

@ -1,20 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\StaticTypeMapper\ValueObject\Type;
use PHPStan\Type\BooleanType;
use PHPStan\Type\VerbosityLevel;
/**
* Special case for union types
* @see https://wiki.php.net/rfc/union_types_v2#false_pseudo-type
*/
final class FalseBooleanType extends BooleanType
{
public function describe(VerbosityLevel $verbosityLevel): string
{
return 'false';
}
}

View File

@ -575,3 +575,16 @@ parameters:
message: '#"%s" in sprintf\(\) format must be quoted#'
paths:
- packages/ChangesReporting/ValueObject/RectorWithFileAndLineChange.php
-
message: '#Class cognitive complexity is \d+, keep it under 50#'
paths:
- packages/PHPStanStaticTypeMapper/TypeMapper/UnionTypeMapper.php
-
message: '#Cognitive complexity for "Rector\\PHPStanStaticTypeMapper\\TypeMapper\\UnionTypeMapper\:\:mapToPhpParserNode\(\)" is 11, keep it under 9#'
paths:
- packages/PHPStanStaticTypeMapper/TypeMapper/UnionTypeMapper.php
- '#Cognitive complexity for "Rector\\PHPStanStaticTypeMapper\\TypeMapper\\UnionTypeMapper\:\:mapToPhpParserNode\(\)" is 10, keep it under 9#'
- '#Method Rector\\NodeNameResolver\\NodeNameResolver\:\:matchRectorBacktraceCall\(\) return type has no value type specified in iterable type array#'

View File

@ -7,6 +7,5 @@ use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigura
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(UnionTypesRector::class);
};

View File

@ -2,7 +2,7 @@
namespace Rector\Tests\Restoration\Rector\ClassMethod\InferParamFromClassMethodReturnRector\Fixture;
use Hoa\Protocol\Node\Node;
use PhpParser\Node;
use PhpParser\Node\Expr\AssignOp\Plus;
use PhpParser\Node\Expr\BinaryOp\Plus as BinaryPlus;
use Rector\Tests\Restoration\Rector\ClassMethod\InferParamFromClassMethodReturnRector\Source\SomeType;

View File

@ -7,10 +7,9 @@ class BoolClass
/**
* @param true $ojoj
* @param FALSE $ojoj2
* @param true|false $ojoj3
* @param int|null|true|false $ojoj5
*/
function someFunction($ojoj, $ojoj2, $ojoj3, $ojoj5)
function someFunction($ojoj, $ojoj2, $ojoj5)
{
}
}
@ -26,7 +25,7 @@ class BoolClass
/**
* @param int|null|true|false $ojoj5
*/
function someFunction(bool $ojoj, bool $ojoj2, bool $ojoj3, $ojoj5)
function someFunction(bool $ojoj, bool $ojoj2, $ojoj5)
{
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Rector\Tests\TypeDeclaration\Rector\FunctionLike\ParamTypeDeclarationRector\Fixture;
final class UnionFalseTrue
{
/**
* @param true|false $ojoj3
*/
function someFunction($ojoj3)
{
}
}
?>
-----
<?php
namespace Rector\Tests\TypeDeclaration\Rector\FunctionLike\ParamTypeDeclarationRector\Fixture;
final class UnionFalseTrue
{
function someFunction(bool $ojoj3)
{
}
}
?>

View File

@ -11,7 +11,6 @@ use PHPStan\Type\MixedType;
use PHPStan\Type\StringType;
use PHPStan\Type\UnionType;
use Rector\Core\HttpKernel\RectorKernel;
use Rector\StaticTypeMapper\StaticTypeMapper;
use Rector\TypeDeclaration\TypeNormalizer;
use Symplify\PackageBuilder\Testing\AbstractKernelTestCase;
@ -22,17 +21,10 @@ final class TypeNormalizerTest extends AbstractKernelTestCase
*/
private $typeNormalizer;
/**
* @var StaticTypeMapper
*/
private $staticTypeMapper;
protected function setUp(): void
{
$this->bootKernel(RectorKernel::class);
$this->typeNormalizer = $this->getService(TypeNormalizer::class);
$this->staticTypeMapper = $this->getService(StaticTypeMapper::class);
}
/**
@ -40,14 +32,8 @@ final class TypeNormalizerTest extends AbstractKernelTestCase
*/
public function testNormalizeArrayOfUnionToUnionArray(ArrayType $arrayType, string $expectedDocString): void
{
$arrayDocString = $this->staticTypeMapper->mapPHPStanTypeToDocString($arrayType);
$this->assertSame($expectedDocString, $arrayDocString);
$unionType = $this->typeNormalizer->normalizeArrayOfUnionToUnionArray($arrayType);
$this->assertInstanceOf(UnionType::class, $unionType);
$unionDocString = $this->staticTypeMapper->mapPHPStanTypeToDocString($unionType);
$this->assertSame($expectedDocString, $unionDocString);
}
/**

View File

@ -38,6 +38,7 @@ final class ParamTagRemover
// remove existing type
$paramTagValueNode = $phpDocInfo->getParamTagValueByName($paramName);
if (! $paramTagValueNode instanceof ParamTagValueNode) {
continue;
}

View File

@ -12,7 +12,6 @@ use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
@ -200,11 +199,7 @@ CODE_SAMPLE
private function isParamDocTypeEqualToPhpType(Param $param, Type $paramType): bool
{
$currentParamType = $this->getObjectType($param);
if ($currentParamType instanceof UnionType) {
$currentParamType = $currentParamType->getTypes()[0];
}
$currentParamType = $this->nodeTypeResolver->getStaticType($param);
return $currentParamType->equals($paramType);
}
}

View File

@ -10,7 +10,6 @@ use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\FunctionLike;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\NullableType;
@ -225,15 +224,10 @@ CODE_SAMPLE
}
/**
* @return Identifier|Name|NullableType|PhpParserUnionType|null
* @return Name|NullableType|PhpParserUnionType|null
*/
private function resolveFuncCallReturnNode(FuncCall $funcCall): ?Node
{
$function = $this->nodeRepository->findFunctionByFuncCall($funcCall);
if ($function instanceof Function_) {
return $function->returnType;
}
$returnType = $this->reflectionTypeResolver->resolveFuncCallReturnType($funcCall);
if (! $returnType instanceof Type) {
return null;

View File

@ -36,12 +36,12 @@ final class ParamTypeInferer
public function inferParam(Param $param): Type
{
foreach ($this->paramTypeInferers as $paramTypeInferer) {
$type = $paramTypeInferer->inferParam($param);
if ($type instanceof MixedType) {
$paramType = $paramTypeInferer->inferParam($param);
if ($paramType instanceof MixedType) {
continue;
}
return $this->genericClassStringTypeNormalizer->normalize($type);
return $this->genericClassStringTypeNormalizer->normalize($paramType);
}
return new MixedType();