Skip to content

Commit a8b793e

Browse files
staabmondrejmirtes
authored andcommitted
Re-introduce TypeTraverser
1 parent 7fd0c48 commit a8b793e

File tree

3 files changed

+43
-29
lines changed

3 files changed

+43
-29
lines changed

src/Type/Php/GetClassDynamicReturnTypeExtension.php

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,17 @@
99
use PHPStan\Type\Constant\ConstantBooleanType;
1010
use PHPStan\Type\Constant\ConstantStringType;
1111
use PHPStan\Type\DynamicFunctionReturnTypeExtension;
12+
use PHPStan\Type\Enum\EnumCaseObjectType;
1213
use PHPStan\Type\Generic\GenericClassStringType;
14+
use PHPStan\Type\IntersectionType;
1315
use PHPStan\Type\ObjectShapeType;
16+
use PHPStan\Type\ObjectType;
1417
use PHPStan\Type\ObjectWithoutClassType;
1518
use PHPStan\Type\StaticType;
1619
use PHPStan\Type\Type;
20+
use PHPStan\Type\TypeCombinator;
1721
use PHPStan\Type\TypeTraverser;
1822
use PHPStan\Type\TypeUtils;
19-
use PHPStan\Type\TypeCombinator;
2023
use PHPStan\Type\UnionType;
2124
use function count;
2225

@@ -50,29 +53,42 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
5053
return new ClassStringType();
5154
}
5255

53-
$isObject = $argType->isObject();
54-
if ($isObject->yes() || $isObject->maybe()) {
55-
if ($argType instanceof ObjectShapeType) {
56-
return new ClassStringType();
57-
}
58-
59-
$objectType = TypeCombinator::intersect($argType, new ObjectWithoutClassType());
60-
if ($objectType instanceof StaticType) {
61-
$objectType = $objectType->getStaticObjectType();
62-
}
63-
$classStringType = new GenericClassStringType($objectType);
64-
65-
if ($isObject->yes()) {
66-
return $classStringType;
67-
}
68-
69-
return new UnionType([
70-
$classStringType,
71-
new ConstantBooleanType(false),
72-
]);
73-
}
74-
75-
return new ConstantBooleanType(false);
56+
return TypeTraverser::map(
57+
$argType,
58+
static function (Type $type, callable $traverse): Type {
59+
if ($type instanceof UnionType || $type instanceof IntersectionType) {
60+
return $traverse($type);
61+
}
62+
63+
if ($type instanceof EnumCaseObjectType) {
64+
return new GenericClassStringType(new ObjectType($type->getClassName()));
65+
}
66+
67+
$isObject = $type->isObject();
68+
if ($isObject->yes() || $isObject->maybe()) {
69+
if ($type instanceof ObjectShapeType) {
70+
return new ClassStringType();
71+
}
72+
73+
$objectType = TypeCombinator::intersect($type, new ObjectWithoutClassType());
74+
if ($objectType instanceof StaticType) {
75+
$objectType = $objectType->getStaticObjectType();
76+
}
77+
$classStringType = new GenericClassStringType($objectType);
78+
79+
if ($isObject->yes()) {
80+
return $classStringType;
81+
}
82+
83+
return new UnionType([
84+
$classStringType,
85+
new ConstantBooleanType(false),
86+
]);
87+
}
88+
89+
return new ConstantBooleanType(false);
90+
},
91+
);
7692
}
7793

7894
}

tests/PHPStan/Analyser/data/generics.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,10 +1309,8 @@ function getClassOnTemplateType($a, $b, $c, $d, $object, $mixed, $tObject)
13091309
get_class($b)
13101310
);
13111311
assertType(
1312-
'class-string<'.
1313-
'U of Exception (function PHPStan\Generics\FunctionsAssertType\getClassOnTemplateType(), argument)|'.
1314-
'V of DateTimeInterface (function PHPStan\Generics\FunctionsAssertType\getClassOnTemplateType(), argument)'.
1315-
'>',
1312+
'class-string<U of Exception (function PHPStan\Generics\FunctionsAssertType\getClassOnTemplateType(), argument)>|' .
1313+
'class-string<V of DateTimeInterface (function PHPStan\Generics\FunctionsAssertType\getClassOnTemplateType(), argument)>',
13161314
get_class($c)
13171315
);
13181316
assertType('class-string<Iterator<mixed, DateTimeInterface>>', get_class($d));

tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,7 @@ public function testLooseComparisonAgainstEnumsNoPhpdoc(): void
10351035
$issues = array_values(array_filter($issues, static fn (array $i) => count($i) === 2));
10361036
$this->analyse([__DIR__ . '/data/loose-comparison-against-enums.php'], $issues);
10371037
}
1038-
1038+
10391039
public function testBug4890b(): void
10401040
{
10411041
$this->checkAlwaysTrueCheckTypeFunctionCall = true;

0 commit comments

Comments
 (0)