Skip to content

Commit 12bafe4

Browse files
popy-devfabpot
authored andcommitted
[PropertyInfo] Implement \"Collection\" types in PhpDocExtractor
1 parent be1b37f commit 12bafe4

File tree

4 files changed

+84
-10
lines changed

4 files changed

+84
-10
lines changed

src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
1616
use Symfony\Component\PropertyInfo\Type;
17+
use phpDocumentor\Reflection\Types\Collection;
1718

1819
/**
1920
* @author Kévin Dunglas <dunglas@gmail.com>
@@ -77,6 +78,39 @@ public function typesProvider()
7778
);
7879
}
7980

81+
/**
82+
* @dataProvider provideCollectionTypes
83+
*/
84+
public function testExtractCollection($property, array $type = null, $shortDescription, $longDescription)
85+
{
86+
if (!class_exists(Collection::class)) {
87+
$this->markTestSkipped('Collections are not implemented in current phpdocumentor/type-resolver version');
88+
}
89+
90+
$this->testExtract($property, $type, $shortDescription, $longDescription);
91+
}
92+
93+
public function provideCollectionTypes()
94+
{
95+
return array(
96+
array('iteratorCollection', array(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Iterator', true, null, new Type(Type::BUILTIN_TYPE_STRING))), null, null),
97+
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),
98+
array(
99+
'nestedIterators',
100+
array(new Type(
101+
Type::BUILTIN_TYPE_OBJECT,
102+
false,
103+
'Iterator',
104+
true,
105+
new Type(Type::BUILTIN_TYPE_INT),
106+
new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Iterator', true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))
107+
)),
108+
null,
109+
null,
110+
),
111+
);
112+
}
113+
80114
public function testParamTagTypeIsOmitted()
81115
{
82116
$this->assertNull($this->extractor->getTypes(OmittedParamTagTypeDocBlock::class, 'omittedType'));

src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ public function testGetProperties()
4242
'Guid',
4343
'array',
4444
'emptyVar',
45+
'iteratorCollection',
46+
'iteratorCollectionWithKey',
47+
'nestedIterators',
4548
'foo',
4649
'foo2',
4750
'foo3',
@@ -79,6 +82,9 @@ public function testGetPropertiesWithCustomPrefixes()
7982
'Guid',
8083
'array',
8184
'emptyVar',
85+
'iteratorCollection',
86+
'iteratorCollectionWithKey',
87+
'nestedIterators',
8288
'foo',
8389
'foo2',
8490
'foo3',
@@ -107,6 +113,9 @@ public function testGetPropertiesWithNoPrefixes()
107113
'Guid',
108114
'array',
109115
'emptyVar',
116+
'iteratorCollection',
117+
'iteratorCollectionWithKey',
118+
'nestedIterators',
110119
'foo',
111120
'foo2',
112121
'foo3',

src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,21 @@ class Dummy extends ParentDummy
7575
*/
7676
public $emptyVar;
7777

78+
/**
79+
* @var \Iterator<string>
80+
*/
81+
public $iteratorCollection;
82+
83+
/**
84+
* @var \Iterator<integer,string>
85+
*/
86+
public $iteratorCollectionWithKey;
87+
88+
/**
89+
* @var \Iterator<integer,\Iterator<integer,string>>
90+
*/
91+
public $nestedIterators;
92+
7893
public static function getStatic()
7994
{
8095
}

src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\PropertyInfo\Util;
1313

1414
use phpDocumentor\Reflection\Type as DocType;
15+
use phpDocumentor\Reflection\Types\Collection;
1516
use phpDocumentor\Reflection\Types\Compound;
1617
use phpDocumentor\Reflection\Types\Null_;
1718
use Symfony\Component\PropertyInfo\Type;
@@ -39,7 +40,7 @@ public function getTypes(DocType $varType): array
3940
$nullable = true;
4041
}
4142

42-
$type = $this->createType((string) $varType, $nullable);
43+
$type = $this->createType($varType, $nullable);
4344
if (null !== $type) {
4445
$types[] = $type;
4546
}
@@ -49,16 +50,15 @@ public function getTypes(DocType $varType): array
4950

5051
$varTypes = array();
5152
for ($typeIndex = 0; $varType->has($typeIndex); ++$typeIndex) {
52-
$varTypes[] = (string) $varType->get($typeIndex);
53-
}
53+
$type = $varType->get($typeIndex);
5454

55-
// If null is present, all types are nullable
56-
$nullKey = array_search(Type::BUILTIN_TYPE_NULL, $varTypes);
57-
$nullable = false !== $nullKey;
55+
// If null is present, all types are nullable
56+
if ($type instanceof Null_) {
57+
$nullable = true;
58+
continue;
59+
}
5860

59-
// Remove the null type from the type if other types are defined
60-
if ($nullable && count($varTypes) > 1) {
61-
unset($varTypes[$nullKey]);
61+
$varTypes[] = $type;
6262
}
6363

6464
foreach ($varTypes as $varType) {
@@ -74,8 +74,24 @@ public function getTypes(DocType $varType): array
7474
/**
7575
* Creates a {@see Type} from a PHPDoc type.
7676
*/
77-
private function createType(string $docType, bool $nullable): ?Type
77+
private function createType(DocType $type, bool $nullable): ?Type
7878
{
79+
$docType = (string) $type;
80+
81+
if ($type instanceof Collection) {
82+
list($phpType, $class) = $this->getPhpTypeAndClass((string) $type->getFqsen());
83+
84+
$key = $this->getTypes($type->getKeyType());
85+
$value = $this->getTypes($type->getValueType());
86+
87+
// More than 1 type returned means it is a Compound type, which is
88+
// not handled by Type, so better use a null value.
89+
$key = 1 === \count($key) ? $key[0] : null;
90+
$value = 1 === \count($value) ? $value[0] : null;
91+
92+
return new Type($phpType, $nullable, $class, true, $key, $value);
93+
}
94+
7995
// Cannot guess
8096
if (!$docType || 'mixed' === $docType) {
8197
return null;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy