1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\Type;
4:
5: use PHPStan\Reflection\ClassReflection;
6: use PHPStan\Reflection\ReflectionProviderStaticAccessor;
7: use PHPStan\TrinaryLogic;
8: use function sprintf;
9:
10: /** @api */
11: class ThisType extends StaticType
12: {
13:
14: /**
15: * @api
16: */
17: public function __construct(
18: ClassReflection $classReflection,
19: ?Type $subtractedType = null,
20: )
21: {
22: parent::__construct($classReflection, $subtractedType);
23: }
24:
25: public function changeBaseClass(ClassReflection $classReflection): StaticType
26: {
27: return new self($classReflection, $this->getSubtractedType());
28: }
29:
30: public function describe(VerbosityLevel $level): string
31: {
32: return sprintf('$this(%s)', $this->getStaticObjectType()->describe($level));
33: }
34:
35: public function isSuperTypeOf(Type $type): TrinaryLogic
36: {
37: if ($type instanceof self) {
38: return $this->getStaticObjectType()->isSuperTypeOf($type);
39: }
40:
41: if ($type instanceof CompoundType) {
42: return $type->isSubTypeOf($this);
43: }
44:
45: $parent = new parent($this->getClassReflection(), $this->getSubtractedType());
46:
47: return $parent->isSuperTypeOf($type)->and(TrinaryLogic::createMaybe());
48: }
49:
50: public function changeSubtractedType(?Type $subtractedType): Type
51: {
52: $type = parent::changeSubtractedType($subtractedType);
53: if ($type instanceof parent) {
54: return new self($type->getClassReflection(), $subtractedType);
55: }
56:
57: return $type;
58: }
59:
60: public function traverse(callable $cb): Type
61: {
62: $subtractedType = $this->getSubtractedType() !== null ? $cb($this->getSubtractedType()) : null;
63:
64: if ($subtractedType !== $this->getSubtractedType()) {
65: return new self(
66: $this->getClassReflection(),
67: $subtractedType,
68: );
69: }
70:
71: return $this;
72: }
73:
74: /**
75: * @param mixed[] $properties
76: */
77: public static function __set_state(array $properties): Type
78: {
79: $reflectionProvider = ReflectionProviderStaticAccessor::getInstance();
80: if ($reflectionProvider->hasClass($properties['baseClass'])) {
81: return new self($reflectionProvider->getClass($properties['baseClass']), $properties['subtractedType'] ?? null);
82: }
83:
84: return new ErrorType();
85: }
86:
87: }
88: