Skip to content

Commit 131f362

Browse files
committed
[PropertyInfo] fix array types with keys (array<string, string>)
1 parent 73cb33a commit 131f362

File tree

4 files changed

+69
-7
lines changed

4 files changed

+69
-7
lines changed

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,39 @@ public function provideCollectionTypes()
150150
null,
151151
null,
152152
],
153+
[
154+
'arrayWithKeys',
155+
[new Type(
156+
Type::BUILTIN_TYPE_ARRAY,
157+
false,
158+
null,
159+
true,
160+
new Type(Type::BUILTIN_TYPE_STRING),
161+
new Type(Type::BUILTIN_TYPE_STRING)
162+
)],
163+
null,
164+
null,
165+
],
166+
[
167+
'arrayWithKeysAndComplexValue',
168+
[new Type(
169+
Type::BUILTIN_TYPE_ARRAY,
170+
false,
171+
null,
172+
true,
173+
new Type(Type::BUILTIN_TYPE_STRING),
174+
new Type(
175+
Type::BUILTIN_TYPE_ARRAY,
176+
true,
177+
null,
178+
true,
179+
new Type(Type::BUILTIN_TYPE_INT),
180+
new Type(Type::BUILTIN_TYPE_STRING, true)
181+
)
182+
)],
183+
null,
184+
null,
185+
],
153186
];
154187
}
155188

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ public function testGetProperties()
5656
'iteratorCollection',
5757
'iteratorCollectionWithKey',
5858
'nestedIterators',
59+
'arrayWithKeys',
60+
'arrayWithKeysAndComplexValue',
5961
'foo',
6062
'foo2',
6163
'foo3',
@@ -104,6 +106,8 @@ public function testGetPropertiesWithCustomPrefixes()
104106
'iteratorCollection',
105107
'iteratorCollectionWithKey',
106108
'nestedIterators',
109+
'arrayWithKeys',
110+
'arrayWithKeysAndComplexValue',
107111
'foo',
108112
'foo2',
109113
'foo3',
@@ -142,6 +146,8 @@ public function testGetPropertiesWithNoPrefixes()
142146
'iteratorCollection',
143147
'iteratorCollectionWithKey',
144148
'nestedIterators',
149+
'arrayWithKeys',
150+
'arrayWithKeysAndComplexValue',
145151
'foo',
146152
'foo2',
147153
'foo3',

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,16 @@ class Dummy extends ParentDummy
130130
*/
131131
public $nestedIterators;
132132

133+
/**
134+
* @var array<string, string>
135+
*/
136+
public $arrayWithKeys;
137+
138+
/**
139+
* @var array<string, array<integer, null|string>|null>
140+
*/
141+
public $arrayWithKeysAndComplexValue;
142+
133143
public static function getStatic()
134144
{
135145
}

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

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111

1212
namespace Symfony\Component\PropertyInfo\Util;
1313

14+
use LogicException;
1415
use phpDocumentor\Reflection\Type as DocType;
16+
use phpDocumentor\Reflection\Types\Array_;
1517
use phpDocumentor\Reflection\Types\Collection;
1618
use phpDocumentor\Reflection\Types\Compound;
1719
use phpDocumentor\Reflection\Types\Null_;
@@ -90,7 +92,7 @@ private function createType(DocType $type, bool $nullable, string $docType = nul
9092
$docType = $docType ?? (string) $type;
9193

9294
if ($type instanceof Collection) {
93-
list($phpType, $class) = $this->getPhpTypeAndClass((string) $type->getFqsen());
95+
[$phpType, $class] = $this->getPhpTypeAndClass((string) $type->getFqsen());
9496

9597
$key = $this->getTypes($type->getKeyType());
9698
$value = $this->getTypes($type->getValueType());
@@ -109,19 +111,30 @@ private function createType(DocType $type, bool $nullable, string $docType = nul
109111
}
110112

111113
if ('[]' === substr($docType, -2)) {
112-
if ('mixed[]' === $docType) {
113-
$collectionKeyType = null;
114+
$collectionKeyType = new Type(Type::BUILTIN_TYPE_INT);
115+
$collectionValueType = $this->createType($type, false, substr($docType, 0, -2));
116+
117+
return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, $collectionKeyType, $collectionValueType);
118+
}
119+
120+
if ('array<' === substr($docType, 0, 6) && $type instanceof Array_) {
121+
// array<value> is converted to x[] which is handled above
122+
// so it's only necessary to handle array<key, value> here
123+
$collectionKeyType = $this->getTypes($type->getKeyType())[0];
124+
125+
// TODO as far as I can see there is no way to define union types yet?
126+
$collectionValueTypes = $this->getTypes($type->getValueType());
127+
if (count($collectionValueTypes) > 1) {
114128
$collectionValueType = null;
115129
} else {
116-
$collectionKeyType = new Type(Type::BUILTIN_TYPE_INT);
117-
$collectionValueType = $this->createType($type, false, substr($docType, 0, -2));
130+
$collectionValueType = $collectionValueTypes[0];
118131
}
119132

120133
return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, $collectionKeyType, $collectionValueType);
121134
}
122135

123136
$docType = $this->normalizeType($docType);
124-
list($phpType, $class) = $this->getPhpTypeAndClass($docType);
137+
[$phpType, $class] = $this->getPhpTypeAndClass($docType);
125138

126139
if ('array' === $docType) {
127140
return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, null, null);
@@ -160,6 +173,6 @@ private function getPhpTypeAndClass(string $docType): array
160173
return [$docType, null];
161174
}
162175

163-
return ['object', substr($docType, 1)];
176+
return ['object', substr($docType, 1)]; // substr to strip the namespace's `\`-prefix
164177
}
165178
}

0 commit comments

Comments
 (0)