Skip to content

Commit 3937f41

Browse files
herndlmondrejmirtes
authored andcommitted
Support isAnyOf
1 parent ceb5414 commit 3937f41

File tree

3 files changed

+38
-13
lines changed

3 files changed

+38
-13
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ This extension specifies types of values passed to:
4848
* `Assert::isInstanceOfAny`
4949
* `Assert::notInstanceOf`
5050
* `Assert::isAOf`
51+
* `Assert::isAnyOf`
5152
* `Assert::subclassOf`
5253
* `Assert::true`
5354
* `Assert::false`

src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -392,19 +392,7 @@ private static function getExpressionResolvers(): array
392392
);
393393
},
394394
'isInstanceOfAny' => static function (Scope $scope, Arg $expr, Arg $classes): ?Expr {
395-
if (!$classes->value instanceof Array_ || $classes->value->items === null) {
396-
return null;
397-
}
398-
399-
$resolvers = array_map(
400-
static function (?ArrayItem $class) use ($scope, $expr) {
401-
return $class !== null ? self::$resolvers['isInstanceOf']($scope, $expr, new Arg($class->value)) : null;
402-
},
403-
$classes->value->items
404-
);
405-
$resolvers = array_filter($resolvers);
406-
407-
return self::implodeExpr($resolvers, BooleanOr::class);
395+
return self::buildAnyOfExpr($scope, $expr, $classes, self::$resolvers['isInstanceOf']);
408396
},
409397
'notInstanceOf' => static function (Scope $scope, Arg $expr, Arg $class): ?Expr {
410398
$expr = self::$resolvers['isInstanceOf']($scope, $expr, $class);
@@ -423,6 +411,9 @@ static function (?ArrayItem $class) use ($scope, $expr) {
423411
[$expr, $class, new Arg(new ConstFetch(new Name($allowString ? 'true' : 'false')))]
424412
);
425413
},
414+
'isAnyOf' => static function (Scope $scope, Arg $value, Arg $classes): ?Expr {
415+
return self::buildAnyOfExpr($scope, $value, $classes, self::$resolvers['isAOf']);
416+
},
426417
'implementsInterface' => static function (Scope $scope, Arg $expr, Arg $class): ?Expr {
427418
$classType = $scope->getType($class->value);
428419
if (!$classType instanceof ConstantStringType) {
@@ -818,4 +809,21 @@ static function (Expr $carry, Expr $item) use ($binaryOp) {
818809
);
819810
}
820811

812+
private static function buildAnyOfExpr(Scope $scope, Arg $value, Arg $items, callable $resolver): ?Expr
813+
{
814+
if (!$items->value instanceof Array_ || $items->value->items === null) {
815+
return null;
816+
}
817+
818+
$resolvers = array_map(
819+
static function (?ArrayItem $item) use ($scope, $value, $resolver) {
820+
return $item !== null ? $resolver($scope, $value, new Arg($item->value)) : null;
821+
},
822+
$items->value->items
823+
);
824+
$resolvers = array_filter($resolvers);
825+
826+
return self::implodeExpr($resolvers, BooleanOr::class);
827+
}
828+
821829
}

tests/Type/WebMozartAssert/data/type.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Type\WebMozartAssert;
44

5+
use DateTimeImmutable;
56
use stdClass;
67
use Webmozart\Assert\Assert;
78

@@ -233,6 +234,21 @@ public function isAOf($a, $b, string $c): void
233234
\PHPStan\Testing\assertType('class-string<stdClass>', $c);
234235
}
235236

237+
public function isAnyOf($a, $b): void
238+
{
239+
Assert::isAnyOf($a, [DateTimeImmutable::class, stdClass::class]);
240+
\PHPStan\Testing\assertTyp0e('DateTimeImmutable|stdClass', $a);
241+
242+
Assert::isAnyOf($b, []);
243+
\PHPStan\Testing\assertType('mixed', $b);
244+
245+
Assert::isAnyOf(Foo::class, [stdClass::class, Bar::class]);
246+
\PHPStan\Testing\assertType('*NEVER*', Foo::class);
247+
248+
Assert::isAnyOf(Bar::class, [stdClass::class, Foo::class]);
249+
\PHPStan\Testing\assertType('\'PHPStan\\\Type\\\WebMozartAssert\\\Bar\'', Bar::class);
250+
}
251+
236252
public function isArrayAccessible($a, $b): void
237253
{
238254
Assert::isArrayAccessible($a);

0 commit comments

Comments
 (0)