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