Skip to content

Commit 61fac70

Browse files
[PropertyInfo] Fix edge cases in ReflectionExtractor
1 parent 7f0ae27 commit 61fac70

File tree

1 file changed

+34
-62
lines changed

1 file changed

+34
-62
lines changed

src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php

+34-62
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
4444
*/
4545
public static $arrayMutatorPrefixes = array('add', 'remove');
4646

47+
private $supportsParameterType;
48+
49+
public function __construct()
50+
{
51+
$this->supportsParameterType = method_exists('ReflectionParameter', 'getType');
52+
}
53+
4754
/**
4855
* {@inheritdoc}
4956
*/
@@ -134,68 +141,33 @@ private function extractFromMutator($class, $property)
134141
$reflectionParameters = $reflectionMethod->getParameters();
135142
$reflectionParameter = $reflectionParameters[0];
136143

137-
$arrayMutator = in_array($prefix, self::$arrayMutatorPrefixes);
138-
139-
if (method_exists($reflectionParameter, 'getType') && $reflectionType = $reflectionParameter->getType()) {
140-
$fromReflectionType = $this->extractFromReflectionType($reflectionType);
141-
142-
if (!$arrayMutator) {
143-
return array($fromReflectionType);
144+
if ($this->supportsParameterType) {
145+
if (!$reflectionType = $reflectionParameter->getType()) {
146+
return;
144147
}
148+
$type = $this->extractFromReflectionType($reflectionType);
145149

146-
$phpType = Type::BUILTIN_TYPE_ARRAY;
147-
$collectionKeyType = new Type(Type::BUILTIN_TYPE_INT);
148-
$collectionValueType = $fromReflectionType;
149-
}
150-
151-
if ($reflectionParameter->isArray()) {
152-
$phpType = Type::BUILTIN_TYPE_ARRAY;
153-
$collection = true;
154-
}
155-
156-
if ($arrayMutator) {
157-
$collection = true;
158-
$nullable = false;
159-
$collectionNullable = $reflectionParameter->allowsNull();
160-
} else {
161-
$nullable = $reflectionParameter->allowsNull();
162-
$collectionNullable = false;
163-
}
164-
165-
if (!isset($collection)) {
166-
$collection = false;
167-
}
168-
169-
if (method_exists($reflectionParameter, 'isCallable') && $reflectionParameter->isCallable()) {
170-
$phpType = Type::BUILTIN_TYPE_CALLABLE;
171-
}
172-
173-
if ($typeHint = $reflectionParameter->getClass()) {
174-
if ($collection) {
175-
$phpType = Type::BUILTIN_TYPE_ARRAY;
176-
$collectionKeyType = new Type(Type::BUILTIN_TYPE_INT);
177-
$collectionValueType = new Type(Type::BUILTIN_TYPE_OBJECT, $collectionNullable, $typeHint->name);
150+
// HHVM reports variadics with "array" but not builtin type hints
151+
if (!$reflectionType->isBuiltin() && Type::BUILTIN_TYPE_ARRAY === $type->getBuiltinType()) {
152+
return;
153+
}
154+
} elseif (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/', $reflectionParameter, $info)) {
155+
if (Type::BUILTIN_TYPE_ARRAY === $info[1]) {
156+
$type = new Type(Type::BUILTIN_TYPE_ARRAY, $reflectionParameter->allowsNull(), null, true);
157+
} elseif (Type::BUILTIN_TYPE_CALLABLE === $info[1]) {
158+
$type = new Type(Type::BUILTIN_TYPE_CALLABLE, $reflectionParameter->allowsNull());
178159
} else {
179-
$phpType = Type::BUILTIN_TYPE_OBJECT;
180-
$typeClass = $typeHint->name;
160+
$type = new Type(Type::BUILTIN_TYPE_OBJECT, $reflectionParameter->allowsNull(), $info[1]);
181161
}
162+
} else {
163+
return;
182164
}
183165

184-
// Nothing useful extracted
185-
if (!isset($phpType)) {
186-
return;
166+
if (in_array($prefix, self::$arrayMutatorPrefixes)) {
167+
$type = new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $type);
187168
}
188169

189-
return array(
190-
new Type(
191-
$phpType,
192-
$nullable,
193-
isset($typeClass) ? $typeClass : null,
194-
$collection,
195-
isset($collectionKeyType) ? $collectionKeyType : null,
196-
isset($collectionValueType) ? $collectionValueType : null
197-
),
198-
);
170+
return array($type);
199171
}
200172

201173
/**
@@ -213,7 +185,7 @@ private function extractFromAccessor($class, $property)
213185
return;
214186
}
215187

216-
if (method_exists($reflectionMethod, 'getReturnType') && $reflectionType = $reflectionMethod->getReturnType()) {
188+
if ($this->supportsParameterType && $reflectionType = $reflectionMethod->getReturnType()) {
217189
return array($this->extractFromReflectionType($reflectionType));
218190
}
219191

@@ -231,15 +203,15 @@ private function extractFromAccessor($class, $property)
231203
*/
232204
private function extractFromReflectionType(\ReflectionType $reflectionType)
233205
{
234-
$phpTypeOrClass = method_exists($reflectionType, 'getName') ? $reflectionType->getName() : (string) $reflectionType;
206+
$phpTypeOrClass = $reflectionType instanceof \ReflectionNamedType ? $reflectionType->getName() : $reflectionType->__toString();
235207
$nullable = $reflectionType->allowsNull();
236208

237-
if ($reflectionType->isBuiltin()) {
238-
if (Type::BUILTIN_TYPE_ARRAY === $phpTypeOrClass) {
239-
$type = new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true);
240-
} else {
241-
$type = new Type($phpTypeOrClass, $nullable);
242-
}
209+
if (Type::BUILTIN_TYPE_ARRAY === $phpTypeOrClass) {
210+
$type = new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true);
211+
} elseif ('void' === $phpTypeOrClass) {
212+
$type = new Type(Type::BUILTIN_TYPE_NULL, $nullable);
213+
} elseif ($reflectionType->isBuiltin()) {
214+
$type = new Type($phpTypeOrClass, $nullable);
243215
} else {
244216
$type = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $phpTypeOrClass);
245217
}

0 commit comments

Comments
 (0)