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 $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 $this */
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: /** @return false */
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 function (ReflectionNamedType $type) : string {
66: return $type->__toString();
67: }, $this->types));
68: }
69: }
70: