Skip to content

Commit b2a8948

Browse files
cdosofteiSimonFrings
authored andcommitted
Adjustments for 7.1, support for union types, test suite updates
1 parent 2279162 commit b2a8948

3 files changed

Lines changed: 92 additions & 6 deletions

File tree

src/functions.php

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,11 +342,33 @@ function _checkTypehint(callable $callback, \Throwable $reason): bool
342342
return true;
343343
}
344344

345-
$expectedClass = $parameters[0]->getClass();
345+
$type = $parameters[0]->getType();
346346

347-
if (!$expectedClass) {
347+
if (!$type) {
348348
return true;
349349
}
350350

351-
return $expectedClass->isInstance($reason);
351+
$types = [$type];
352+
353+
if ($type instanceof \ReflectionUnionType) {
354+
$types = $type->getTypes();
355+
}
356+
357+
$mismatched = false;
358+
359+
foreach ($types as $type) {
360+
if (!$type || $type->isBuiltin()) {
361+
continue;
362+
}
363+
364+
$expectedClass = $type->getName();
365+
366+
if ($reason instanceof $expectedClass) {
367+
return true;
368+
}
369+
370+
$mismatched = true;
371+
}
372+
373+
return !$mismatched;
352374
}

tests/ErrorCollector.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ public function start()
1010
{
1111
$errors = [];
1212

13-
set_error_handler(function ($errno, $errstr, $errfile, $errline, $errcontext) use (&$errors) {
14-
$errors[] = compact('errno', 'errstr', 'errfile', 'errline', 'errcontext');
13+
set_error_handler(function ($errno, $errstr, $errfile, $errline) use (&$errors) {
14+
$errors[] = compact('errno', 'errstr', 'errfile', 'errline');
1515
});
1616

1717
$this->errors = &$errors;

tests/FunctionCheckTypehintTest.php

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,49 @@ public function shouldAcceptStaticClassCallbackWithTypehint()
4242
self::assertFalse(_checkTypehint([TestCallbackWithTypehintClass::class, 'testCallbackStatic'], new Exception()));
4343
}
4444

45+
/**
46+
* @test
47+
* @requires PHP 8
48+
*/
49+
public function shouldAcceptClosureCallbackWithUnionTypehint()
50+
{
51+
eval(
52+
'namespace React\Promise;' .
53+
'self::assertTrue(_checkTypehint(function (\RuntimeException|\InvalidArgumentException $e) {}, new \InvalidArgumentException()));' .
54+
'self::assertFalse(_checkTypehint(function (\RuntimeException|\InvalidArgumentException $e) {}, new \Exception()));'
55+
);
56+
}
57+
58+
/**
59+
* @test
60+
* @requires PHP 8
61+
*/
62+
public function shouldAcceptInvokableObjectCallbackWithUnionTypehint()
63+
{
64+
self::assertTrue(_checkTypehint(new TestCallbackWithUnionTypehintClass(), new InvalidArgumentException()));
65+
self::assertFalse(_checkTypehint(new TestCallbackWithUnionTypehintClass(), new Exception()));
66+
}
67+
68+
/**
69+
* @test
70+
* @requires PHP 8
71+
*/
72+
public function shouldAcceptObjectMethodCallbackWithUnionTypehint()
73+
{
74+
self::assertTrue(_checkTypehint([new TestCallbackWithUnionTypehintClass(), 'testCallback'], new InvalidArgumentException()));
75+
self::assertFalse(_checkTypehint([new TestCallbackWithUnionTypehintClass(), 'testCallback'], new Exception()));
76+
}
77+
78+
/**
79+
* @test
80+
* @requires PHP 8
81+
*/
82+
public function shouldAcceptStaticClassCallbackWithUnionTypehint()
83+
{
84+
self::assertTrue(_checkTypehint([TestCallbackWithUnionTypehintClass::class, 'testCallbackStatic'], new InvalidArgumentException()));
85+
self::assertFalse(_checkTypehint([TestCallbackWithUnionTypehintClass::class, 'testCallbackStatic'], new Exception()));
86+
}
87+
4588
/** @test */
4689
public function shouldAcceptClosureCallbackWithoutTypehint()
4790
{
@@ -52,7 +95,7 @@ public function shouldAcceptClosureCallbackWithoutTypehint()
5295
/** @test */
5396
public function shouldAcceptFunctionStringCallbackWithoutTypehint()
5497
{
55-
self::assertTrue(_checkTypehint(new TestCallbackWithTypehintClass(), new InvalidArgumentException()));
98+
self::assertTrue(_checkTypehint(new TestCallbackWithoutTypehintClass(), new InvalidArgumentException()));
5699
}
57100

58101
/** @test */
@@ -97,6 +140,27 @@ public static function testCallbackStatic(InvalidArgumentException $e)
97140
}
98141
}
99142

143+
if (defined('PHP_MAJOR_VERSION') && (PHP_MAJOR_VERSION >= 8)) {
144+
eval(<<<EOT
145+
namespace React\Promise;
146+
class TestCallbackWithUnionTypehintClass
147+
{
148+
public function __invoke(\RuntimeException|\InvalidArgumentException \$e)
149+
{
150+
}
151+
152+
public function testCallback(\RuntimeException|\InvalidArgumentException \$e)
153+
{
154+
}
155+
156+
public static function testCallbackStatic(\RuntimeException|\InvalidArgumentException \$e)
157+
{
158+
}
159+
}
160+
EOT
161+
);
162+
}
163+
100164
class TestCallbackWithoutTypehintClass
101165
{
102166
public function __invoke()

0 commit comments

Comments
 (0)