1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace PHPStan\BetterReflection\Reflection;
6:
7: use PhpParser\Node\Identifier;
8: use PhpParser\Node\IntersectionType;
9: use PhpParser\Node\Name;
10: use PhpParser\Node\UnionType;
11: use PHPStan\BetterReflection\Reflector\Reflector;
12:
13: use function array_map;
14: use function assert;
15: use function implode;
16: use function sprintf;
17:
18: class ReflectionUnionType extends ReflectionType
19: {
20: /** @var non-empty-list<ReflectionNamedType|ReflectionIntersectionType> */
21: private $types;
22:
23: /** @internal
24: * @param \PHPStan\BetterReflection\Reflection\ReflectionParameter|\PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionEnum|\PHPStan\BetterReflection\Reflection\ReflectionProperty $owner */
25: public function __construct(Reflector $reflector, $owner, UnionType $type)
26: {
27: /** @var non-empty-list<ReflectionNamedType|ReflectionIntersectionType> $types */
28: $types = array_map(static function ($type) use ($reflector, $owner) {
29: $type = ReflectionType::createFromNode($reflector, $owner, $type);
30: assert($type instanceof ReflectionNamedType || $type instanceof ReflectionIntersectionType);
31:
32: return $type;
33: }, $type->types);
34: $this->types = $types;
35: }
36:
37: /** @internal
38: * @param \PHPStan\BetterReflection\Reflection\ReflectionParameter|\PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionEnum|\PHPStan\BetterReflection\Reflection\ReflectionProperty $owner
39: * @return $this */
40: public function withOwner($owner)
41: {
42: $clone = clone $this;
43:
44: foreach ($clone->types as $typeNo => $innerType) {
45: $clone->types[$typeNo] = $innerType->withOwner($owner);
46: }
47:
48: return $clone;
49: }
50:
51: /** @return non-empty-list<ReflectionNamedType|ReflectionIntersectionType> */
52: public function getTypes(): array
53: {
54: return $this->types;
55: }
56:
57: public function allowsNull(): bool
58: {
59: foreach ($this->types as $type) {
60: if ($type->allowsNull()) {
61: return true;
62: }
63: }
64:
65: return false;
66: }
67:
68: public function __toString(): string
69: {
70: return implode('|', array_map(static function (ReflectionType $type): string {
71: if ($type instanceof ReflectionIntersectionType) {
72: return sprintf('(%s)', $type->__toString());
73: }
74:
75: return $type->__toString();
76: }, $this->types));
77: }
78: }
79: