Skip to content

Commit

Permalink
[3.4] Fix support for PHP8 union types
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-grekas committed Jun 18, 2020
1 parent 82d9fc8 commit 0700b7f
Showing 1 changed file with 23 additions and 19 deletions.
42 changes: 23 additions & 19 deletions Extractor/ReflectionExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -187,26 +187,26 @@ private function extractFromMutator($class, $property)
$type = $this->extractFromReflectionType($reflectionType, $reflectionMethod);

// HHVM reports variadics with "array" but not builtin type hints
if (!$reflectionType->isBuiltin() && Type::BUILTIN_TYPE_ARRAY === $type->getBuiltinType()) {
if (1 === \count($type) && !$reflectionType->isBuiltin() && Type::BUILTIN_TYPE_ARRAY === $type[0]->getBuiltinType()) {
return null;
}
} 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);
$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());
$type = [new Type(Type::BUILTIN_TYPE_CALLABLE, $reflectionParameter->allowsNull())];
} else {
$type = new Type(Type::BUILTIN_TYPE_OBJECT, $reflectionParameter->allowsNull(), $this->resolveTypeName($info[1], $reflectionMethod));
$type = [new Type(Type::BUILTIN_TYPE_OBJECT, $reflectionParameter->allowsNull(), $this->resolveTypeName($info[1], $reflectionMethod))];
}
} else {
return null;
}

if (\in_array($prefix, $this->arrayMutatorPrefixes)) {
$type = new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $type);
if (1 === \count($type) && \in_array($prefix, $this->arrayMutatorPrefixes)) {
$type = [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $type[0])];
}

return [$type];
return $type;
}

/**
Expand All @@ -225,7 +225,7 @@ private function extractFromAccessor($class, $property)
}

if ($this->supportsParameterType && $reflectionType = $reflectionMethod->getReturnType()) {
return [$this->extractFromReflectionType($reflectionType, $reflectionMethod)];
return $this->extractFromReflectionType($reflectionType, $reflectionMethod);
}

return \in_array($prefix, ['is', 'can']) ? [new Type(Type::BUILTIN_TYPE_BOOL)] : null;
Expand All @@ -234,24 +234,28 @@ private function extractFromAccessor($class, $property)
/**
* Extracts data from the PHP 7 reflection type.
*
* @return Type
* @return Type[]
*/
private function extractFromReflectionType(\ReflectionType $reflectionType, \ReflectionMethod $reflectionMethod)
{
$phpTypeOrClass = $reflectionType instanceof \ReflectionNamedType ? $reflectionType->getName() : $reflectionType->__toString();
$types = [];
$nullable = $reflectionType->allowsNull();

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, $this->resolveTypeName($phpTypeOrClass, $reflectionMethod));
foreach ($reflectionType instanceof \ReflectionUnionType ? $reflectionType->getTypes() : [$reflectionType] as $type) {
$phpTypeOrClass = $reflectionType instanceof \ReflectionNamedType ? $reflectionType->getName() : (string) $type;

if (Type::BUILTIN_TYPE_ARRAY === $phpTypeOrClass) {
$types[] = new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true);
} elseif ('void' === $phpTypeOrClass || 'null' === $phpTypeOrClass) {
$types[] = new Type(Type::BUILTIN_TYPE_NULL, $nullable);
} elseif ($reflectionType->isBuiltin()) {
$types[] = new Type($phpTypeOrClass, $nullable);
} else {
$types[] = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $this->resolveTypeName($phpTypeOrClass, $reflectionMethod));
}
}

return $type;
return $types;
}

private function resolveTypeName($name, \ReflectionMethod $reflectionMethod)
Expand Down

0 comments on commit 0700b7f

Please sign in to comment.