diff --git a/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php b/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php index b4c4f8b..4d29712 100644 --- a/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php +++ b/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php @@ -752,6 +752,9 @@ private function getExpressionResolvers(): array ) ); }, + 'uniqueValues' => static function (Scope $scope, Arg $value): array { + return self::createIsNonEmptyArrayAndSomethingExprPair('uniqueValues', [$value]); + }, ]; foreach (['contains', 'startsWith', 'endsWith'] as $name) { @@ -784,7 +787,6 @@ private function getExpressionResolvers(): array return self::createIsNonEmptyStringAndSomethingExprPair($name, [$value]); }; } - } return $this->resolvers; @@ -1003,6 +1005,28 @@ private static function createIsNonEmptyStringAndSomethingExprPair(string $name, return [$expr, $rootExpr]; } + /** + * @param Arg[] $args + * @return array{Expr, Expr} + */ + private static function createIsNonEmptyArrayAndSomethingExprPair(string $name, array $args): array + { + $expr = new GreaterOrEqual( + new FuncCall( + new Name('count'), + [$args[0]] + ), + new LNumber(1) + ); + + $rootExpr = new BooleanAnd( + $expr, + new FuncCall(new Name('FAUX_FUNCTION_ ' . $name), $args) + ); + + return [$expr, $rootExpr]; + } + private function specifyRootExprIfSet(?Expr $rootExpr, SpecifiedTypes $specifiedTypes): SpecifiedTypes { if ($rootExpr === null) { diff --git a/tests/Type/WebMozartAssert/data/type.php b/tests/Type/WebMozartAssert/data/type.php index f920254..b075a8f 100644 --- a/tests/Type/WebMozartAssert/data/type.php +++ b/tests/Type/WebMozartAssert/data/type.php @@ -305,6 +305,12 @@ public function isArrayAccessible($a, $b): void Assert::nullOrIsArrayAccessible($b); assertType('array|ArrayAccess|null', $b); } + + public function uniqueValues(array $a): void + { + Assert::uniqueValues($a); + assertType('non-empty-array', $a); + } } class Foo {}