Skip to content

Commit e8a0044

Browse files
authored
Feature: Iterate over an iterable (#31)
Signed-off-by: Nathanael Esayeas <nathanael.esayeas@protonmail.com>
2 parents d03bece + 5026e6a commit e8a0044

10 files changed

+279
-203
lines changed

composer.lock

+235-173
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

phpunit.xml.dist

+7-1
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,23 @@
44
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd"
55
beStrictAboutCoverageMetadata="true"
66
beStrictAboutOutputDuringTests="true"
7+
beStrictAboutChangesToGlobalState="true"
8+
beStrictAboutTestsThatDoNotTestAnything="true"
9+
beStrictAboutTodoAnnotatedTests="true"
710
bootstrap="vendor/autoload.php"
811
cacheDirectory=".cache/phpunit"
912
colors="true"
1013
executionOrder="depends,defects"
1114
failOnRisky="true"
1215
failOnWarning="true"
16+
failOnEmptyTestSuite="true"
17+
failOnIncomplete="true"
18+
failOnSkipped="true"
1319
requireCoverageMetadata="true"
1420
testdox="true"
1521
>
1622
<testsuites>
17-
<testsuite name="Test Suite">
23+
<testsuite name="Option Test Suite">
1824
<directory>tests/Unit</directory>
1925
</testsuite>
2026
</testsuites>

psalm-baseline.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<files psalm-version="5.0.0@4e177bf0c9f03c17d2fbfd83b7cc9c47605274d8"/>
2+
<files psalm-version="5.8.0@9cf4f60a333f779ad3bc704a555920e81d4fdcda"/>

src/Contract/NoneInterface.php

+2-4
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@
55
namespace Ghostwriter\Option\Contract;
66

77
/**
8-
* @immutable
9-
*
10-
* @implements OptionInterface<TValue>
11-
*
128
* @template TValue
9+
*
10+
* @extends OptionInterface<TValue>
1311
*/
1412
interface NoneInterface extends OptionInterface
1513
{

src/Contract/OptionInterface.php

+8-8
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44

55
namespace Ghostwriter\Option\Contract;
66

7+
use Generator;
78
use Ghostwriter\Option\Exception\NullPointerException;
89
use IteratorAggregate;
910
use Throwable;
10-
use Traversable;
1111

1212
/**
13-
* @implements IteratorAggregate<int,TValue>
14-
*
1513
* @template TValue
14+
*
15+
* @extends IteratorAggregate<int,TValue>
1616
*/
1717
interface OptionInterface extends IteratorAggregate
1818
{
@@ -27,15 +27,15 @@ public function and(self $option): self;
2727
* @template TAndThen
2828
*
2929
* @param callable(TValue):TAndThen $function
30-
*
31-
* @return self<TAndThen|TValue>
3230
*/
3331
public function andThen(callable $function): self;
3432

3533
/**
3634
* Returns true if the option is a Some value containing the given $value.
3735
*
38-
* @param TValue $value
36+
* @template TContainsValue
37+
*
38+
* @param TContainsValue $value
3939
*/
4040
public function contains(mixed $value): bool;
4141

@@ -65,7 +65,7 @@ public function filter(callable $function): self;
6565
*/
6666
public function flatten(): self;
6767

68-
public function getIterator(): Traversable;
68+
public function getIterator(): Generator;
6969

7070
/**
7171
* Returns true if the Option is an instance of None.
@@ -140,7 +140,7 @@ public function or(self $option): self;
140140
*
141141
* @template TCallableResultValue
142142
*
143-
* @param callable(): OptionInterface<TCallableResultValue> $function
143+
* @param callable(): self<TCallableResultValue> $function
144144
*/
145145
public function orElse(callable $function): self;
146146

src/Contract/SomeInterface.php

+2-4
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@
55
namespace Ghostwriter\Option\Contract;
66

77
/**
8-
* @immutable
9-
*
10-
* @implements OptionInterface<TValue>
11-
*
128
* @template TValue
9+
*
10+
* @extends OptionInterface<TValue>
1311
*/
1412
interface SomeInterface extends OptionInterface
1513
{

src/None.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@
55
namespace Ghostwriter\Option;
66

77
use Ghostwriter\Option\Contract\NoneInterface;
8+
use Ghostwriter\Option\Tests\Unit\NoneTest;
89
use Ghostwriter\Option\Traits\OptionTrait;
910

1011
/**
11-
* @immutable
12+
* @template TValue
1213
*
1314
* @implements NoneInterface<TValue>
1415
*
15-
* @template TValue
16+
* @see NoneTest
1617
*/
1718
final class None implements NoneInterface
1819
{

src/Some.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66

77
use Ghostwriter\Option\Contract\SomeInterface;
88
use Ghostwriter\Option\Exception\NullPointerException;
9+
use Ghostwriter\Option\Tests\Unit\SomeTest;
910
use Ghostwriter\Option\Traits\OptionTrait;
1011

1112
/**
12-
* @immutable
13+
* @template TValue
1314
*
1415
* @implements SomeInterface<TValue>
1516
*
16-
* @template TValue
17+
* @see SomeTest
1718
*/
1819
final class Some implements SomeInterface
1920
{

src/Traits/OptionTrait.php

+15-8
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Ghostwriter\Option\Traits;
66

7+
use Generator;
78
use Ghostwriter\Option\Contract\NoneInterface;
89
use Ghostwriter\Option\Contract\OptionInterface;
910
use Ghostwriter\Option\Contract\SomeInterface;
@@ -12,19 +13,16 @@
1213
use Ghostwriter\Option\None;
1314
use Ghostwriter\Option\Some;
1415
use Throwable;
15-
use Traversable;
1616

1717
/**
1818
* @template TValue
19-
*
20-
* @immutable
21-
*
22-
* @implements OptionInterface<TValue>
2319
*/
2420
trait OptionTrait
2521
{
22+
private static ?NoneInterface $none = null;
23+
2624
/**
27-
* @param ?TValue $value
25+
* @param TValue $value
2826
*/
2927
private function __construct(
3028
private readonly mixed $value = null
@@ -87,10 +85,19 @@ public function flatten(): OptionInterface
8785
return $this->map(fn (mixed $value) => $value instanceof SomeInterface ? $value : $this);
8886
}
8987

90-
public function getIterator(): Traversable
88+
public function getIterator(): Generator
9189
{
9290
if ($this instanceof SomeInterface) {
93-
yield $this->value;
91+
/**
92+
* @var TValue $value
93+
*/
94+
$value = $this->value;
95+
96+
if (is_iterable($value)) {
97+
yield from $value;
98+
} else {
99+
yield $value;
100+
}
94101
}
95102
}
96103

tests/Unit/SomeTest.php

+3
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ public function testGetIterator(): void
171171
{
172172
$some = Some::create('foo');
173173
self::assertCount(1, iterator_to_array($some));
174+
175+
$some = Some::create(['foo', 'bar']);
176+
self::assertCount(2, iterator_to_array($some));
174177
}
175178

176179
/**

0 commit comments

Comments
 (0)