1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace PHPStan\BetterReflection\Reflection;
6:
7: use PhpParser\Node;
8: use PhpParser\Node\IntersectionType;
9: use PHPStan\BetterReflection\Reflector\Reflector;
10:
11: use function array_map;
12: use function assert;
13: use function implode;
14:
15: /** @psalm-immutable */
16: class ReflectionIntersectionType extends ReflectionType
17: {
18: /** @var non-empty-list<ReflectionNamedType> */
19: private array $types;
20:
21: /** @internal
22: * @param \PHPStan\BetterReflection\Reflection\ReflectionParameter|\PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionEnum|\PHPStan\BetterReflection\Reflection\ReflectionProperty|\PHPStan\BetterReflection\Reflection\ReflectionClassConstant $owner */
23: public function __construct(Reflector $reflector, $owner, IntersectionType $type)
24: {
25: /** @var non-empty-list<ReflectionNamedType> $types */
26: $types = array_map(static function ($type) use ($reflector, $owner): ReflectionNamedType {
27: $type = ReflectionType::createFromNode($reflector, $owner, $type);
28: assert($type instanceof ReflectionNamedType);
29:
30: return $type;
31: }, $type->types);
32: $this->types = $types;
33: }
34:
35: /** @internal
36: * @param \PHPStan\BetterReflection\Reflection\ReflectionParameter|\PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionEnum|\PHPStan\BetterReflection\Reflection\ReflectionProperty|\PHPStan\BetterReflection\Reflection\ReflectionClassConstant $owner
37: * @return static */
38: public function withOwner($owner)
39: {
40: $clone = clone $this;
41:
42: $clone->types = array_map(static fn (ReflectionNamedType $type): ReflectionNamedType => $type->withOwner($owner), $clone->types);
43:
44: return $clone;
45: }
46:
47: /** @return non-empty-list<ReflectionNamedType> */
48: public function getTypes(): array
49: {
50: return $this->types;
51: }
52:
53: /**
54: * @return false
55: */
56: public function allowsNull(): bool
57: {
58: return false;
59: }
60:
61: /** @return non-empty-string */
62: public function __toString(): string
63: {
64: // @infection-ignore-all UnwrapArrayMap: It works without array_map() as well but this is less magical
65: return implode('&', array_map(static fn (ReflectionNamedType $type): string => $type->__toString(), $this->types));
66: }
67: }
68: