Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3d57310

Browse files
committed
[PropertyInfo] Extract the logic converting a php doc to a Type
in PhpDocTypeHelperTrait
1 parent ad85c79 commit 3d57310

File tree

2 files changed

+172
-127
lines changed

2 files changed

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

0 commit comments

Comments
 (0)