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