[PropertyInfo] Implement \"Collection\" types in PhpDocExtractor
This commit is contained in:
parent
be1b37f017
commit
12bafe46d0
@ -14,6 +14,7 @@ namespace Symfony\Component\PropertyInfo\Tests\PhpDocExtractor;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
|
||||
use Symfony\Component\PropertyInfo\Type;
|
||||
use phpDocumentor\Reflection\Types\Collection;
|
||||
|
||||
/**
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
@ -77,6 +78,39 @@ class PhpDocExtractorTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideCollectionTypes
|
||||
*/
|
||||
public function testExtractCollection($property, array $type = null, $shortDescription, $longDescription)
|
||||
{
|
||||
if (!class_exists(Collection::class)) {
|
||||
$this->markTestSkipped('Collections are not implemented in current phpdocumentor/type-resolver version');
|
||||
}
|
||||
|
||||
$this->testExtract($property, $type, $shortDescription, $longDescription);
|
||||
}
|
||||
|
||||
public function provideCollectionTypes()
|
||||
{
|
||||
return array(
|
||||
array('iteratorCollection', array(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Iterator', true, null, new Type(Type::BUILTIN_TYPE_STRING))), null, null),
|
||||
array('iteratorCollectionWithKey', array(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Iterator', true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))), null, null),
|
||||
array(
|
||||
'nestedIterators',
|
||||
array(new Type(
|
||||
Type::BUILTIN_TYPE_OBJECT,
|
||||
false,
|
||||
'Iterator',
|
||||
true,
|
||||
new Type(Type::BUILTIN_TYPE_INT),
|
||||
new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Iterator', true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))
|
||||
)),
|
||||
null,
|
||||
null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function testParamTagTypeIsOmitted()
|
||||
{
|
||||
$this->assertNull($this->extractor->getTypes(OmittedParamTagTypeDocBlock::class, 'omittedType'));
|
||||
|
@ -42,6 +42,9 @@ class ReflectionExtractorTest extends TestCase
|
||||
'Guid',
|
||||
'array',
|
||||
'emptyVar',
|
||||
'iteratorCollection',
|
||||
'iteratorCollectionWithKey',
|
||||
'nestedIterators',
|
||||
'foo',
|
||||
'foo2',
|
||||
'foo3',
|
||||
@ -79,6 +82,9 @@ class ReflectionExtractorTest extends TestCase
|
||||
'Guid',
|
||||
'array',
|
||||
'emptyVar',
|
||||
'iteratorCollection',
|
||||
'iteratorCollectionWithKey',
|
||||
'nestedIterators',
|
||||
'foo',
|
||||
'foo2',
|
||||
'foo3',
|
||||
@ -107,6 +113,9 @@ class ReflectionExtractorTest extends TestCase
|
||||
'Guid',
|
||||
'array',
|
||||
'emptyVar',
|
||||
'iteratorCollection',
|
||||
'iteratorCollectionWithKey',
|
||||
'nestedIterators',
|
||||
'foo',
|
||||
'foo2',
|
||||
'foo3',
|
||||
|
@ -75,6 +75,21 @@ class Dummy extends ParentDummy
|
||||
*/
|
||||
public $emptyVar;
|
||||
|
||||
/**
|
||||
* @var \Iterator<string>
|
||||
*/
|
||||
public $iteratorCollection;
|
||||
|
||||
/**
|
||||
* @var \Iterator<integer,string>
|
||||
*/
|
||||
public $iteratorCollectionWithKey;
|
||||
|
||||
/**
|
||||
* @var \Iterator<integer,\Iterator<integer,string>>
|
||||
*/
|
||||
public $nestedIterators;
|
||||
|
||||
public static function getStatic()
|
||||
{
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\PropertyInfo\Util;
|
||||
|
||||
use phpDocumentor\Reflection\Type as DocType;
|
||||
use phpDocumentor\Reflection\Types\Collection;
|
||||
use phpDocumentor\Reflection\Types\Compound;
|
||||
use phpDocumentor\Reflection\Types\Null_;
|
||||
use Symfony\Component\PropertyInfo\Type;
|
||||
@ -39,7 +40,7 @@ final class PhpDocTypeHelper
|
||||
$nullable = true;
|
||||
}
|
||||
|
||||
$type = $this->createType((string) $varType, $nullable);
|
||||
$type = $this->createType($varType, $nullable);
|
||||
if (null !== $type) {
|
||||
$types[] = $type;
|
||||
}
|
||||
@ -49,16 +50,15 @@ final class PhpDocTypeHelper
|
||||
|
||||
$varTypes = array();
|
||||
for ($typeIndex = 0; $varType->has($typeIndex); ++$typeIndex) {
|
||||
$varTypes[] = (string) $varType->get($typeIndex);
|
||||
}
|
||||
$type = $varType->get($typeIndex);
|
||||
|
||||
// If null is present, all types are nullable
|
||||
$nullKey = array_search(Type::BUILTIN_TYPE_NULL, $varTypes);
|
||||
$nullable = false !== $nullKey;
|
||||
if ($type instanceof Null_) {
|
||||
$nullable = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove the null type from the type if other types are defined
|
||||
if ($nullable && count($varTypes) > 1) {
|
||||
unset($varTypes[$nullKey]);
|
||||
$varTypes[] = $type;
|
||||
}
|
||||
|
||||
foreach ($varTypes as $varType) {
|
||||
@ -74,8 +74,24 @@ final class PhpDocTypeHelper
|
||||
/**
|
||||
* Creates a {@see Type} from a PHPDoc type.
|
||||
*/
|
||||
private function createType(string $docType, bool $nullable): ?Type
|
||||
private function createType(DocType $type, bool $nullable): ?Type
|
||||
{
|
||||
$docType = (string) $type;
|
||||
|
||||
if ($type instanceof Collection) {
|
||||
list($phpType, $class) = $this->getPhpTypeAndClass((string) $type->getFqsen());
|
||||
|
||||
$key = $this->getTypes($type->getKeyType());
|
||||
$value = $this->getTypes($type->getValueType());
|
||||
|
||||
// More than 1 type returned means it is a Compound type, which is
|
||||
// not handled by Type, so better use a null value.
|
||||
$key = 1 === \count($key) ? $key[0] : null;
|
||||
$value = 1 === \count($value) ? $value[0] : null;
|
||||
|
||||
return new Type($phpType, $nullable, $class, true, $key, $value);
|
||||
}
|
||||
|
||||
// Cannot guess
|
||||
if (!$docType || 'mixed' === $docType) {
|
||||
return null;
|
||||
|
Reference in New Issue
Block a user