Skip to content

Commit a12f7e3

Browse files
authored
Merge pull request #132 from voku/array-key-fix
Fix: An array can have only integers or strings as keys
2 parents 4b3579f + ccac888 commit a12f7e3

File tree

7 files changed

+74
-3
lines changed

7 files changed

+74
-3
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ psalm:
2929

3030
.PHONY: test
3131
test:
32-
docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:7.2 tools/phpunit
32+
docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:7.3 tools/phpunit
3333

3434
.PHONY: pre-commit-test
3535
pre-commit-test: test phpcs phpstan psalm

src/PseudoTypes/LiteralString.php

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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\PseudoType;
17+
use phpDocumentor\Reflection\Type;
18+
use phpDocumentor\Reflection\Types\String_;
19+
20+
/**
21+
* Value Object representing the type 'string'.
22+
*
23+
* @psalm-immutable
24+
*/
25+
final class LiteralString extends String_ implements PseudoType
26+
{
27+
public function underlyingType(): Type
28+
{
29+
return new String_();
30+
}
31+
32+
/**
33+
* Returns a rendered output of the Type as it would be used in a DocBlock.
34+
*/
35+
public function __toString(): string
36+
{
37+
return 'literal-string';
38+
}
39+
}

src/TypeResolver.php

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use ArrayIterator;
1717
use InvalidArgumentException;
1818
use phpDocumentor\Reflection\Types\Array_;
19+
use phpDocumentor\Reflection\Types\ArrayKey;
1920
use phpDocumentor\Reflection\Types\ClassString;
2021
use phpDocumentor\Reflection\Types\Collection;
2122
use phpDocumentor\Reflection\Types\Compound;
@@ -102,6 +103,7 @@ final class TypeResolver
102103
'callable-string' => PseudoTypes\CallableString::class,
103104
'false' => PseudoTypes\False_::class,
104105
'true' => PseudoTypes\True_::class,
106+
'literal-string' => PseudoTypes\LiteralString::class,
105107
'self' => Types\Self_::class,
106108
'$this' => Types\This::class,
107109
'static' => Types\Static_::class,
@@ -543,6 +545,7 @@ private function resolveCollection(ArrayIterator $tokens, Type $classType, Conte
543545
// check the key type for an "array" collection. We allow only
544546
// strings or integers.
545547
if (
548+
!$keyType instanceof ArrayKey &&
546549
!$keyType instanceof String_ &&
547550
!$keyType instanceof Integer &&
548551
!$keyType instanceof Compound
@@ -555,6 +558,7 @@ private function resolveCollection(ArrayIterator $tokens, Type $classType, Conte
555558
if ($keyType instanceof Compound) {
556559
foreach ($keyType->getIterator() as $item) {
557560
if (
561+
!$item instanceof ArrayKey &&
558562
!$item instanceof String_ &&
559563
!$item instanceof Integer
560564
) {

src/Types/ArrayKey.php

+9-1
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,28 @@
1313

1414
namespace phpDocumentor\Reflection\Types;
1515

16+
use phpDocumentor\Reflection\PseudoType;
17+
use phpDocumentor\Reflection\Type;
18+
1619
/**
1720
* Value Object representing a array-key Type.
1821
*
1922
* A array-key Type is the supertype (but not a union) of int and string.
2023
*
2124
* @psalm-immutable
2225
*/
23-
final class ArrayKey extends AggregatedType
26+
final class ArrayKey extends AggregatedType implements PseudoType
2427
{
2528
public function __construct()
2629
{
2730
parent::__construct([new String_(), new Integer()], '|');
2831
}
2932

33+
public function underlyingType(): Type
34+
{
35+
return new Compound([new String_(), new Integer()]);
36+
}
37+
3038
public function __toString(): string
3139
{
3240
return 'array-key';

src/Types/ClassString.php

+7-1
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@
1414
namespace phpDocumentor\Reflection\Types;
1515

1616
use phpDocumentor\Reflection\Fqsen;
17+
use phpDocumentor\Reflection\PseudoType;
1718
use phpDocumentor\Reflection\Type;
1819

1920
/**
2021
* Value Object representing the type 'string'.
2122
*
2223
* @psalm-immutable
2324
*/
24-
final class ClassString implements Type
25+
final class ClassString extends String_ implements PseudoType
2526
{
2627
/** @var Fqsen|null */
2728
private $fqsen;
@@ -34,6 +35,11 @@ public function __construct(?Fqsen $fqsen = null)
3435
$this->fqsen = $fqsen;
3536
}
3637

38+
public function underlyingType(): Type
39+
{
40+
return new String_();
41+
}
42+
3743
/**
3844
* Returns the FQSEN associated with this object.
3945
*/

tests/unit/CollectionResolverTest.php

+13
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,19 @@ public function testBadArrayCollectionKey(): void
223223
$fixture->resolve('array<object,string>', new Context(''));
224224
}
225225

226+
/**
227+
* @covers ::__construct
228+
* @covers ::resolve
229+
*/
230+
public function testGoodArrayCollectionKey(): void
231+
{
232+
$fixture = new TypeResolver();
233+
$fixture->resolve('array<array-key,string>', new Context(''));
234+
235+
$fixture = new TypeResolver();
236+
$fixture->resolve('array<class-string,string>', new Context(''));
237+
}
238+
226239
/**
227240
* @covers ::__construct
228241
* @covers ::resolve

tests/unit/TypeResolverTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,7 @@ public function provideKeywords(): array
758758
['parent', Types\Parent_::class],
759759
['iterable', Types\Iterable_::class],
760760
['never', Types\Never_::class],
761+
['literal-string', PseudoTypes\LiteralString::class],
761762
];
762763
}
763764

0 commit comments

Comments
 (0)