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