1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\Analyser;
4:
5: use PHPStan\ShouldNotHappenException;
6: use PHPStan\Turbo\ShadowedByTurboExtension;
7:
8: /**
9: * @api
10: */
11: #[ShadowedByTurboExtension(implementation: __DIR__ . '/../../turbo-ext/src/TypeSpecifierContext.cpp')]
12: final class TypeSpecifierContext
13: {
14:
15: public const CONTEXT_TRUE = 0b0001;
16: public const CONTEXT_TRUTHY_BUT_NOT_TRUE = 0b0010;
17: public const CONTEXT_TRUTHY = self::CONTEXT_TRUE | self::CONTEXT_TRUTHY_BUT_NOT_TRUE;
18: public const CONTEXT_FALSE = 0b0100;
19: public const CONTEXT_FALSEY_BUT_NOT_FALSE = 0b1000;
20: public const CONTEXT_FALSEY = self::CONTEXT_FALSE | self::CONTEXT_FALSEY_BUT_NOT_FALSE;
21: public const CONTEXT_BITMASK = 0b1111;
22:
23: /** @var self[] */
24: private static array $registry;
25:
26: private function __construct(private ?int $value)
27: {
28: }
29:
30: private static function create(?int $value): self
31: {
32: $key = $value ?? '';
33: self::$registry[$key] ??= new self($value);
34: return self::$registry[$key];
35: }
36:
37: public static function createTrue(): self
38: {
39: return self::create(self::CONTEXT_TRUE);
40: }
41:
42: public static function createTruthy(): self
43: {
44: return self::create(self::CONTEXT_TRUTHY);
45: }
46:
47: public static function createFalse(): self
48: {
49: return self::create(self::CONTEXT_FALSE);
50: }
51:
52: public static function createFalsey(): self
53: {
54: return self::create(self::CONTEXT_FALSEY);
55: }
56:
57: public static function createNull(): self
58: {
59: return self::create(null);
60: }
61:
62: public function negate(): self
63: {
64: if ($this->value === null) {
65: throw new ShouldNotHappenException();
66: }
67: return self::create(~$this->value & self::CONTEXT_BITMASK);
68: }
69:
70: public function true(): bool
71: {
72: return $this->value !== null && (bool) ($this->value & self::CONTEXT_TRUE);
73: }
74:
75: public function truthy(): bool
76: {
77: return $this->value !== null && (bool) ($this->value & self::CONTEXT_TRUTHY);
78: }
79:
80: public function false(): bool
81: {
82: return $this->value !== null && (bool) ($this->value & self::CONTEXT_FALSE);
83: }
84:
85: public function falsey(): bool
86: {
87: return $this->value !== null && (bool) ($this->value & self::CONTEXT_FALSEY);
88: }
89:
90: /** Whether the branch admits falsey values other than `false`, e.g. `null`. */
91: public function falseyButNotFalse(): bool
92: {
93: return $this->value !== null && (bool) ($this->value & self::CONTEXT_FALSEY_BUT_NOT_FALSE);
94: }
95:
96: public function null(): bool
97: {
98: return $this->value === null;
99: }
100:
101: }
102: