Skip to content

Commit

Permalink
Reflection: added getReturnTypes(), getParameterTypes() and getProper…
Browse files Browse the repository at this point in the history
…tyTypes()
  • Loading branch information
dg committed Nov 25, 2020
1 parent 21a840d commit 19b3057
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 3 deletions.
47 changes: 44 additions & 3 deletions src/Utils/Reflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ public static function getReturnType(\ReflectionFunctionAbstract $func): ?string
}


/**
* Returns the types of return value of given function or method and normalizes `self`, `static`, and `parent` to actual class names.
*/
public static function getReturnTypes(\ReflectionFunctionAbstract $func): array
{
return self::getType($func, $func->getReturnType(), true);
}


/**
* Returns the type of given parameter and normalizes `self` and `parent` to the actual class names.
* If the parameter does not have a type, it returns null.
Expand All @@ -56,6 +65,15 @@ public static function getParameterType(\ReflectionParameter $param): ?string
}


/**
* Returns the types of given parameter and normalizes `self` and `parent` to the actual class names.
*/
public static function getParameterTypes(\ReflectionParameter $param): array
{
return self::getType($param, $param->getType(), true);
}


/**
* Returns the type of given property and normalizes `self` and `parent` to the actual class names.
* If the property does not have a type, it returns null.
Expand All @@ -67,18 +85,41 @@ public static function getPropertyType(\ReflectionProperty $prop): ?string
}


/**
* Returns the types of given property and normalizes `self` and `parent` to the actual class names.
*/
public static function getPropertyTypes(\ReflectionProperty $prop): array
{
return self::getType($prop, PHP_VERSION_ID >= 70400 ? $prop->getType() : null, true);
}


/**
* @param \ReflectionFunction|\ReflectionMethod|\ReflectionParameter|\ReflectionProperty $reflection
* @return string|array|null
*/
private static function getType($reflection, ?\ReflectionType $type): ?string
private static function getType($reflection, ?\ReflectionType $type, bool $asArray = false)
{
if ($type === null) {
return null;
return $asArray ? [] : null;

} elseif ($type instanceof \ReflectionNamedType) {
return self::normalizeType($type->getName(), $reflection);
$name = self::normalizeType($type->getName(), $reflection);
if ($asArray) {
return $type->allowsNull() && $type->getName() !== 'mixed'
? [$name, 'null']
: [$name];
}
return $name;

} elseif ($type instanceof \ReflectionUnionType) {
if ($asArray) {
$types = [];
foreach ($type->getTypes() as $type) {
$types[] = self::normalizeType($type->getName(), $reflection);
}
return $types;
}
throw new Nette\InvalidStateException('The ' . self::toString($reflection) . ' is not expected to have a union type.');

} else {
Expand Down
4 changes: 4 additions & 0 deletions tests/Utils/Reflection.getParameterType.80.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ Assert::same('callable', Reflection::getParameterType($params[3]));
Assert::same('A', Reflection::getParameterType($params[4]));
Assert::null(Reflection::getParameterType($params[5]));
Assert::same('Test\B', Reflection::getParameterType($params[6]));
Assert::same(['Test\B', 'null'], Reflection::getParameterTypes($params[6]));
Assert::same('mixed', Reflection::getParameterType($params[7]));
Assert::same(['mixed'], Reflection::getParameterTypes($params[7]));
Assert::same(['A', 'array'], Reflection::getParameterTypes($params[8]));
Assert::same(['A', 'array', 'null'], Reflection::getParameterTypes($params[9]));

Assert::exception(function () use ($params) {
Reflection::getParameterType($params[8]);
Expand Down
4 changes: 4 additions & 0 deletions tests/Utils/Reflection.getPropertyType.80.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ Assert::same('array', Reflection::getPropertyType($props[2]));
Assert::same('A', Reflection::getPropertyType($props[3]));
Assert::null(Reflection::getPropertyType($props[4]));
Assert::same('Test\B', Reflection::getPropertyType($props[5]));
Assert::same(['Test\B', 'null'], Reflection::getPropertyTypes($props[5]));
Assert::same('mixed', Reflection::getPropertyType($props[6]));
Assert::same(['mixed'], Reflection::getPropertyTypes($props[6]));
Assert::same(['A', 'array'], Reflection::getPropertyTypes($props[7]));
Assert::same(['A', 'array', 'null'], Reflection::getPropertyTypes($props[8]));

Assert::exception(function () use ($props) {
Reflection::getPropertyType($props[7]);
Expand Down
6 changes: 6 additions & 0 deletions tests/Utils/Reflection.getReturnType.80.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ namespace

Assert::same('NS\A', Reflection::getReturnType(new \ReflectionMethod(NS\A::class, 'nullableSelfType')));

Assert::same(['NS\A', 'array'], Reflection::getReturnTypes(new \ReflectionMethod(NS\A::class, 'unionType')));

Assert::same(['NS\A', 'array', 'null'], Reflection::getReturnTypes(new \ReflectionMethod(NS\A::class, 'nullableUnionType')));

Assert::exception(function () {
Reflection::getReturnType(new \ReflectionMethod(NS\A::class, 'unionType'));
}, Nette\InvalidStateException::class, 'The NS\A::unionType is not expected to have a union type.');
Expand All @@ -131,6 +135,8 @@ namespace

Assert::same('string', Reflection::getReturnType(new \ReflectionFunction('NS\nativeType')));

Assert::same(['NS\A', 'array'], Reflection::getReturnTypes(new \ReflectionFunction('NS\unionType')));

Assert::exception(function () {
Reflection::getReturnType(new \ReflectionFunction('NS\unionType'));
}, Nette\InvalidStateException::class, 'The NS\unionType is not expected to have a union type.');
Expand Down

0 comments on commit 19b3057

Please sign in to comment.