Skip to content

Commit 41cb981

Browse files
committed
Resolve type incompatibilities
I don't know whether PHP Parser changed or we always had an interesting situation, but phpstan pointed out that the TypeFactory contained a type incompatibility. I have resolved that and made the stringifying code recursive because an intersection type may contain another intersection type, etc, etc.
1 parent 5478413 commit 41cb981

File tree

5 files changed

+45
-9
lines changed

5 files changed

+45
-9
lines changed

src/phpDocumentor/Reflection/Php/Factory/ClassConstantIterator.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
/**
2323
* This class acts like a combination of a ClassConst and Const_
2424
* to be able to create constant descriptors using a normal strategy.
25+
*
26+
* @implements Iterator<int, ClassConstantIterator>
2527
*/
2628
final class ClassConstantIterator implements Iterator
2729
{

src/phpDocumentor/Reflection/Php/Factory/GlobalConstantIterator.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
use PhpParser\Node\Expr;
2020
use PhpParser\Node\Stmt\Const_;
2121

22+
/**
23+
* @implements Iterator<int, GlobalConstantIterator>
24+
*/
2225
final class GlobalConstantIterator implements Iterator
2326
{
2427
private Const_ $constant;

src/phpDocumentor/Reflection/Php/Factory/PropertyIterator.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
/**
2626
* This class acts like a combination of a PropertyNode and PropertyProperty to
2727
* be able to create property descriptors using a normal strategy.
28+
*
29+
* @implements Iterator<int, PropertyIterator>
2830
*/
2931
final class PropertyIterator implements Iterator
3032
{

src/phpDocumentor/Reflection/Php/Factory/Type.php

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,12 @@
2323
use PhpParser\Node\Name;
2424
use PhpParser\Node\NullableType;
2525
use PhpParser\Node\UnionType;
26+
use PhpParser\NodeAbstract;
2627

28+
use function array_map;
2729
use function get_class;
2830
use function implode;
31+
use function is_string;
2932
use function sprintf;
3033

3134
final class Type
@@ -39,23 +42,49 @@ public function fromPhpParser($type, ?Context $context = null): ?TypeElement
3942
return null;
4043
}
4144

42-
$typeResolver = new TypeResolver();
45+
return (new TypeResolver())
46+
->resolve($this->convertPhpParserTypeToString($type), $context);
47+
}
48+
49+
/**
50+
* @param NodeAbstract|string $type
51+
*/
52+
private function convertPhpParserTypeToString($type): string
53+
{
54+
if (is_string($type)) {
55+
return $type;
56+
}
57+
58+
if ($type instanceof Identifier) {
59+
return $type->toString();
60+
}
61+
62+
if ($type instanceof Name) {
63+
return $type->toString();
64+
}
65+
4366
if ($type instanceof NullableType) {
44-
return $typeResolver->resolve('?' . $type->type, $context);
67+
return '?' . $this->convertPhpParserTypeToString($type->type);
4568
}
4669

4770
if ($type instanceof UnionType) {
48-
return $typeResolver->resolve(implode('|', $type->types), $context);
71+
$typesAsStrings = array_map(
72+
fn ($typeObject): string => $this->convertPhpParserTypeToString($typeObject),
73+
$type->types
74+
);
75+
76+
return implode('|', $typesAsStrings);
4977
}
5078

5179
if ($type instanceof IntersectionType) {
52-
return $typeResolver->resolve(implode('&', $type->types), $context);
53-
}
80+
$typesAsStrings = array_map(
81+
fn ($typeObject): string => $this->convertPhpParserTypeToString($typeObject),
82+
$type->types
83+
);
5484

55-
if ($type instanceof ComplexType) {
56-
throw new InvalidArgumentException(sprintf('Unsupported complex type %s', get_class($type)));
85+
return implode('&', $typesAsStrings);
5786
}
5887

59-
return $typeResolver->resolve($type->toString(), $context);
88+
throw new InvalidArgumentException(sprintf('Unsupported complex type %s', get_class($type)));
6089
}
6190
}

tests/unit/phpDocumentor/Reflection/Php/Factory/TypeTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public function testReturnsNullableTypeWhenPassedAPhpParserNullable(): void
7878
public function testReturnsUnion(): void
7979
{
8080
$factory = new Type();
81-
$given = new UnionType(['integer', 'string']);
81+
$given = new UnionType([new Identifier('integer'), new Identifier('string')]);
8282
$expected = new Compound([new Integer(), new String_()]);
8383

8484
$result = $factory->fromPhpParser($given);

0 commit comments

Comments
 (0)