10000 [PropertyInfo] Extract the logic converting a php doc to a Type · symfony/symfony@d6e93d8 · GitHub
[go: up one dir, main page]

Skip to content

Commit d6e93d8

Browse files
committed
[PropertyInfo] Extract the logic converting a php doc to a Type
in PhpDocTypeHelperTrait
1 parent 904279e commit d6e93d8

File tree

2 files changed

+167
-127
lines changed

2 files changed

+167
-127
lines changed

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

Lines changed: 8 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,11 @@
1414
use phpDocumentor\Reflection\DocBlock;
1515
use phpDocumentor\Reflection\DocBlockFactory;
1616
use phpDocumentor\Reflection\DocBlockFactoryInterface;
17-
use phpDocumentor\Reflection\Types\Compound;
1817
use phpDocumentor\Reflection\Types\ContextFactory;
19-
use phpDocumentor\Reflection\Types\Null_;
2018
use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface;
2119
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
2220
use Symfony\Component\PropertyInfo\Type;
21+
use Symfony\Component\PropertyInfo\Util\PhpDocTypeHelper;
2322

2423
/**
2524
* Extracts data using a PHPDoc parser.
@@ -47,10 +46,16 @@ class PhpDocExtractor implements PropertyDescriptionExtractorInterface, Property
4746
*/
4847
private $contextFactory;
4948

49+
/**
50+
* @var PhpDocTypeHelper
51+
*/
52+
private $phpDocTypeHelper;
53+
5054
public function __construct(DocBlockFactoryInterface $docBlockFactory = null)
5155
{
5256
$this->docBlockFactory = $docBlockFactory ?: DocBlockFactory::createInstance();
5357
$this->contextFactory = new ContextFactory();
58+
$this->phpDocTypeHelper = new PhpDocTypeHelper();
5459
}
5560

5661
/**
@@ -123,45 +128,7 @@ public function getTypes($class, $property, array $context = array())
123128
$types = array();
124129
/** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */
125130
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->getTypes($tag->getType()));
165132
}
166133

167134
if (!isset($types[0])) {
@@ -274,90 +241,4 @@ private function getDocBlockFromMethod($class, $ucFirstProperty, $type)
274241

275242
return array($this->docBlockFactory->create($reflectionMethod, $this->contextFactory->createFromReflector($reflectionMethod)), $prefix);
276243
}
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 & 10000 #39;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-
}
363244
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\PropertyInfo\Util;
13+
14+
use phpDocumentor\Reflection\Type as DocType;
15+
use phpDocumentor\Reflection\Types\Compound;
16+
use phpDocumentor\Reflection\Types\Null_;
17+
use Symfony\Component\PropertyInfo\Type;
18+
19+
/**
20+
* Transforms a php doc type to a {@link Type} instance.
21+
*
22+
* @author Kévin Dunglas <dunglas@gmail.com>
23+
* @author Guilhem N. <egetick@gmail.com>
24+
*/
25+
final class PhpDocTypeHelper
26+
{
27+
/**
28+
* Creates a {@see Type} from a PHPDoc type.
29+
*
30+
* @return Type
31+
*/
32+
public function getTypes(DocType $varType)
33+
{
34+
$types = array();
35+
$nullable = false;
36+
37+
if (!$varType instanceof Compound) {
38+
if ($varType instanceof Null_) {
39+
$nullable = true;
40+
}
41+
42+
$type = $this->createType((string) $varType, $nullable);
43+
if (null !== $type) {
44+
$types[] = $type;
45+
}
46+
47+
return $types;
48+
}
49+
50+
$varTypes = array();
51+
for ($typeIndex = 0; $varType->has($typeIndex); ++$typeIndex) {
52+
$varTypes[] = (string) $varType->get($typeIndex);
53+
}
54+
55+
// If null is present, all types are nullable
56+
$nullKey = array_search(Type::BUILTIN_TYPE_NULL, $varTypes);
57+
$nullable = false !== $nullKey;
58+
59+
// Remove the null type from the type if other types are defined
60+
if ($nullable && count($varTypes) > 1) {
61+
unset($varTypes[$nullKey]);
62+
}
63+
64+
foreach ($varTypes as $varType) {
65+
$type = $this->createType($varType, $nullable);
66+
if (null !== $type) {
67+
$types[] = $type;
68+
}
69+
}
70+
71+
return $types;
72+
}
73+
74+
/**
75+
* Creates a {@see Type} from a PHPDoc type.
76+
*
77+
* @param string $docType
78+
* @param bool $nullable
79+
*
80+
* @return Type|null
81+
*/
82+
private function createType($docType, $nullable)
83+
{
84+
// Cannot guess
85+
if (!$docType || 'mixed' === $docType) {
86+
return;
87+
}
88+
89+
if ($collection = '[]' === substr($docType, -2)) {
90+
$docType = substr($docType, 0, -2);
91+
}
92+
93+
$docType = $this->normalizeType($docType);
94+
list($phpType, $class) = $this->getPhpTypeAndClass($docType);
95+
96+
$array = 'array' === $docType;
97+
98+
if ($collection || $array) {
99+
if ($array || 'mixed' === $docType) {
100+
$collectionKeyType = null;
101+
$collectionValueType = null;
102+
} else {
103+
$collectionKeyType = new Type(Type::BUILTIN_TYPE_INT);
104+
$collectionValueType = new Type($phpType, false, $class);
105+
}
106+
107+
return new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, $collectionKeyType, $collectionValueType);
108+
}
109+
110+
return new Type($phpType, $nullable, $class);
111+
}
112+
113+
/**
114+
* Normalizes the type.
115+
*
116+
* @param string $docType
117+
*
118+
* @return string
119+
*/
120+
private function normalizeType($docType)
121+
{
122+
switch ($docType) {
123+
case 'integer':
124+
return 'int';
125+
126+
case 'boolean':
127+
return 'bool';
128+
129+
// real is not part of the PHPDoc standard, so we ignore it
130+
case 'double':
131+
return 'float';
132+
133+
case 'callback':
134+
return 'callable';
135+
136+
case 'void':
137+
return 'null';
138+
139+
default:
140+
return $docType;
141+
}
142+
}
143+
144+
/**
145+
* Gets an array containing the PHP type and the class.
146+
*
147+
* @param string $docType
148+
*
149+
* @return array
150+
*/
151+
private function getPhpTypeAndClass($docType)
152+
{
153+
if (in_array($docType, Type::$builtinTypes)) {
154+
return array($docType, null);
155+
}
156+
157+
return array('object', substr($docType, 1));
158+
}
159+
}

0 commit comments

Comments
 (0)
0