diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
index 862be75..f673d86 100644
--- a/.github/workflows/static-analysis.yml
+++ b/.github/workflows/static-analysis.yml
@@ -32,3 +32,27 @@ jobs:
- name: "Run a static analysis with phpstan/phpstan"
run: "vendor/bin/phpstan analyse --error-format=checkstyle | cs2pr"
+
+ static-analysis-psalm:
+ name: "Static Analysis with Psalm"
+ runs-on: "ubuntu-20.04"
+
+ strategy:
+ matrix:
+ php-version:
+ - "7.3"
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+
+ - name: Psalm
+ uses: docker://vimeo/psalm-github-actions:4.4.1
+ with:
+ composer_require_dev: true
+ security_analysis: true
+ report_file: results.sarif
+ - name: Upload Security Analysis results to GitHub
+ uses: github/codeql-action/upload-sarif@v1
+ with:
+ sarif_file: results.sarif
diff --git a/.gitignore b/.gitignore
index 6f24d73..56ed85a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,5 +3,6 @@
/composer.lock
/phpcs.xml
/phpstan.neon
+/psalm.xml
/phpunit.xml
/vendor/
diff --git a/README.md b/README.md
index 890c809..4b615dd 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
[](https://packagist.org/packages/bentools/iterable-functions)
[![GitHub Actions][GA master image]][GA master]
[![Code Coverage][Coverage image]][CodeCov Master]
+[![Shepherd Type][Shepherd Image]][Shepherd Link]
[](https://packagist.org/packages/bentools/iterable-functions)
Iterable functions
@@ -177,7 +178,14 @@ Unit tests
php vendor/bin/pest
```
-[CodeCov Master]: https://codecov.io/gh/bpolaszek/php-iterable-functions/branch/2.0.x-dev
-[Coverage image]: https://codecov.io/gh/bpolaszek/php-iterable-functions/branch/2.0.x-dev/graph/badge.svg
[GA master]: https://github.com/bpolaszek/php-iterable-functions/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A2.0.x-dev
+
[GA master image]: https://github.com/bpolaszek/php-iterable-functions/workflows/Continuous%20Integration/badge.svg
+
+[CodeCov Master]: https://codecov.io/gh/bpolaszek/php-iterable-functions/branch/2.0.x-dev
+
+[Coverage image]: https://codecov.io/gh/bpolaszek/php-iterable-functions/branch/2.0.x-dev/graph/badge.svg
+
+[Shepherd Image]: https://shepherd.dev/github/bpolaszek/php-iterable-functions/coverage.svg
+
+[Shepherd Link]: https://shepherd.dev/github/bpolaszek/php-iterable-functions
diff --git a/composer.json b/composer.json
index b6a5021..7730355 100644
--- a/composer.json
+++ b/composer.json
@@ -26,7 +26,8 @@
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "^0.12.67",
"phpstan/phpstan-strict-rules": "^0.12.9",
- "symfony/var-dumper": "^5.2"
+ "symfony/var-dumper": "^5.2",
+ "vimeo/psalm": "^4.4"
},
"config": {
"sort-packages": true
diff --git a/psalm.xml.dist b/psalm.xml.dist
new file mode 100644
index 0000000..3e6a115
--- /dev/null
+++ b/psalm.xml.dist
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/iterable-functions.php b/src/iterable-functions.php
index c35732c..f9a698d 100644
--- a/src/iterable-functions.php
+++ b/src/iterable-functions.php
@@ -73,9 +73,11 @@ function iterable_to_traversable(iterable $iterable): Traversable
function iterable_filter(iterable $iterable, ?callable $filter = null)
{
if ($filter === null) {
- $filter = static function ($value): bool {
- return (bool) $value;
- };
+ $filter =
+ /** @param mixed $value */
+ static function ($value): bool {
+ return (bool) $value;
+ };
}
if ($iterable instanceof Traversable) {
diff --git a/tests/IterableFilterTest.php b/tests/IterableFilterTest.php
index 083d355..c1a44c5 100644
--- a/tests/IterableFilterTest.php
+++ b/tests/IterableFilterTest.php
@@ -23,7 +23,9 @@
it('filters an array with a callback', function (): void {
$iterable = ['foo', 'bar'];
- $filter = static function ($input): bool {
+ $filter =
+ /** @param mixed $input */
+ static function ($input): bool {
return $input === 'bar';
};
assertEquals([1 => 'bar'], iterable_to_array(iterable_filter($iterable, $filter)));
@@ -31,7 +33,9 @@
it('filters a Travsersable object with a callback', function (): void {
$iterable = SplFixedArray::fromArray(['foo', 'bar']);
- $filter = static function ($input): bool {
+ $filter =
+ /** @param mixed $input */
+ static function ($input): bool {
return $input === 'bar';
};
assertEquals([1 => 'bar'], iterable_to_array(iterable_filter($iterable, $filter)));
diff --git a/tests/IterableObjectTest.php b/tests/IterableObjectTest.php
index f7dc96b..3eee1f5 100644
--- a/tests/IterableObjectTest.php
+++ b/tests/IterableObjectTest.php
@@ -17,9 +17,11 @@
$dataProvider = static function (): Generator {
$data = ['foo', 'bar'];
- $filter = static function ($value): bool {
- return $value === 'bar';
- };
+ $filter =
+ /** @param mixed $value */
+ static function ($value): bool {
+ return $value === 'bar';
+ };
$map = 'strtoupper';
yield from [
@@ -50,32 +52,50 @@
];
};
-test('input: array | output: traversable', function ($data, $filter, $map, $expectedResult): void {
- $iterableObject = iterable($data, $filter, $map);
- assertEquals($expectedResult, iterator_to_array($iterableObject));
-})->with($dataProvider());
+test(
+ 'input: array | output: traversable',
+ /** @param array $data */
+ function (array $data, ?callable $filter, ?callable $map, array $expectedResult): void {
+ $iterableObject = iterable($data, $filter, $map);
+ assertEquals($expectedResult, iterator_to_array($iterableObject));
+ }
+)->with($dataProvider());
-test('input: array | output: array', function ($data, $filter, $map, $expectedResult): void {
- $iterableObject = iterable($data, $filter, $map);
- assertEquals($expectedResult, $iterableObject->asArray());
-})->with($dataProvider());
+test(
+ 'input: array | output: array',
+ /** @param array $data */
+ function (array $data, ?callable $filter, ?callable $map, array $expectedResult): void {
+ $iterableObject = iterable($data, $filter, $map);
+ assertEquals($expectedResult, $iterableObject->asArray());
+ }
+)->with($dataProvider());
-test('input: traversable | output: traversable', function ($data, $filter, $map, $expectedResult): void {
- $data = SplFixedArray::fromArray($data);
- $iterableObject = iterable($data, $filter, $map);
- assertEquals($expectedResult, iterator_to_array($iterableObject));
-})->with($dataProvider());
+test(
+ 'input: traversable | output: traversable',
+ /** @param array $data */
+ function (array $data, ?callable $filter, ?callable $map, array $expectedResult): void {
+ $data = SplFixedArray::fromArray($data);
+ $iterableObject = iterable($data, $filter, $map);
+ assertEquals($expectedResult, iterator_to_array($iterableObject));
+ }
+)->with($dataProvider());
-test('input: traversable | output: array', function ($data, $filter, $map, $expectedResult): void {
- $data = SplFixedArray::fromArray($data);
- $iterableObject = iterable($data, $filter, $map);
- assertEquals($expectedResult, $iterableObject->asArray());
-})->with($dataProvider());
+test(
+ 'input: traversable | output: array',
+ /** @param array $data */
+ function (array $data, ?callable $filter, ?callable $map, array $expectedResult): void {
+ $data = SplFixedArray::fromArray($data);
+ $iterableObject = iterable($data, $filter, $map);
+ assertEquals($expectedResult, $iterableObject->asArray());
+ }
+)->with($dataProvider());
it('filters the subject', function (): void {
- $filter = static function ($value): bool {
- return $value === 'bar';
- };
+ $filter =
+ /** @param mixed $value */
+ static function ($value): bool {
+ return $value === 'bar';
+ };
$iterableObject = iterable(['foo', 'bar'])->filter($filter);
assertEquals([1 => 'bar'], iterator_to_array($iterableObject));
});
@@ -88,9 +108,11 @@
});
it('combines filter and map', function (): void {
- $filter = static function ($value): bool {
- return $value === 'bar';
- };
+ $filter =
+ /** @param mixed $value */
+ static function ($value): bool {
+ return $value === 'bar';
+ };
$map = 'strtoupper';
$iterableObject = iterable(['foo', 'bar'])->map($map)->filter($filter);
assertInstanceOf(IterableObject::class, $iterableObject);
diff --git a/tests/IterableReduceTest.php b/tests/IterableReduceTest.php
index f6ee50d..0001cc4 100644
--- a/tests/IterableReduceTest.php
+++ b/tests/IterableReduceTest.php
@@ -12,16 +12,16 @@
it('reduces an array', function (): void {
$iterable = [1, 2];
- $reduce = static function ($carry, $item) {
- return $carry + $item;
+ $reduce = static function (?int $carry, int $item): int {
+ return (int) $carry + $item;
};
assertSame(3, iterable_reduce($iterable, $reduce, 0));
});
it('reduces an traversable', function (): void {
$iterable = SplFixedArray::fromArray([1, 2]);
- $reduce = static function ($carry, $item) {
- return $carry + $item;
+ $reduce = static function (?int $carry, int $item): int {
+ return (int) $carry + $item;
};
assertSame(3, iterable_reduce($iterable, $reduce, 0));
});