|
14 | 14 | use phpDocumentor\Reflection\DocBlock;
|
15 | 15 | use phpDocumentor\Reflection\DocBlockFactory;
|
16 | 16 | use phpDocumentor\Reflection\DocBlockFactoryInterface;
|
17 |
| -use phpDocumentor\Reflection\Types\Compound; |
18 | 17 | use phpDocumentor\Reflection\Types\ContextFactory;
|
19 |
| -use phpDocumentor\Reflection\Types\Null_; |
20 | 18 | use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface;
|
21 | 19 | use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
|
22 | 20 | use Symfony\Component\PropertyInfo\Type;
|
| 21 | +use Symfony\Component\PropertyInfo\Util\PhpDocTypeHelper; |
23 | 22 |
|
24 | 23 | /**
|
25 | 24 | * Extracts data using a PHPDoc parser.
|
@@ -47,10 +46,16 @@ class PhpDocExtractor implements PropertyDescriptionExtractorInterface, Property
|
47 | 46 | */
|
48 | 47 | private $contextFactory;
|
49 | 48 |
|
| 49 | + /** |
| 50 | + * @var PhpDocTypeHelper |
| 51 | + */ |
| 52 | + private $phpDocTypeHelper; |
| 53 | + |
50 | 54 | public function __construct(DocBlockFactoryInterface $docBlockFactory = null)
|
51 | 55 | {
|
52 | 56 | $this->docBlockFactory = $docBlockFactory ?: DocBlockFactory::createInstance();
|
53 | 57 | $this->contextFactory = new ContextFactory();
|
| 58 | + $this->phpDocTypeHelper = new PhpDocTypeHelper(); |
54 | 59 | }
|
55 | 60 |
|
56 | 61 | /**
|
@@ -123,45 +128,7 @@ public function getTypes($class, $property, array $context = array())
|
123 | 128 | $types = array();
|
124 | 129 | /** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */
|
125 | 130 | foreach ($docBlock->getTagsByName($tag) as $tag) {
|
126 |
| - $varType = $tag->getType(); |
127 |
| - $nullable = false; |
128 |
| - |
129 |
| - if (!$varType instanceof Compound) { |
130 |
| - if ($varType instanceof Null_) { |
131 |
| - $nullable = true; |
132 |
| - } |
133 |
| - |
134 |
| - $type = $this->createType((string) $varType, $nullable); |
135 |
| - |
136 |
| - if (null !== $type) { |
137 |
| - $types[] = $type; |
138 |
| - } |
139 |
| - |
140 |
| - continue; |
141 |
| - } |
142 |
| - |
143 |
| - $typeIndex = 0; |
144 |
| - $varTypes = array(); |
145 |
| - while ($varType->has($typeIndex)) { |
146 |
| - $varTypes[] = (string) $varType->get($typeIndex); |
147 |
| - ++$typeIndex; |
148 |
| - } |
149 |
| - |
150 |
| - // If null is present, all types are nullable |
151 |
| - $nullKey = array_search(Type::BUILTIN_TYPE_NULL, $varTypes); |
152 |
| - $nullable = false !== $nullKey; |
153 |
| - |
154 |
| - // Remove the null type from the type if other types are defined |
155 |
| - if ($nullable && count($varTypes) > 1) { |
156 |
| - unset($varTypes[$nullKey]); |
157 |
| - } |
158 |
| - |
159 |
| - foreach ($varTypes as $varType) { |
160 |
| - $type = $this->createType($varType, $nullable); |
161 |
| - if (null !== $type) { |
162 |
| - $types[] = $type; |
163 |
| - } |
164 |
| - } |
| 131 | + $types = array_merge($types, $this->phpDocTypeHelper->getTypesFromTag($tag)); |
165 | 132 | }
|
166 | 133 |
|
167 | 134 | if (!isset($types[0])) {
|
@@ -274,90 +241,4 @@ private function getDocBlockFromMethod($class, $ucFirstProperty, $type)
|
274 | 241 |
|
275 | 242 | return array($this->docBlockFactory->create($reflectionMethod, $this->contextFactory->createFromReflector($reflectionMethod)), $prefix);
|
276 | 243 | }
|
277 |
| - |
278 |
| - /** |
279 |
| - * Creates a {@see Type} from a PHPDoc type. |
280 |
| - * |
281 |
| - * @param string $docType |
282 |
| - * @param bool $nullable |
283 |
| - * |
284 |
| - * @return Type|null |
285 |
| - */ |
286 |
| - private function createType($docType, $nullable) |
287 |
| - { |
288 |
| - // Cannot guess |
289 |
| - if (!$docType || 'mixed' === $docType) { |
290 |
| - return; |
291 |
| - } |
292 |
| - |
293 |
| - if ($collection = '[]' === substr($docType, -2)) { |
294 |
| - $docType = substr($docType, 0, -2); |
295 |
| - } |
296 |
| - |
297 |
| - $docType = $this->normalizeType($docType); |
298 |
| - list($phpType, $class) = $this->getPhpTypeAndClass($docType); |
299 |
| - |
300 |
| - $array = 'array' === $docType; |
301 |
| - |
302 |
| - if ($collection || $array) { |
303 |
| - if ($array || 'mixed' === $docType) { |
304 |
| - $collectionKeyType = null; |
305 |
| - $collectionValueType = null; |
306 |
| - } else { |
307 |
| - $collectionKeyType = new Type(Type::BUILTIN_TYPE_INT); |
308 |
| - $collectionValueType = new Type($phpType, false, $class); |
309 |
| - } |
310 |
| - |
311 |
| - return new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, $collectionKeyType, $collectionValueType); |
312 |
| - } |
313 |
| - |
314 |
| - return new Type($phpType, $nullable, $class); |
315 |
| - } |
316 |
| - |
317 |
| - /** |
318 |
| - * Normalizes the type. |
319 |
| - * |
320 |
| - * @param string $docType |
321 |
| - * |
322 |
| - * @return string |
323 |
| - */ |
324 |
| - private function normalizeType($docType) |
325 |
| - { |
326 |
| - switch ($docType) { |
327 |
| - case 'integer': |
328 |
| - return 'int'; |
329 |
| - |
330 |
| - case 'boolean': |
331 |
| - return 'bool'; |
332 |
| - |
333 |
| - // real is not part of the PHPDoc standard, so we ignore it |
334 |
| - case 'double': |
335 |
| - return 'float'; |
336 |
| - |
337 |
| - case 'callback': |
338 |
| - return 'callable'; |
339 |
| - |
340 |
| - case 'void': |
341 |
| - return 'null'; |
342 |
| - |
343 |
| - default: |
344 |
| - return $docType; |
345 |
| - } |
346 |
| - } |
347 |
| - |
348 |
| - /** |
349 |
| - * Gets an array containing the PHP type and the class. |
350 |
| - * |
351 |
| - * @param string $docType |
352 |
| - * |
353 |
| - * @return array |
354 |
| - */ |
355 |
| - private function getPhpTypeAndClass($docType) |
356 |
| - { |
357 |
| - if (in_array($docType, Type::$builtinTypes)) { |
358 |
| - return array($docType, null); |
359 |
| - } |
360 |
| - |
361 |
| - return array('object', substr($docType, 1)); |
362 |
| - } |
363 | 244 | }
|
0 commit comments