Skip to content

Commit

Permalink
Merge pull request #132 from voku/array-key-fix
Browse files Browse the repository at this point in the history
Fix: An array can have only integers or strings as keys
  • Loading branch information
jaapio authored Oct 2, 2021
2 parents 4b3579f + ccac888 commit a12f7e3
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ psalm:

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

.PHONY: pre-commit-test
pre-commit-test: test phpcs phpstan psalm
Expand Down
39 changes: 39 additions & 0 deletions src/PseudoTypes/LiteralString.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link http://phpdoc.org
*/

namespace phpDocumentor\Reflection\PseudoTypes;

use phpDocumentor\Reflection\PseudoType;
use phpDocumentor\Reflection\Type;
use phpDocumentor\Reflection\Types\String_;

/**
* Value Object representing the type 'string'.
*
* @psalm-immutable
*/
final class LiteralString extends String_ implements PseudoType
{
public function underlyingType(): Type
{
return new String_();
}

/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*/
public function __toString(): string
{
return 'literal-string';
}
}
4 changes: 4 additions & 0 deletions src/TypeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use ArrayIterator;
use InvalidArgumentException;
use phpDocumentor\Reflection\Types\Array_;
use phpDocumentor\Reflection\Types\ArrayKey;
use phpDocumentor\Reflection\Types\ClassString;
use phpDocumentor\Reflection\Types\Collection;
use phpDocumentor\Reflection\Types\Compound;
Expand Down Expand Up @@ -102,6 +103,7 @@ final class TypeResolver
'callable-string' => PseudoTypes\CallableString::class,
'false' => PseudoTypes\False_::class,
'true' => PseudoTypes\True_::class,
'literal-string' => PseudoTypes\LiteralString::class,
'self' => Types\Self_::class,
'$this' => Types\This::class,
'static' => Types\Static_::class,
Expand Down Expand Up @@ -543,6 +545,7 @@ private function resolveCollection(ArrayIterator $tokens, Type $classType, Conte
// check the key type for an "array" collection. We allow only
// strings or integers.
if (
!$keyType instanceof ArrayKey &&
!$keyType instanceof String_ &&
!$keyType instanceof Integer &&
!$keyType instanceof Compound
Expand All @@ -555,6 +558,7 @@ private function resolveCollection(ArrayIterator $tokens, Type $classType, Conte
if ($keyType instanceof Compound) {
foreach ($keyType->getIterator() as $item) {
if (
!$item instanceof ArrayKey &&
!$item instanceof String_ &&
!$item instanceof Integer
) {
Expand Down
10 changes: 9 additions & 1 deletion src/Types/ArrayKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,28 @@

namespace phpDocumentor\Reflection\Types;

use phpDocumentor\Reflection\PseudoType;
use phpDocumentor\Reflection\Type;

/**
* Value Object representing a array-key Type.
*
* A array-key Type is the supertype (but not a union) of int and string.
*
* @psalm-immutable
*/
final class ArrayKey extends AggregatedType
final class ArrayKey extends AggregatedType implements PseudoType
{
public function __construct()
{
parent::__construct([new String_(), new Integer()], '|');
}

public function underlyingType(): Type
{
return new Compound([new String_(), new Integer()]);
}

public function __toString(): string
{
return 'array-key';
Expand Down
8 changes: 7 additions & 1 deletion src/Types/ClassString.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@
namespace phpDocumentor\Reflection\Types;

use phpDocumentor\Reflection\Fqsen;
use phpDocumentor\Reflection\PseudoType;
use phpDocumentor\Reflection\Type;

/**
* Value Object representing the type 'string'.
*
* @psalm-immutable
*/
final class ClassString implements Type
final class ClassString extends String_ implements PseudoType
{
/** @var Fqsen|null */
private $fqsen;
Expand All @@ -34,6 +35,11 @@ public function __construct(?Fqsen $fqsen = null)
$this->fqsen = $fqsen;
}

public function underlyingType(): Type
{
return new String_();
}

/**
* Returns the FQSEN associated with this object.
*/
Expand Down
13 changes: 13 additions & 0 deletions tests/unit/CollectionResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,19 @@ public function testBadArrayCollectionKey(): void
$fixture->resolve('array<object,string>', new Context(''));
}

/**
* @covers ::__construct
* @covers ::resolve
*/
public function testGoodArrayCollectionKey(): void
{
$fixture = new TypeResolver();
$fixture->resolve('array<array-key,string>', new Context(''));

$fixture = new TypeResolver();
$fixture->resolve('array<class-string,string>', new Context(''));
}

/**
* @covers ::__construct
* @covers ::resolve
Expand Down
1 change: 1 addition & 0 deletions tests/unit/TypeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,7 @@ public function provideKeywords(): array
['parent', Types\Parent_::class],
['iterable', Types\Iterable_::class],
['never', Types\Never_::class],
['literal-string', PseudoTypes\LiteralString::class],
];
}

Expand Down

0 comments on commit a12f7e3

Please sign in to comment.