From 3c2100b3a8d2372094135efa9c4d0433078337b5 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 1 Jul 2024 09:15:52 +0200 Subject: [PATCH] Union mapper cleanup (#6094) * instnance check * union mapper cleanup --- .../TypeAnalyzer/UnionTypeAnalyzer.php | 32 ------- .../TypeMapper/UnionTypeMapper.php | 88 +------------------ .../ValueObject/UnionTypeAnalysis.php | 24 ----- .../Naming/NameScopeFactory.php | 14 +-- 4 files changed, 10 insertions(+), 148 deletions(-) delete mode 100644 src/PHPStanStaticTypeMapper/ValueObject/UnionTypeAnalysis.php diff --git a/src/PHPStanStaticTypeMapper/TypeAnalyzer/UnionTypeAnalyzer.php b/src/PHPStanStaticTypeMapper/TypeAnalyzer/UnionTypeAnalyzer.php index 5ccf4431960..be19eaba320 100644 --- a/src/PHPStanStaticTypeMapper/TypeAnalyzer/UnionTypeAnalyzer.php +++ b/src/PHPStanStaticTypeMapper/TypeAnalyzer/UnionTypeAnalyzer.php @@ -4,43 +4,11 @@ namespace Rector\PHPStanStaticTypeMapper\TypeAnalyzer; -use PHPStan\Type\ArrayType; -use PHPStan\Type\IterableType; use PHPStan\Type\NullType; -use PHPStan\Type\ObjectType; use PHPStan\Type\UnionType; -use Rector\PHPStanStaticTypeMapper\ValueObject\UnionTypeAnalysis; -use Traversable; final class UnionTypeAnalyzer { - public function analyseForArrayAndIterable(UnionType $unionType): ?UnionTypeAnalysis - { - $hasIterable = false; - $hasArray = false; - - foreach ($unionType->getTypes() as $unionedType) { - if ($unionedType instanceof IterableType) { - $hasIterable = true; - continue; - } - - if ($unionedType instanceof ArrayType) { - $hasArray = true; - continue; - } - - if ($unionedType instanceof ObjectType && $unionedType->getClassName() === Traversable::class) { - $hasIterable = true; - continue; - } - - return null; - } - - return new UnionTypeAnalysis($hasIterable, $hasArray); - } - public function isNullable(UnionType $unionType, bool $checkTwoTypes = false): bool { $types = $unionType->getTypes(); diff --git a/src/PHPStanStaticTypeMapper/TypeMapper/UnionTypeMapper.php b/src/PHPStanStaticTypeMapper/TypeMapper/UnionTypeMapper.php index e96ef258da6..faeaec5772b 100644 --- a/src/PHPStanStaticTypeMapper/TypeMapper/UnionTypeMapper.php +++ b/src/PHPStanStaticTypeMapper/TypeMapper/UnionTypeMapper.php @@ -14,20 +14,16 @@ use PhpParser\Node\UnionType as PhpParserUnionType; use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Type\Constant\ConstantBooleanType; -use PHPStan\Type\IterableType; use PHPStan\Type\MixedType; use PHPStan\Type\NullType; use PHPStan\Type\Type; use PHPStan\Type\UnionType; use PHPStan\Type\VoidType; use Rector\BetterPhpDocParser\ValueObject\Type\BracketsAwareUnionTypeNode; -use Rector\NodeNameResolver\NodeNameResolver; use Rector\Php\PhpVersionProvider; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; use Rector\PHPStanStaticTypeMapper\Enum\TypeKind; use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper; -use Rector\PHPStanStaticTypeMapper\TypeAnalyzer\UnionTypeAnalyzer; -use Rector\PHPStanStaticTypeMapper\ValueObject\UnionTypeAnalysis; use Rector\ValueObject\PhpVersionFeature; use Webmozart\Assert\Assert; use Webmozart\Assert\InvalidArgumentException; @@ -41,8 +37,6 @@ final class UnionTypeMapper implements TypeMapperInterface public function __construct( private readonly PhpVersionProvider $phpVersionProvider, - private readonly UnionTypeAnalyzer $unionTypeAnalyzer, - private readonly NodeNameResolver $nodeNameResolver ) { } @@ -61,19 +55,11 @@ public function getNodeClass(): string */ public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode { - // note: cannot be handled by PHPStan as uses no-space around | $unionTypesNodes = []; - $skipIterable = $this->shouldSkipIterable($type); - foreach ($type->getTypes() as $unionedType) { - if ($unionedType instanceof IterableType && $skipIterable) { - continue; - } - $unionTypesNodes[] = $this->phpStanStaticTypeMapper->mapToPHPStanPhpDocTypeNode($unionedType); } - $unionTypesNodes = array_unique($unionTypesNodes); return new BracketsAwareUnionTypeNode($unionTypesNodes); } @@ -83,15 +69,10 @@ public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode public function mapToPhpParserNode(Type $type, string $typeKind): ?Node { // special case for nullable - $nullabledType = $this->matchTypeForNullableUnionType($type); - if (! $nullabledType instanceof Type) { - return $this->matchTypeForUnionedTypes($type, $typeKind); - } - - return $this->mapNullabledType($nullabledType, $typeKind); + return $this->matchTypeForUnionedTypes($type, $typeKind); } - public function resolveTypeWithNullablePHPParserUnionType( + private function resolveTypeWithNullablePHPParserUnionType( PhpParserUnionType $phpParserUnionType ): PhpParserUnionType|NullableType|null { $totalTypes = count($phpParserUnionType->types); @@ -138,7 +119,7 @@ private function resolveNullableType(NullableType $nullableType): null|NullableT return $nullableType; } - if (! $this->phpVersionProvider->isAtLeastPhpVersion(PhpVersionFeature::INTERSECTION_TYPES)) { + if (! $this->phpVersionProvider->isAtLeastPhpVersion(PhpVersionFeature::UNION_TYPES)) { return null; } @@ -148,49 +129,6 @@ private function resolveNullableType(NullableType $nullableType): null|NullableT return new PhpParserUnionType($types); } - /** - * @param TypeKind::* $typeKind - */ - private function mapNullabledType( - Type $nullabledType, - string $typeKind - ): NullableType|ComplexType|PhpParserUnionType|null { - // void cannot be nullable - if ($nullabledType->isVoid()->yes()) { - return null; - } - - $nullabledTypeNode = $this->phpStanStaticTypeMapper->mapToPhpParserNode($nullabledType, $typeKind); - if (! $nullabledTypeNode instanceof Node) { - return null; - } - - if (in_array($nullabledTypeNode::class, [NullableType::class, ComplexType::class], true)) { - return $nullabledTypeNode; - } - - /** @var Name $nullabledTypeNode */ - if (! $this->nodeNameResolver->isNames($nullabledTypeNode, ['false', 'mixed'])) { - return $this->resolveNullableType(new NullableType($nullabledTypeNode)); - } - - return null; - } - - private function shouldSkipIterable(UnionType $unionType): bool - { - $unionTypeAnalysis = $this->unionTypeAnalyzer->analyseForArrayAndIterable($unionType); - if (! $unionTypeAnalysis instanceof UnionTypeAnalysis) { - return false; - } - - if (! $unionTypeAnalysis->hasIterable()) { - return false; - } - - return $unionTypeAnalysis->hasArray(); - } - private function resolveUnionTypes(PhpParserUnionType $phpParserUnionType): ?PhpParserUnionType { if (! $this->phpVersionProvider->isAtLeastPhpVersion(PhpVersionFeature::UNION_TYPES)) { @@ -200,26 +138,6 @@ private function resolveUnionTypes(PhpParserUnionType $phpParserUnionType): ?Php return $phpParserUnionType; } - private function matchTypeForNullableUnionType(UnionType $unionType): ?Type - { - if (count($unionType->getTypes()) !== 2) { - return null; - } - - $firstType = $unionType->getTypes()[0]; - $secondType = $unionType->getTypes()[1]; - - if ($firstType instanceof NullType) { - return $secondType; - } - - if ($secondType instanceof NullType) { - return $firstType; - } - - return null; - } - private function hasObjectAndStaticType(PhpParserUnionType $phpParserUnionType): bool { $hasAnonymousObjectType = false; diff --git a/src/PHPStanStaticTypeMapper/ValueObject/UnionTypeAnalysis.php b/src/PHPStanStaticTypeMapper/ValueObject/UnionTypeAnalysis.php deleted file mode 100644 index e3e448b8ff0..00000000000 --- a/src/PHPStanStaticTypeMapper/ValueObject/UnionTypeAnalysis.php +++ /dev/null @@ -1,24 +0,0 @@ -hasIterable; - } - - public function hasArray(): bool - { - return $this->hasArray; - } -} diff --git a/src/StaticTypeMapper/Naming/NameScopeFactory.php b/src/StaticTypeMapper/Naming/NameScopeFactory.php index 1c69e232ef6..a0432f6c97d 100644 --- a/src/StaticTypeMapper/Naming/NameScopeFactory.php +++ b/src/StaticTypeMapper/Naming/NameScopeFactory.php @@ -27,18 +27,18 @@ public function __construct( public function createNameScopeFromNodeWithoutTemplateTypes(Node $node): NameScope { $scope = $node->getAttribute(AttributeKey::SCOPE); - $namespace = $scope instanceof Scope ? $scope->getNamespace() : null; - - $uses = $this->useImportsResolver->resolve(); - $usesAliasesToNames = $this->resolveUseNamesByAlias($uses); - - if ($scope instanceof Scope && $scope->getClassReflection() instanceof ClassReflection) { + if ($scope instanceof Scope) { + $namespace = $scope->getNamespace(); $classReflection = $scope->getClassReflection(); - $className = $classReflection->getName(); + $className = $classReflection instanceof ClassReflection ? $classReflection->getName() : null; } else { + $namespace = null; $className = null; } + $uses = $this->useImportsResolver->resolve(); + $usesAliasesToNames = $this->resolveUseNamesByAlias($uses); + return new NameScope($namespace, $usesAliasesToNames, $className); }