Skip to content

Commit

Permalink
Merge pull request #197 from SimonFrings/deprecated
Browse files Browse the repository at this point in the history
Add PHP 8 support and address deprecation of ReflectionType::getClass()
  • Loading branch information
WyriHaximus authored Oct 12, 2021
2 parents babade6 + 5ea3fe8 commit d649e30
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 48 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ jobs:
strategy:
matrix:
php:
- 8.0
- 7.4
- 7.3
- 7.2
Expand Down
28 changes: 25 additions & 3 deletions src/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -342,11 +342,33 @@ function _checkTypehint(callable $callback, \Throwable $reason): bool
return true;
}

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

if (!$expectedClass) {
if (!$type) {
return true;
}

return $expectedClass->isInstance($reason);
$types = [$type];

if ($type instanceof \ReflectionUnionType) {
$types = $type->getTypes();
}

$mismatched = false;

foreach ($types as $type) {
if (!$type || $type->isBuiltin()) {
continue;
}

$expectedClass = $type->getName();

if ($reason instanceof $expectedClass) {
return true;
}

$mismatched = true;
}

return !$mismatched;
}
4 changes: 2 additions & 2 deletions tests/ErrorCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ public function start()
{
$errors = [];

set_error_handler(function ($errno, $errstr, $errfile, $errline, $errcontext) use (&$errors) {
$errors[] = compact('errno', 'errstr', 'errfile', 'errline', 'errcontext');
set_error_handler(function ($errno, $errstr, $errfile, $errline) use (&$errors) {
$errors[] = compact('errno', 'errstr', 'errfile', 'errline');
});

$this->errors = &$errors;
Expand Down
99 changes: 56 additions & 43 deletions tests/FunctionCheckTypehintTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,75 @@ public function shouldAcceptClosureCallbackWithTypehint()
/** @test */
public function shouldAcceptFunctionStringCallbackWithTypehint()
{
self::assertTrue(_checkTypehint(new TestCallbackWithTypehintClass(), new InvalidArgumentException()));
self::assertFalse(_checkTypehint(new TestCallbackWithTypehintClass(), new Exception()));
self::assertTrue(_checkTypehint(new CallbackWithTypehintClass(), new InvalidArgumentException()));
self::assertFalse(_checkTypehint(new CallbackWithTypehintClass(), new Exception()));
}

/** @test */
public function shouldAcceptInvokableObjectCallbackWithTypehint()
{
self::assertTrue(_checkTypehint(new TestCallbackWithTypehintClass(), new InvalidArgumentException()));
self::assertFalse(_checkTypehint(new TestCallbackWithTypehintClass(), new Exception()));
self::assertTrue(_checkTypehint(new CallbackWithTypehintClass(), new InvalidArgumentException()));
self::assertFalse(_checkTypehint(new CallbackWithTypehintClass(), new Exception()));
}

/** @test */
public function shouldAcceptObjectMethodCallbackWithTypehint()
{
self::assertTrue(_checkTypehint([new TestCallbackWithTypehintClass(), 'testCallback'], new InvalidArgumentException()));
self::assertFalse(_checkTypehint([new TestCallbackWithTypehintClass(), 'testCallback'], new Exception()));
self::assertTrue(_checkTypehint([new CallbackWithTypehintClass(), 'testCallback'], new InvalidArgumentException()));
self::assertFalse(_checkTypehint([new CallbackWithTypehintClass(), 'testCallback'], new Exception()));
}

/** @test */
public function shouldAcceptStaticClassCallbackWithTypehint()
{
self::assertTrue(_checkTypehint([TestCallbackWithTypehintClass::class, 'testCallbackStatic'], new InvalidArgumentException()));
self::assertFalse(_checkTypehint([TestCallbackWithTypehintClass::class, 'testCallbackStatic'], new Exception()));
self::assertTrue(_checkTypehint([CallbackWithTypehintClass::class, 'testCallbackStatic'], new InvalidArgumentException()));
self::assertFalse(_checkTypehint([CallbackWithTypehintClass::class, 'testCallbackStatic'], new Exception()));
}

/** @test */
/**
* @test
* @requires PHP 8
*/
public function shouldAcceptClosureCallbackWithUnionTypehint()
{
eval(
'namespace React\Promise;' .
'self::assertTrue(_checkTypehint(function (\RuntimeException|\InvalidArgumentException $e) {}, new \InvalidArgumentException()));' .
'self::assertFalse(_checkTypehint(function (\RuntimeException|\InvalidArgumentException $e) {}, new \Exception()));'
);
}

/**
* @test
* @requires PHP 8
*/
public function shouldAcceptInvokableObjectCallbackWithUnionTypehint()
{
self::assertTrue(_checkTypehint(new CallbackWithUnionTypehintClass(), new InvalidArgumentException()));
self::assertFalse(_checkTypehint(new CallbackWithUnionTypehintClass(), new Exception()));
}

/**
* @test
* @requires PHP 8
*/
public function shouldAcceptObjectMethodCallbackWithUnionTypehint()
{
self::assertTrue(_checkTypehint([new CallbackWithUnionTypehintClass(), 'testCallback'], new InvalidArgumentException()));
self::assertFalse(_checkTypehint([new CallbackWithUnionTypehintClass(), 'testCallback'], new Exception()));
}

/**
* @test
* @requires PHP 8
*/
public function shouldAcceptStaticClassCallbackWithUnionTypehint()
{
self::assertTrue(_checkTypehint([CallbackWithUnionTypehintClass::class, 'testCallbackStatic'], new InvalidArgumentException()));
self::assertFalse(_checkTypehint([CallbackWithUnionTypehintClass::class, 'testCallbackStatic'], new Exception()));
}

/** @test */
public function shouldAcceptClosureCallbackWithoutTypehint()
{
self::assertTrue(_checkTypehint(function (InvalidArgumentException $e) {
Expand All @@ -52,25 +95,25 @@ public function shouldAcceptClosureCallbackWithoutTypehint()
/** @test */
public function shouldAcceptFunctionStringCallbackWithoutTypehint()
{
self::assertTrue(_checkTypehint(new TestCallbackWithTypehintClass(), new InvalidArgumentException()));
self::assertTrue(_checkTypehint(new CallbackWithoutTypehintClass(), new InvalidArgumentException()));
}

/** @test */
public function shouldAcceptInvokableObjectCallbackWithoutTypehint()
{
self::assertTrue(_checkTypehint(new TestCallbackWithoutTypehintClass(), new InvalidArgumentException()));
self::assertTrue(_checkTypehint(new CallbackWithoutTypehintClass(), new InvalidArgumentException()));
}

/** @test */
public function shouldAcceptObjectMethodCallbackWithoutTypehint()
{
self::assertTrue(_checkTypehint([new TestCallbackWithoutTypehintClass(), 'testCallback'], new InvalidArgumentException()));
self::assertTrue(_checkTypehint([new CallbackWithoutTypehintClass(), 'testCallback'], new InvalidArgumentException()));
}

/** @test */
public function shouldAcceptStaticClassCallbackWithoutTypehint()
{
self::assertTrue(_checkTypehint([TestCallbackWithoutTypehintClass::class, 'testCallbackStatic'], new InvalidArgumentException()));
self::assertTrue(_checkTypehint([CallbackWithoutTypehintClass::class, 'testCallbackStatic'], new InvalidArgumentException()));
}
}

Expand All @@ -81,33 +124,3 @@ function testCallbackWithTypehint(InvalidArgumentException $e)
function testCallbackWithoutTypehint()
{
}

class TestCallbackWithTypehintClass
{
public function __invoke(InvalidArgumentException $e)
{
}

public function testCallback(InvalidArgumentException $e)
{
}

public static function testCallbackStatic(InvalidArgumentException $e)
{
}
}

class TestCallbackWithoutTypehintClass
{
public function __invoke()
{
}

public function testCallback()
{
}

public static function testCallbackStatic()
{
}
}
20 changes: 20 additions & 0 deletions tests/fixtures/CallbackWithTypehintClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace React\Promise;

use InvalidArgumentException;

class CallbackWithTypehintClass
{
public function __invoke(InvalidArgumentException $e)
{
}

public function testCallback(InvalidArgumentException $e)
{
}

public static function testCallbackStatic(InvalidArgumentException $e)
{
}
}
21 changes: 21 additions & 0 deletions tests/fixtures/CallbackWithUnionTypehintClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace React\Promise;

use InvalidArgumentException;
use RuntimeException;

class CallbackWithUnionTypehintClass
{
public function __invoke(RuntimeException|InvalidArgumentException $e)
{
}

public function testCallback(RuntimeException|InvalidArgumentException $e)
{
}

public static function testCallbackStatic(RuntimeException|InvalidArgumentException $e)
{
}
}
18 changes: 18 additions & 0 deletions tests/fixtures/CallbackWithoutTypehintClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace React\Promise;

class CallbackWithoutTypehintClass
{
public function __invoke()
{
}

public function testCallback()
{
}

public static function testCallbackStatic()
{
}
}

0 comments on commit d649e30

Please sign in to comment.