Skip to content

Commit

Permalink
Add CollectionTypeInferenceTest
Browse files Browse the repository at this point in the history
  • Loading branch information
paulbalandan committed Sep 8, 2024
1 parent f9a5aaa commit 84c811c
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 3 deletions.
20 changes: 17 additions & 3 deletions src/Nexus/Collection/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,15 @@ public function __construct(\Closure $callable, iterable $parameter = [])
$this->innerIterator = ClosureIteratorAggregate::from($callable, ...$parameter);
}

public static function wrap(\Closure|iterable $items): CollectionInterface
/**
* @template WKey
* @template W
*
* @param (\Closure(): iterable<WKey, W>)|iterable<WKey, W> $items
*
* @return self<WKey, W>
*/
public static function wrap(\Closure|iterable $items): self
{
if ($items instanceof \Closure) {
return new self(static fn(): \Generator => yield from $items());
Expand Down Expand Up @@ -76,7 +84,10 @@ public function getIterator(): \Traversable
yield from $this->innerIterator->getIterator();
}

public function keys(): CollectionInterface
/**
* @return self<int, TKey>
*/
public function keys(): self
{
return new self(static function (iterable $collection): iterable {
foreach ($collection as $key => $_) {
Expand All @@ -85,7 +96,10 @@ public function keys(): CollectionInterface
}, [$this]);
}

public function values(): CollectionInterface
/**
* @return self<int, T>
*/
public function values(): self
{
return new self(static function (iterable $collection): iterable {
foreach ($collection as $item) {
Expand Down
42 changes: 42 additions & 0 deletions tests/Collection/CollectionTypeInferenceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Nexus framework.
*
* (c) John Paul E. Balandan, CPA <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace Nexus\Tests\Collection;

use PHPStan\Testing\TypeInferenceTestCase;
use PHPUnit\Framework\Attributes\CoversNothing;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Group;

/**
* @internal
*/
#[CoversNothing]
#[Group('static-analysis')]
final class CollectionTypeInferenceTest extends TypeInferenceTestCase
{
#[DataProvider('provideFileAssertsCases')]
public function testFileAsserts(string $assertType, string $file, mixed ...$args): void
{
$this->assertFileAsserts($assertType, $file, ...$args);
}

/**
* @return iterable<string, list<mixed>>
*/
public static function provideFileAssertsCases(): iterable
{
// @phpstan-ignore generator.valueType
yield from self::gatherAssertTypesFromDirectory(__DIR__.'/data');
}
}
44 changes: 44 additions & 0 deletions tests/Collection/data/collection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Nexus framework.
*
* (c) John Paul E. Balandan, CPA <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace Nexus\Tests\Collection;

use Nexus\Collection\Collection;

use function PHPStan\Testing\assertType;

assertType(
'Nexus\Collection\Collection<string, int>',
new Collection(static function (): iterable {
yield 'apple' => 1;
}),
);
assertType('Nexus\Collection\Collection<int, string>', Collection::wrap(['a', 'b', 'c']));
assertType(
'Nexus\Collection\Collection<string, bool>',
Collection::wrap(static function (): iterable {
yield 'a' => true;

yield 'b' => true;

yield 'c' => false;
}),
);
assertType('Nexus\Collection\Collection<int, int>', Collection::wrap(new \ArrayIterator([1, 2])));

assertType('array<int>', Collection::wrap(['a' => 1, 'b' => 2])->all(true));
assertType('array<int, int>', Collection::wrap(['a' => 1, 'b' => 2])->all());

$collection = Collection::wrap(['apples' => 10, 'bananas' => 20]);
assertType('Nexus\Collection\Collection<int, string>', $collection->keys());
assertType('Nexus\Collection\Collection<int, int>', $collection->values());
41 changes: 41 additions & 0 deletions tests/Collection/data/iterator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Nexus framework.
*
* (c) John Paul E. Balandan, CPA <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace Nexus\Tests\Collection;

use Nexus\Collection\Collection;
use Nexus\Collection\Iterator\ClosureIteratorAggregate;

use function PHPStan\Testing\assertType;

assertType(
'Nexus\Collection\Iterator\ClosureIteratorAggregate<int, string>',
ClosureIteratorAggregate::from(
static fn(string $item): iterable => yield $item,
'a',
),
);
assertType(
// @todo Make PHPStan understand the key is 'int'
'Nexus\Collection\Iterator\ClosureIteratorAggregate<mixed, string>',
ClosureIteratorAggregate::from(
static function (iterable $collection): iterable {
foreach ($collection as $key => $item) {
assertType('int', $key);

yield $key => get_debug_type($item);
}
},
Collection::wrap([1, new \stdClass()]),
),
);

0 comments on commit 84c811c

Please sign in to comment.