[PropertyInfo] Fix edge cases in ReflectionExtractor
This commit is contained in:
parent
7f0ae27521
commit
bffdfad41e
@ -44,6 +44,13 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
|
||||
*/
|
||||
public static $arrayMutatorPrefixes = array('add', 'remove');
|
||||
|
||||
private $supportsParameterType;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->supportsParameterType = method_exists('ReflectionParameter', 'getType');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@ -134,68 +141,33 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
|
||||
$reflectionParameters = $reflectionMethod->getParameters();
|
||||
$reflectionParameter = $reflectionParameters[0];
|
||||
|
||||
$arrayMutator = in_array($prefix, self::$arrayMutatorPrefixes);
|
||||
|
||||
if (method_exists($reflectionParameter, 'getType') && $reflectionType = $reflectionParameter->getType()) {
|
||||
$fromReflectionType = $this->extractFromReflectionType($reflectionType);
|
||||
|
||||
if (!$arrayMutator) {
|
||||
return array($fromReflectionType);
|
||||
if ($this->supportsParameterType) {
|
||||
if (!$reflectionType = $reflectionParameter->getType()) {
|
||||
return;
|
||||
}
|
||||
$type = $this->extractFromReflectionType($reflectionType);
|
||||
|
||||
$phpType = Type::BUILTIN_TYPE_ARRAY;
|
||||
$collectionKeyType = new Type(Type::BUILTIN_TYPE_INT);
|
||||
$collectionValueType = $fromReflectionType;
|
||||
}
|
||||
|
||||
if ($reflectionParameter->isArray()) {
|
||||
$phpType = Type::BUILTIN_TYPE_ARRAY;
|
||||
$collection = true;
|
||||
}
|
||||
|
||||
if ($arrayMutator) {
|
||||
$collection = true;
|
||||
$nullable = false;
|
||||
$collectionNullable = $reflectionParameter->allowsNull();
|
||||
} else {
|
||||
$nullable = $reflectionParameter->allowsNull();
|
||||
$collectionNullable = false;
|
||||
}
|
||||
|
||||
if (!isset($collection)) {
|
||||
$collection = false;
|
||||
}
|
||||
|
||||
if (method_exists($reflectionParameter, 'isCallable') && $reflectionParameter->isCallable()) {
|
||||
$phpType = Type::BUILTIN_TYPE_CALLABLE;
|
||||
}
|
||||
|
||||
if ($typeHint = $reflectionParameter->getClass()) {
|
||||
if ($collection) {
|
||||
$phpType = Type::BUILTIN_TYPE_ARRAY;
|
||||
$collectionKeyType = new Type(Type::BUILTIN_TYPE_INT);
|
||||
$collectionValueType = new Type(Type::BUILTIN_TYPE_OBJECT, $collectionNullable, $typeHint->name);
|
||||
// HHVM reports variadics with "array" but not builtin type hints
|
||||
if (!$reflectionType->isBuiltin() && Type::BUILTIN_TYPE_ARRAY === $type->getBuiltinType()) {
|
||||
return;
|
||||
}
|
||||
} elseif (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/', $reflectionParameter, $info)) {
|
||||
if (Type::BUILTIN_TYPE_ARRAY === $info[1]) {
|
||||
$type = new Type(Type::BUILTIN_TYPE_ARRAY, $reflectionParameter->allowsNull(), null, true);
|
||||
} elseif (Type::BUILTIN_TYPE_CALLABLE === $info[1]) {
|
||||
$type = new Type(Type::BUILTIN_TYPE_CALLABLE, $reflectionParameter->allowsNull());
|
||||
} else {
|
||||
$phpType = Type::BUILTIN_TYPE_OBJECT;
|
||||
$typeClass = $typeHint->name;
|
||||
$type = new Type(Type::BUILTIN_TYPE_OBJECT, $reflectionParameter->allowsNull(), $info[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing useful extracted
|
||||
if (!isset($phpType)) {
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
return array(
|
||||
new Type(
|
||||
$phpType,
|
||||
$nullable,
|
||||
isset($typeClass) ? $typeClass : null,
|
||||
$collection,
|
||||
isset($collectionKeyType) ? $collectionKeyType : null,
|
||||
isset($collectionValueType) ? $collectionValueType : null
|
||||
),
|
||||
);
|
||||
if (in_array($prefix, self::$arrayMutatorPrefixes)) {
|
||||
$type = new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $type);
|
||||
}
|
||||
|
||||
return array($type);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -213,7 +185,7 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
|
||||
return;
|
||||
}
|
||||
|
||||
if (method_exists($reflectionMethod, 'getReturnType') && $reflectionType = $reflectionMethod->getReturnType()) {
|
||||
if ($this->supportsParameterType && $reflectionType = $reflectionMethod->getReturnType()) {
|
||||
return array($this->extractFromReflectionType($reflectionType));
|
||||
}
|
||||
|
||||
@ -231,15 +203,15 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
|
||||
*/
|
||||
private function extractFromReflectionType(\ReflectionType $reflectionType)
|
||||
{
|
||||
$phpTypeOrClass = method_exists($reflectionType, 'getName') ? $reflectionType->getName() : (string) $reflectionType;
|
||||
$phpTypeOrClass = $reflectionType instanceof \ReflectionNamedType ? $reflectionType->getName() : $reflectionType->__toString();
|
||||
$nullable = $reflectionType->allowsNull();
|
||||
|
||||
if ($reflectionType->isBuiltin()) {
|
||||
if (Type::BUILTIN_TYPE_ARRAY === $phpTypeOrClass) {
|
||||
$type = new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true);
|
||||
} else {
|
||||
$type = new Type($phpTypeOrClass, $nullable);
|
||||
}
|
||||
if (Type::BUILTIN_TYPE_ARRAY === $phpTypeOrClass) {
|
||||
$type = new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true);
|
||||
} elseif ('void' === $phpTypeOrClass) {
|
||||
$type = new Type(Type::BUILTIN_TYPE_NULL, $nullable);
|
||||
} elseif ($reflectionType->isBuiltin()) {
|
||||
$type = new Type($phpTypeOrClass, $nullable);
|
||||
} else {
|
||||
$type = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $phpTypeOrClass);
|
||||
}
|
||||
|
@ -107,6 +107,7 @@ class ReflectionExtractorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
return array(
|
||||
array('foo', array(new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true))),
|
||||
array('buz', array(new Type(Type::BUILTIN_TYPE_NULL))),
|
||||
array('bar', array(new Type(Type::BUILTIN_TYPE_INT, true))),
|
||||
array('baz', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING)))),
|
||||
array('donotexist', null),
|
||||
|
@ -20,6 +20,10 @@ class Php71Dummy
|
||||
{
|
||||
}
|
||||
|
||||
public function getBuz(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function setBar(?int $bar)
|
||||
{
|
||||
}
|
||||
|
Reference in New Issue
Block a user