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