Skip to content

Commit ff4f871

Browse files
committed
extract NodeTypeCorrector service to wrap similar logic
1 parent c419fe2 commit ff4f871

2 files changed

Lines changed: 84 additions & 34 deletions

File tree

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\NodeTypeResolver;
6+
7+
use PHPStan\Type\Accessory\AccessoryArrayListType;
8+
use PHPStan\Type\IntersectionType;
9+
use PHPStan\Type\Type;
10+
use Rector\NodeTypeResolver\NodeTypeCorrector\AccessoryNonEmptyArrayTypeCorrector;
11+
use Rector\NodeTypeResolver\NodeTypeCorrector\AccessoryNonEmptyStringTypeCorrector;
12+
use Rector\NodeTypeResolver\NodeTypeCorrector\GenericClassStringTypeCorrector;
13+
14+
/**
15+
* This service correct unnecessary intersection/union types that do not bring any value.
16+
* We focus on scalar types like "array", "string", "int" etc.,
17+
* to print them as valid type declarations.
18+
*/
19+
final readonly class NodeTypeCorrector
20+
{
21+
public function __construct(
22+
private AccessoryNonEmptyStringTypeCorrector $accessoryNonEmptyStringTypeCorrector,
23+
private GenericClassStringTypeCorrector $genericClassStringTypeCorrector,
24+
private AccessoryNonEmptyArrayTypeCorrector $accessoryNonEmptyArrayTypeCorrector,
25+
) {
26+
}
27+
28+
public function correctType(Type $type): Type
29+
{
30+
$type = $this->accessoryNonEmptyStringTypeCorrector->correct($type);
31+
$type = $this->genericClassStringTypeCorrector->correct($type);
32+
33+
$type = $this->removeAccessoryArrayListType($type);
34+
35+
return $this->accessoryNonEmptyArrayTypeCorrector->correct($type);
36+
}
37+
38+
private function removeAccessoryArrayListType(Type $type): Type
39+
{
40+
if (! $type instanceof IntersectionType) {
41+
return $type;
42+
}
43+
44+
$cleanTypes = [];
45+
foreach ($type->getTypes() as $intersectionType) {
46+
if ($intersectionType instanceof AccessoryArrayListType) {
47+
continue;
48+
}
49+
50+
$cleanTypes[] = $intersectionType;
51+
}
52+
53+
if (count($cleanTypes) === 1) {
54+
return $cleanTypes[0];
55+
}
56+
57+
return new IntersectionType($cleanTypes);
58+
}
59+
}

src/NodeTypeResolver/NodeTypeResolver.php

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public function __construct(
8383
private readonly ObjectTypeSpecifier $objectTypeSpecifier,
8484
private readonly ClassAnalyzer $classAnalyzer,
8585
private readonly GenericClassStringTypeCorrector $genericClassStringTypeCorrector,
86+
private readonly NodeTypeCorrector $nodeTypeCorrector,
8687
private readonly ReflectionProvider $reflectionProvider,
8788
private readonly AccessoryNonEmptyStringTypeCorrector $accessoryNonEmptyStringTypeCorrector,
8889
private readonly AccessoryNonEmptyArrayTypeCorrector $accessoryNonEmptyArrayTypeCorrector,
@@ -203,7 +204,7 @@ public function getType(Node $node): Type
203204
$type = $this->resolveByNodeTypeResolvers($node);
204205

205206
if ($type instanceof Type) {
206-
$type = $this->correctType($type);
207+
$type = $this->nodeTypeCorrector->correctType($type);
207208

208209
if ($type instanceof ObjectType) {
209210
$scope = $node->getAttribute(AttributeKey::SCOPE);
@@ -238,7 +239,7 @@ public function getType(Node $node): Type
238239
return new MixedType();
239240
}
240241

241-
$type = $this->correctType($scope->getType($node));
242+
$type = $this->nodeTypeCorrector->correctType($scope->getType($node));
242243

243244
// hot fix for phpstan not resolving chain method calls
244245
if (! $node instanceof MethodCall) {
@@ -286,7 +287,7 @@ public function getNativeType(Expr $expr): Type
286287
return new ObjectWithoutClassType();
287288
}
288289

289-
return $this->correctType($type);
290+
return $this->nodeTypeCorrector->correctType($type);
290291
}
291292

292293
return $this->resolveNativeUnionType($type);
@@ -374,16 +375,6 @@ public function isMethodStaticCallOrClassMethodObjectType(Node $node, ObjectType
374375
return $classReflection->hasTraitUse($objectType->getClassName());
375376
}
376377

377-
private function correctType(Type $type): Type
378-
{
379-
$type = $this->accessoryNonEmptyStringTypeCorrector->correct($type);
380-
$type = $this->genericClassStringTypeCorrector->correct($type);
381-
382-
$type = $this->cleanArrayIntersectionType($type);
383-
384-
return $this->accessoryNonEmptyArrayTypeCorrector->correct($type);
385-
}
386-
387378
/**
388379
* Allow pull type from
389380
*
@@ -680,25 +671,25 @@ private function isSubstrOnPHP74(FuncCall $funcCall): bool
680671
return ! $this->phpVersionProvider->isAtLeastPhpVersion(PhpVersion::PHP_80);
681672
}
682673

683-
private function cleanArrayIntersectionType(Type $type): Type
684-
{
685-
if (! $type instanceof IntersectionType) {
686-
return $type;
687-
}
688-
689-
$cleanTypes = [];
690-
foreach ($type->getTypes() as $intersectionType) {
691-
if ($intersectionType instanceof AccessoryArrayListType) {
692-
continue;
693-
}
694-
695-
$cleanTypes[] = $intersectionType;
696-
}
697-
698-
if (count($cleanTypes) === 1) {
699-
return $cleanTypes[0];
700-
}
701-
702-
return new IntersectionType($cleanTypes);
703-
}
674+
// private function cleanArrayIntersectionType(Type $type): Type
675+
// {
676+
// if (! $type instanceof IntersectionType) {
677+
// return $type;
678+
// }
679+
//
680+
// $cleanTypes = [];
681+
// foreach ($type->getTypes() as $intersectionType) {
682+
// if ($intersectionType instanceof AccessoryArrayListType) {
683+
// continue;
684+
// }
685+
//
686+
// $cleanTypes[] = $intersectionType;
687+
// }
688+
//
689+
// if (count($cleanTypes) === 1) {
690+
// return $cleanTypes[0];
691+
// }
692+
//
693+
// return new IntersectionType($cleanTypes);
694+
// }
704695
}

0 commit comments

Comments
 (0)