Skip to content

Commit ce1fb91

Browse files
committed
[DX] Fix message on callable filter returns union or intersection
1 parent 4913af4 commit ce1fb91

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

src/Assert/Filter.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@
77
use Closure;
88
use InvalidArgumentException;
99
use ReflectionFunction;
10+
use ReflectionIntersectionType;
1011
use ReflectionMethod;
1112
use ReflectionNamedType;
13+
use ReflectionUnionType;
1214

15+
use function array_map;
1316
use function gettype;
17+
use function implode;
1418
use function is_object;
1519
use function sprintf;
1620

@@ -30,6 +34,21 @@ public static function boolean(callable $filter): void
3034

3135
$returnType = $reflection->getReturnType();
3236

37+
if ($returnType instanceof ReflectionUnionType || $returnType instanceof ReflectionIntersectionType) {
38+
$separator = $returnType instanceof ReflectionUnionType ? '|' : '&';
39+
/** @var ReflectionNamedType[] $types */
40+
$types = $returnType->getTypes();
41+
throw new InvalidArgumentException(
42+
sprintf(
43+
'Expected a bool return type on callable filter, %s given',
44+
implode($separator, array_map(
45+
static fn (ReflectionNamedType $reflectionNamedType): string => $reflectionNamedType->getName(),
46+
$types
47+
))
48+
)
49+
);
50+
}
51+
3352
if (! $returnType instanceof ReflectionNamedType) {
3453
throw new InvalidArgumentException('Expected a bool return type on callable filter, null given');
3554
}

tests/FilterTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,37 @@ public function __invoke(int $datum): string
6868

6969
AtLeast::once($data, $filter);
7070
}
71+
72+
public function testWithUnionReturnTypeCallable(): void
73+
{
74+
$this->expectException(InvalidArgumentException::class);
75+
$this->expectExceptionMessage('Expected a bool return type on callable filter, string|bool given');
76+
77+
$data = [1, 2, 3];
78+
$filter = new class {
79+
public function __invoke(int $datum): string|bool
80+
{
81+
return 'test';
82+
}
83+
};
84+
85+
AtLeast::once($data, $filter);
86+
}
87+
88+
public function testWithIntersectionTypeCallable(): void
89+
{
90+
$this->expectException(InvalidArgumentException::class);
91+
$this->expectExceptionMessage(
92+
'Expected a bool return type on callable filter, ArrayLookup\Tests\A&ArrayLookup\Tests\B given'
93+
);
94+
95+
$data = [1, 2, 3];
96+
$filter = new class {
97+
public function __invoke(int $datum): A&B
98+
{
99+
}
100+
};
101+
102+
AtLeast::once($data, $filter);
103+
}
71104
}

0 commit comments

Comments
 (0)