Skip to content

Commit

Permalink
Fixed ReflectionParameter::isArray() and isCallable()
Browse files Browse the repository at this point in the history
  • Loading branch information
kukulich committed Oct 12, 2021
1 parent a4c07be commit c1a6982
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 21 deletions.
33 changes: 30 additions & 3 deletions src/Reflection/ReflectionParameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
use function is_array;
use function is_object;
use function is_string;
use function preg_match;
use function sprintf;
use function strtolower;

Expand Down Expand Up @@ -409,15 +408,43 @@ public function removeType(): void
*/
public function isArray(): bool
{
return preg_match('~^\??array$~i', (string) $this->getType()) === 1;
return $this->isType($this->getType(), 'array');
}

/**
* Is this parameter a callable?
*/
public function isCallable(): bool
{
return preg_match('~^\??callable$~i', (string) $this->getType()) === 1;
return $this->isType($this->getType(), 'callable');
}

/**
* For isArray() and isCallable().
*/
private function isType(ReflectionNamedType|ReflectionUnionType|null $typeReflection, string $type): bool
{
if ($typeReflection === null) {
return false;
}

if ($typeReflection instanceof ReflectionUnionType) {
$unionTypes = $typeReflection->getTypes();

if (count($unionTypes) > 2) {
return false;
}

foreach ($unionTypes as $unionTypeReflection) {
if ($this->isType($unionTypeReflection, $type)) {
return true;
}
}

return false;
}

return strtolower($typeReflection->getName()) === $type;
}

/**
Expand Down
28 changes: 28 additions & 0 deletions test/unit/Fixture/Methods.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,34 @@ public function methodWithExplicitTypedParameters(
) {
}

public function methodIsArrayParameters(
$noTypeParameter,
bool $boolParameter,
array $arrayParameter,
ArRaY $arrayCaseInsensitiveParameter,
?array $nullableArrayParameter,
null|array $unionArrayParameterNullFirst,
array|null $unionArrayParameterNullLast,
string|bool $unionNotArrayParameter,
array|string|null $unionWithArrayNotArrayParameter,
)
{
}

public function methodIsCallableParameters(
$noTypeParameter,
bool $boolParameter,
callable $callableParameter,
cAlLaBlE $callableCaseInsensitiveParameter,
?callable $nullableCallableParameter,
null|callable $unionCallableParameterNullFirst,
callable|null $unionCallableParameterNullLast,
string|bool $unionNotCallableParameter,
callable|string|null $unionWithCallableNotCallableParameter,
)
{
}

public function methodWithVariadic($nonVariadicParameter, ...$variadicParameter)
{
}
Expand Down
4 changes: 2 additions & 2 deletions test/unit/Reflection/ReflectionClassTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ public function getMethodsWithFilterDataProvider(): array
[CoreReflectionMethod::IS_STATIC, 1],
[CoreReflectionMethod::IS_ABSTRACT, 1],
[CoreReflectionMethod::IS_FINAL, 1],
[CoreReflectionMethod::IS_PUBLIC, 17],
[CoreReflectionMethod::IS_PUBLIC, 19],
[CoreReflectionMethod::IS_PROTECTED, 1],
[CoreReflectionMethod::IS_PRIVATE, 1],
[
Expand All @@ -186,7 +186,7 @@ public function getMethodsWithFilterDataProvider(): array
CoreReflectionMethod::IS_PUBLIC |
CoreReflectionMethod::IS_PROTECTED |
CoreReflectionMethod::IS_PRIVATE,
19,
21,
],
];
}
Expand Down
60 changes: 44 additions & 16 deletions test/unit/Reflection/ReflectionParameterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -401,30 +401,58 @@ public function testRemoveType(): void
);
}

public function testIsCallable(): void
public function isCallableProvider(): array
{
$classInfo = $this->reflector->reflectClass(Methods::class);

$method = $classInfo->getMethod('methodWithExplicitTypedParameters');
return [
['noTypeParameter', false],
['boolParameter', false],
['callableParameter', true],
['callableCaseInsensitiveParameter', true],
['nullableCallableParameter', true],
['unionCallableParameterNullFirst', true],
['unionCallableParameterNullLast', true],
['unionNotCallableParameter', false],
['unionWithCallableNotCallableParameter', false],
];
}

$nonCallableParam = $method->getParameter('stdClassParameter');
self::assertFalse($nonCallableParam->isCallable());
/**
* @dataProvider isCallableProvider
*/
public function testIsCallable(string $parameterName, bool $isCallable): void
{
$classReflection = $this->reflector->reflectClass(Methods::class);
$methodReflection = $classReflection->getMethod('methodIsCallableParameters');
$parameterReflection = $methodReflection->getParameter($parameterName);

$callableParam = $method->getParameter('callableParameter');
self::assertTrue($callableParam->isCallable());
self::assertSame($isCallable, $parameterReflection->isCallable());
}

public function testIsArray(): void
public function isArrayProvider(): array
{
$classInfo = $this->reflector->reflectClass(Methods::class);

$method = $classInfo->getMethod('methodWithExplicitTypedParameters');
return [
['noTypeParameter', false],
['boolParameter', false],
['arrayParameter', true],
['arrayCaseInsensitiveParameter', true],
['nullableArrayParameter', true],
['unionArrayParameterNullFirst', true],
['unionArrayParameterNullLast', true],
['unionNotArrayParameter', false],
['unionWithArrayNotArrayParameter', false],
];
}

$nonArrayParam = $method->getParameter('stdClassParameter');
self::assertFalse($nonArrayParam->isArray());
/**
* @dataProvider isArrayProvider
*/
public function testIsArray(string $parameterName, bool $isArray): void
{
$classReflection = $this->reflector->reflectClass(Methods::class);
$methodReflection = $classReflection->getMethod('methodIsArrayParameters');
$parameterReflection = $methodReflection->getParameter($parameterName);

$arrayParam = $method->getParameter('arrayParameter');
self::assertTrue($arrayParam->isArray());
self::assertSame($isArray, $parameterReflection->isArray());
}

public function testIsVariadic(): void
Expand Down

0 comments on commit c1a6982

Please sign in to comment.