diff --git a/README.md b/README.md index 41b4545..6d2998f 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ This extension specifies types of values passed to: * `Assert::classExists` * `Assert::interfaceExists` * `Assert::validArrayKey` +* `Assert::count` * `Assert::minCount` * `Assert::inArray` * `Assert::oneOf` diff --git a/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php b/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php index 1c9e733..7e3014a 100644 --- a/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php +++ b/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php @@ -395,6 +395,15 @@ private static function getExpressionResolvers(): array [$class] ); }, + 'count' => function (Scope $scope, Arg $array, Arg $number): \PhpParser\Node\Expr { + return new \PhpParser\Node\Expr\BinaryOp\Identical( + new \PhpParser\Node\Expr\FuncCall( + new \PhpParser\Node\Name('count'), + [$array] + ), + $number->value + ); + }, 'minCount' => function (Scope $scope, Arg $array, Arg $number): \PhpParser\Node\Expr { return new \PhpParser\Node\Expr\BinaryOp\GreaterOrEqual( new \PhpParser\Node\Expr\FuncCall( diff --git a/tests/Type/WebMozartAssert/data/data.php b/tests/Type/WebMozartAssert/data/data.php index fbfc5ae..0d1866b 100644 --- a/tests/Type/WebMozartAssert/data/data.php +++ b/tests/Type/WebMozartAssert/data/data.php @@ -174,6 +174,14 @@ public function doFoo($a, $b, array $c, iterable $d, $e, $f, $g, $h, $i, $j, $k, Assert::interfaceExists($ag); \PHPStan\Testing\assertType('class-string', $ag); + + /** @var int[] $at */ + $at = doFoo(); + Assert::count($at, 1); + $au = array_pop($at); + $av = array_pop($at); + \PHPStan\Testing\assertType('int', $au); + \PHPStan\Testing\assertType('int|null', $av); } }