Skip to content

Commit 0e496ac

Browse files
herndlmondrejmirtes
authored andcommitted
Support isInstanceOfAny
1 parent a46f664 commit 0e496ac

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ This extension specifies types of values passed to:
4545
* `Assert::isIterable`
4646
* `Assert::isCountable`
4747
* `Assert::isInstanceOf`
48+
* `Assert::isInstanceOfAny`
4849
* `Assert::notInstanceOf`
4950
* `Assert::isAOf`
5051
* `Assert::subclassOf`

src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php

+42
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
use Countable;
88
use PhpParser\Node\Arg;
99
use PhpParser\Node\Expr;
10+
use PhpParser\Node\Expr\Array_;
11+
use PhpParser\Node\Expr\ArrayItem;
12+
use PhpParser\Node\Expr\BinaryOp;
1013
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
1114
use PhpParser\Node\Expr\BinaryOp\BooleanOr;
1215
use PhpParser\Node\Expr\BinaryOp\Greater;
@@ -45,7 +48,11 @@
4548
use PHPStan\Type\TypeWithClassName;
4649
use ReflectionObject;
4750
use Traversable;
51+
use function array_filter;
4852
use function array_key_exists;
53+
use function array_map;
54+
use function array_reduce;
55+
use function array_shift;
4956
use function count;
5057
use function key;
5158
use function lcfirst;
@@ -366,6 +373,21 @@ private static function getExpressionResolvers(): array
366373
$className
367374
);
368375
},
376+
'isInstanceOfAny' => static function (Scope $scope, Arg $expr, Arg $classes): ?Expr {
377+
if (!$classes->value instanceof Array_ || $classes->value->items === null) {
378+
return null;
379+
}
380+
381+
$resolvers = array_map(
382+
static function (?ArrayItem $class) use ($scope, $expr) {
383+
return $class !== null ? self::$resolvers['isInstanceOf']($scope, $expr, new Arg($class->value)) : null;
384+
},
385+
$classes->value->items
386+
);
387+
$resolvers = array_filter($resolvers);
388+
389+
return self::implodeExpr($resolvers, BooleanOr::class);
390+
},
369391
'notInstanceOf' => static function (Scope $scope, Arg $expr, Arg $class): ?Expr {
370392
$classType = $scope->getType($class->value);
371393
if ($classType instanceof ConstantStringType) {
@@ -779,4 +801,24 @@ private function arrayOrIterable(
779801
);
780802
}
781803

804+
/**
805+
* @param Expr[] $expressions
806+
* @param class-string<BinaryOp> $binaryOp
807+
*/
808+
private static function implodeExpr(array $expressions, string $binaryOp): ?Expr
809+
{
810+
$firstExpression = array_shift($expressions);
811+
if ($firstExpression === null) {
812+
return null;
813+
}
814+
815+
return array_reduce(
816+
$expressions,
817+
static function (Expr $carry, Expr $item) use ($binaryOp) {
818+
return new $binaryOp($carry, $item);
819+
},
820+
$firstExpression
821+
);
822+
}
823+
782824
}

tests/Type/WebMozartAssert/data/type.php

+24
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,30 @@ public function isInstanceOf($a, $b, $c, $d): void
174174
\PHPStan\Testing\assertType('mixed', $d);
175175
}
176176

177+
public function isInstanceOfAny($a, $b, $c, $d, $e, $f, $g): void
178+
{
179+
Assert::isInstanceOfAny($a, [self::class, new stdClass()]);
180+
\PHPStan\Testing\assertType('PHPStan\Type\WebMozartAssert\TypeTest|stdClass', $a);
181+
182+
Assert::isInstanceOfAny($b, [new stdClass()]);
183+
\PHPStan\Testing\assertType('stdClass', $b);
184+
185+
Assert::isInstanceOfAny($c, []);
186+
\PHPStan\Testing\assertType('mixed', $c);
187+
188+
Assert::isInstanceOfAny($d, 'foo');
189+
\PHPStan\Testing\assertType('mixed', $d);
190+
191+
Assert::isInstanceOfAny($e, [17]);
192+
\PHPStan\Testing\assertType('mixed', $e);
193+
194+
Assert::isInstanceOfAny($f, [17, self::class]);
195+
\PHPStan\Testing\assertType('PHPStan\Type\WebMozartAssert\TypeTest', $f);
196+
197+
Assert::nullOrIsInstanceOfAny($g, [self::class, new stdClass()]);
198+
\PHPStan\Testing\assertType('PHPStan\Type\WebMozartAssert\TypeTest|stdClass|null', $g);
199+
}
200+
177201
/**
178202
* @param Foo|Bar $a
179203
* @param Foo|stdClass $b

0 commit comments

Comments
 (0)