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: foreach ($clone->types as $typeNo => $innerType) {
43: $clone->types[$typeNo] = $innerType->withOwner($owner);
44: }
45:
46: return $clone;
47: }
48:
49: /** @return non-empty-list<ReflectionNamedType> */
50: public function getTypes(): array
51: {
52: return $this->types;
53: }
54:
55: /**
56: * @return false
57: */
58: public function allowsNull(): bool
59: {
60: return false;
61: }
62:
63: /** @return non-empty-string */
64: public function __toString(): string
65: {
66: // @infection-ignore-all UnwrapArrayMap: It works without array_map() as well but this is less magical
67: return implode('&', array_map(static fn (ReflectionNamedType $type): string => $type->__toString(), $this->types));
68: }
69: }
70: