1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\Type;
4:
5: use PHPStan\ShouldNotHappenException;
6: use PHPStan\TrinaryLogic;
7: use function array_map;
8: use function array_merge;
9: use function array_unique;
10: use function array_values;
11:
12: /**
13: * @api
14: * @final
15: */
16: class AcceptsResult
17: {
18:
19: /**
20: * @api
21: * @param list<string> $reasons
22: */
23: public function __construct(
24: public readonly TrinaryLogic $result,
25: public readonly array $reasons,
26: )
27: {
28: }
29:
30: public function yes(): bool
31: {
32: return $this->result->yes();
33: }
34:
35: public function maybe(): bool
36: {
37: return $this->result->maybe();
38: }
39:
40: public function no(): bool
41: {
42: return $this->result->no();
43: }
44:
45: public static function createYes(): self
46: {
47: return new self(TrinaryLogic::createYes(), []);
48: }
49:
50: /**
51: * @param list<string> $reasons
52: */
53: public static function createNo(array $reasons = []): self
54: {
55: return new self(TrinaryLogic::createNo(), $reasons);
56: }
57:
58: public static function createMaybe(): self
59: {
60: return new self(TrinaryLogic::createMaybe(), []);
61: }
62:
63: public static function createFromBoolean(bool $value): self
64: {
65: return new self(TrinaryLogic::createFromBoolean($value), []);
66: }
67:
68: public function and(self $other): self
69: {
70: return new self(
71: $this->result->and($other->result),
72: array_values(array_unique(array_merge($this->reasons, $other->reasons))),
73: );
74: }
75:
76: public function or(self $other): self
77: {
78: return new self(
79: $this->result->or($other->result),
80: array_values(array_unique(array_merge($this->reasons, $other->reasons))),
81: );
82: }
83:
84: /**
85: * @param callable(string): string $cb
86: */
87: public function decorateReasons(callable $cb): self
88: {
89: $reasons = [];
90: foreach ($this->reasons as $reason) {
91: $reasons[] = $cb($reason);
92: }
93:
94: return new self($this->result, $reasons);
95: }
96:
97: public static function extremeIdentity(self ...$operands): self
98: {
99: if ($operands === []) {
100: throw new ShouldNotHappenException();
101: }
102:
103: $result = TrinaryLogic::extremeIdentity(...array_map(static fn (self $result) => $result->result, $operands));
104: $reasons = [];
105: foreach ($operands as $operand) {
106: foreach ($operand->reasons as $reason) {
107: $reasons[] = $reason;
108: }
109: }
110:
111: return new self($result, $reasons);
112: }
113:
114: public static function maxMin(self ...$operands): self
115: {
116: if ($operands === []) {
117: throw new ShouldNotHappenException();
118: }
119:
120: $result = TrinaryLogic::maxMin(...array_map(static fn (self $result) => $result->result, $operands));
121: $reasons = [];
122: foreach ($operands as $operand) {
123: foreach ($operand->reasons as $reason) {
124: $reasons[] = $reason;
125: }
126: }
127:
128: return new self($result, $reasons);
129: }
130:
131: }
132: