Skip to content

Commit 0700b7f

Browse files
[3.4] Fix support for PHP8 union types
1 parent 82d9fc8 commit 0700b7f

File tree

1 file changed

+23
-19
lines changed

1 file changed

+23
-19
lines changed

Extractor/ReflectionExtractor.php

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -187,26 +187,26 @@ private function extractFromMutator($class, $property)
187187
$type = $this->extractFromReflectionType($reflectionType, $reflectionMethod);
188188

189189
// HHVM reports variadics with "array" but not builtin type hints
190-
if (!$reflectionType->isBuiltin() && Type::BUILTIN_TYPE_ARRAY === $type->getBuiltinType()) {
190+
if (1 === \count($type) && !$reflectionType->isBuiltin() && Type::BUILTIN_TYPE_ARRAY === $type[0]->getBuiltinType()) {
191191
return null;
192192
}
193193
} elseif (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/', $reflectionParameter, $info)) {
194194
if (Type::BUILTIN_TYPE_ARRAY === $info[1]) {
195-
$type = new Type(Type::BUILTIN_TYPE_ARRAY, $reflectionParameter->allowsNull(), null, true);
195+
$type = [new Type(Type::BUILTIN_TYPE_ARRAY, $reflectionParameter->allowsNull(), null, true)];
196196
} elseif (Type::BUILTIN_TYPE_CALLABLE === $info[1]) {
197-
$type = new Type(Type::BUILTIN_TYPE_CALLABLE, $reflectionParameter->allowsNull());
197+
$type = [new Type(Type::BUILTIN_TYPE_CALLABLE, $reflectionParameter->allowsNull())];
198198
} else {
199-
$type = new Type(Type::BUILTIN_TYPE_OBJECT, $reflectionParameter->allowsNull(), $this->resolveTypeName($info[1], $reflectionMethod));
199+
$type = [new Type(Type::BUILTIN_TYPE_OBJECT, $reflectionParameter->allowsNull(), $this->resolveTypeName($info[1], $reflectionMethod))];
200200
}
201201
} else {
202202
return null;
203203
}
204204

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

209-
return [$type];
209+
return $type;
210210
}
211211

212212
/**
@@ -225,7 +225,7 @@ private function extractFromAccessor($class, $property)
225225
}
226226

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

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

244-
if (Type::BUILTIN_TYPE_ARRAY === $phpTypeOrClass) {
245-
$type = new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true);
246-
} elseif ('void' === $phpTypeOrClass) {
247-
$type = new Type(Type::BUILTIN_TYPE_NULL, $nullable);
248-
} elseif ($reflectionType->isBuiltin()) {
249-
$type = new Type($phpTypeOrClass, $nullable);
250-
} else {
251-
$type = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $this->resolveTypeName($phpTypeOrClass, $reflectionMethod));
244+
foreach ($reflectionType instanceof \ReflectionUnionType ? $reflectionType->getTypes() : [$reflectionType] as $type) {
245+
$phpTypeOrClass = $reflectionType instanceof \ReflectionNamedType ? $reflectionType->getName() : (string) $type;
246+
247+
if (Type::BUILTIN_TYPE_ARRAY === $phpTypeOrClass) {
248+
$types[] = new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true);
249+
} elseif ('void' === $phpTypeOrClass || 'null' === $phpTypeOrClass) {
250+
$types[] = new Type(Type::BUILTIN_TYPE_NULL, $nullable);
251+
} elseif ($reflectionType->isBuiltin()) {
252+
$types[] = new Type($phpTypeOrClass, $nullable);
253+
} else {
254+
$types[] = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $this->resolveTypeName($phpTypeOrClass, $reflectionMethod));
255+
}
252256
}
253257

254-
return $type;
258+
return $types;
255259
}
256260

257261
private function resolveTypeName($name, \ReflectionMethod $reflectionMethod)

0 commit comments

Comments
 (0)