1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\Type;
4:
5: use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
6: use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
7: use PHPStan\PhpDocParser\Ast\Type\TypeNode;
8: use PHPStan\Type\Generic\TemplateTypeVariance;
9: use PHPStan\Type\Traits\LateResolvableTypeTrait;
10: use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
11: use function sprintf;
12:
13: /** @api */
14: class KeyOfType implements CompoundType, LateResolvableType
15: {
16:
17: use LateResolvableTypeTrait;
18: use NonGeneralizableTypeTrait;
19:
20: public function __construct(private Type $type)
21: {
22: }
23:
24: public function getType(): Type
25: {
26: return $this->type;
27: }
28:
29: public function getReferencedClasses(): array
30: {
31: return $this->type->getReferencedClasses();
32: }
33:
34: public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance): array
35: {
36: return $this->type->getReferencedTemplateTypes($positionVariance);
37: }
38:
39: public function equals(Type $type): bool
40: {
41: return $type instanceof self
42: && $this->type->equals($type->type);
43: }
44:
45: public function describe(VerbosityLevel $level): string
46: {
47: return sprintf('key-of<%s>', $this->type->describe($level));
48: }
49:
50: public function isResolvable(): bool
51: {
52: return !TypeUtils::containsTemplateType($this->type);
53: }
54:
55: protected function getResult(): Type
56: {
57: return $this->type->getIterableKeyType();
58: }
59:
60: /**
61: * @param callable(Type): Type $cb
62: */
63: public function traverse(callable $cb): Type
64: {
65: $type = $cb($this->type);
66:
67: if ($this->type === $type) {
68: return $this;
69: }
70:
71: return new self($type);
72: }
73:
74: public function traverseSimultaneously(Type $right, callable $cb): Type
75: {
76: if (!$right instanceof self) {
77: return $this;
78: }
79:
80: $type = $cb($this->type, $right->type);
81:
82: if ($this->type === $type) {
83: return $this;
84: }
85:
86: return new self($type);
87: }
88:
89: public function toPhpDocNode(): TypeNode
90: {
91: return new GenericTypeNode(new IdentifierTypeNode('key-of'), [$this->type->toPhpDocNode()]);
92: }
93:
94: /**
95: * @param mixed[] $properties
96: */
97: public static function __set_state(array $properties): Type
98: {
99: return new self(
100: $properties['type'],
101: );
102: }
103:
104: }
105: