Skip to content

Commit b755ce9

Browse files
committed
Add list pseudo-type
1 parent 9dc4bb0 commit b755ce9

File tree

6 files changed

+111
-3
lines changed

6 files changed

+111
-3
lines changed

src/PseudoTypes/List_.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace phpDocumentor\Reflection\PseudoTypes;
4+
5+
use phpDocumentor\Reflection\Type;
6+
use phpDocumentor\Reflection\Types\Array_;
7+
use phpDocumentor\Reflection\Types\Integer;
8+
use phpDocumentor\Reflection\Types\Mixed_;
9+
10+
final class List_ extends Array_
11+
{
12+
public function __construct(?Type $valueType = null)
13+
{
14+
parent::__construct($valueType, new Integer());
15+
}
16+
17+
/**
18+
* Returns a rendered output of the Type as it would be used in a DocBlock.
19+
*/
20+
public function __toString(): string
21+
{
22+
if ($this->valueType instanceof Mixed_) {
23+
return 'list';
24+
}
25+
26+
return 'list<' . $this->valueType . '>';
27+
}
28+
}

src/TypeResolver.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
use phpDocumentor\Reflection\Types\InterfaceString;
2727
use phpDocumentor\Reflection\Types\Intersection;
2828
use phpDocumentor\Reflection\Types\Iterable_;
29+
use phpDocumentor\Reflection\PseudoTypes\List_;
2930
use phpDocumentor\Reflection\Types\Nullable;
3031
use phpDocumentor\Reflection\Types\Object_;
3132
use phpDocumentor\Reflection\Types\String_;
@@ -521,10 +522,11 @@ private function resolveCollection(ArrayIterator $tokens, Type $classType, Conte
521522
{
522523
$isArray = ((string) $classType === 'array');
523524
$isIterable = ((string) $classType === 'iterable');
525+
$isList = ((string) $classType === 'list');
524526

525527
// allow only "array", "iterable" or class name before "<"
526528
if (
527-
!$isArray && !$isIterable
529+
!$isArray && !$isIterable && !$isList
528530
&& (!$classType instanceof Object_ || $classType->getFqsen() === null)
529531
) {
530532
throw new RuntimeException(
@@ -538,7 +540,7 @@ private function resolveCollection(ArrayIterator $tokens, Type $classType, Conte
538540
$keyType = null;
539541

540542
$token = $tokens->current();
541-
if ($token !== null && trim($token) === ',') {
543+
if ($token !== null && trim($token) === ',' && !$isList) {
542544
// if we have a comma, then we just parsed the key type, not the value type
543545
$keyType = $valueType;
544546
if ($isArray) {
@@ -596,6 +598,10 @@ private function resolveCollection(ArrayIterator $tokens, Type $classType, Conte
596598
return new Iterable_($valueType, $keyType);
597599
}
598600

601+
if ($isList) {
602+
return new List_($valueType);
603+
}
604+
599605
if ($classType instanceof Object_) {
600606
return $this->makeCollectionFromObject($classType, $valueType, $keyType);
601607
}

src/Types/Array_.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@
2424
*
2525
* @psalm-immutable
2626
*/
27-
final class Array_ extends AbstractList
27+
class Array_ extends AbstractList
2828
{
2929
}

tests/unit/CollectionResolverTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace phpDocumentor\Reflection;
1515

16+
use phpDocumentor\Reflection\PseudoTypes\List_;
1617
use phpDocumentor\Reflection\Types\Array_;
1718
use phpDocumentor\Reflection\Types\Collection;
1819
use phpDocumentor\Reflection\Types\Context;
@@ -297,4 +298,28 @@ public function testResolvingCollectionAsArray(): void
297298
$this->assertInstanceOf(Types\Float_::class, $valueType);
298299
$this->assertInstanceOf(Types\String_::class, $keyType);
299300
}
301+
302+
/**
303+
* @uses \phpDocumentor\Reflection\Types\Context
304+
* @uses \phpDocumentor\Reflection\Types\String_
305+
*
306+
* @covers ::__construct
307+
* @covers ::resolve
308+
*/
309+
public function testResolvingList(): void
310+
{
311+
$fixture = new TypeResolver();
312+
313+
$resolvedType = $fixture->resolve('list<string>', new Context(''));
314+
315+
$this->assertInstanceOf(List_::class, $resolvedType);
316+
$this->assertSame('list<string>', (string) $resolvedType);
317+
318+
$valueType = $resolvedType->getValueType();
319+
320+
$keyType = $resolvedType->getKeyType();
321+
322+
$this->assertInstanceOf(Types\String_::class, $valueType);
323+
$this->assertInstanceOf(Types\Integer::class, $keyType);
324+
}
300325
}

tests/unit/PseudoTypes/ListTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of phpDocumentor.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*
11+
* @link http://phpdoc.org
12+
*/
13+
14+
namespace phpDocumentor\Reflection\PseudoTypes;
15+
16+
use phpDocumentor\Reflection\Types\Compound;
17+
use phpDocumentor\Reflection\Types\Integer;
18+
use phpDocumentor\Reflection\Types\Mixed_;
19+
use phpDocumentor\Reflection\Types\String_;
20+
use PHPUnit\Framework\TestCase;
21+
22+
/**
23+
* @coversDefaultClass \phpDocumentor\Reflection\PseudoTypes\List_
24+
*/
25+
class ListTest extends TestCase
26+
{
27+
/**
28+
* @dataProvider provideArrays
29+
* @covers ::__toString
30+
*/
31+
public function testArrayStringifyCorrectly(List_ $array, string $expectedString): void
32+
{
33+
$this->assertSame($expectedString, (string) $array);
34+
}
35+
36+
/**
37+
* @return mixed[]
38+
*/
39+
public function provideArrays(): array
40+
{
41+
return [
42+
'simple list' => [new List_(), 'list'],
43+
'list of mixed' => [new List_(new Mixed_()), 'list'],
44+
'list of single type' => [new List_(new String_()), 'list<string>'],
45+
'list of compound type' => [new List_(new Compound([new Integer(), new String_()])), 'list<int|string>'],
46+
];
47+
}
48+
}

tests/unit/TypeResolverTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,7 @@ public function provideKeywords(): array
759759
['iterable', Types\Iterable_::class],
760760
['never', Types\Never_::class],
761761
['literal-string', PseudoTypes\LiteralString::class],
762+
['list', PseudoTypes\List_::class],
762763
];
763764
}
764765

0 commit comments

Comments
 (0)