Skip to content

Commit d02822e

Browse files
Add isNotInstanceOfAny assertion (#352)
1 parent ff31ad6 commit d02822e

5 files changed

Lines changed: 176 additions & 30 deletions

File tree

README.md

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -82,36 +82,37 @@ The [`Assert`] class provides the following assertions:
8282

8383
### Type Assertions
8484

85-
Method | Description
86-
-------------------------------------------------------- | --------------------------------------------------
87-
`string($value, $message = '')` | Check that a value is a string
88-
`stringNotEmpty($value, $message = '')` | Check that a value is a non-empty string
89-
`integer($value, $message = '')` | Check that a value is an integer
90-
`integerish($value, $message = '')` | Check that a value casts to an integer
91-
`positiveInteger($value, $message = '')` | Check that a value is a positive (non-zero) integer
92-
`negativeInteger($value, $message = '')` | Check that a value is a negative integer
93-
`notNegativeInteger($value, $message = '')` | Check that a value is a non-negative integer
94-
`float($value, $message = '')` | Check that a value is a float
95-
`numeric($value, $message = '')` | Check that a value is numeric
96-
`natural($value, $message = '')` | Check that a value is a non-negative integer
97-
`boolean($value, $message = '')` | Check that a value is a boolean
98-
`scalar($value, $message = '')` | Check that a value is a scalar
99-
`object($value, $message = '')` | Check that a value is an object
100-
`objectish($value, $message = '')` | Check that a value is an object or a string of a class that exists
101-
`resource($value, $type = null, $message = '')` | Check that a value is a resource
102-
`isInitialized($value, $property, $message = '')` | Check that a value has an initialized property
103-
`isCallable($value, $message = '')` | Check that a value is a callable
104-
`isArray($value, $message = '')` | Check that a value is an array
105-
`isIterable($value, $message = '')` | Check that a value is an array or a `\Traversable`
106-
`isCountable($value, $message = '')` | Check that a value is an array or a `\Countable`
107-
`isInstanceOf($value, $class, $message = '')` | Check that a value is an `instanceof` a class
108-
`isInstanceOfAny($value, array $classes, $message = '')` | Check that a value is an `instanceof` at least one class on the array of classes
109-
`notInstanceOf($value, $class, $message = '')` | Check that a value is not an `instanceof` a class
110-
`isAOf($value, $class, $message = '')` | Check that a value is of the class or has one of its parents
111-
`isAnyOf($value, array $classes, $message = '')` | Check that a value is of at least one of the classes or has one of its parents
112-
`isNotA($value, $class, $message = '')` | Check that a value is not of the class or has not one of its parents
113-
`isArrayAccessible($value, $message = '')` | Check that a value can be accessed as an array
114-
`uniqueValues($values, $message = '')` | Check that the given array contains unique values
85+
Method | Description
86+
----------------------------------------------------------- | --------------------------------------------------
87+
`string($value, $message = '')` | Check that a value is a string
88+
`stringNotEmpty($value, $message = '')` | Check that a value is a non-empty string
89+
`integer($value, $message = '')` | Check that a value is an integer
90+
`integerish($value, $message = '')` | Check that a value casts to an integer
91+
`positiveInteger($value, $message = '')` | Check that a value is a positive (non-zero) integer
92+
`negativeInteger($value, $message = '')` | Check that a value is a negative integer
93+
`notNegativeInteger($value, $message = '')` | Check that a value is a non-negative integer
94+
`float($value, $message = '')` | Check that a value is a float
95+
`numeric($value, $message = '')` | Check that a value is numeric
96+
`natural($value, $message = '')` | Check that a value is a non-negative integer
97+
`boolean($value, $message = '')` | Check that a value is a boolean
98+
`scalar($value, $message = '')` | Check that a value is a scalar
99+
`object($value, $message = '')` | Check that a value is an object
100+
`objectish($value, $message = '')` | Check that a value is an object or a string of a class that exists
101+
`resource($value, $type = null, $message = '')` | Check that a value is a resource
102+
`isInitialized($value, $property, $message = '')` | Check that a value has an initialized property
103+
`isCallable($value, $message = '')` | Check that a value is a callable
104+
`isArray($value, $message = '')` | Check that a value is an array
105+
`isIterable($value, $message = '')` | Check that a value is an array or a `\Traversable`
106+
`isCountable($value, $message = '')` | Check that a value is an array or a `\Countable`
107+
`isInstanceOf($value, $class, $message = '')` | Check that a value is an `instanceof` a class
108+
`isInstanceOfAny($value, array $classes, $message = '')` | Check that a value is an `instanceof` at least one class on the array of classes
109+
`notInstanceOf($value, $class, $message = '')` | Check that a value is not an `instanceof` a class
110+
`isNotInstanceOfAny($value, array $classes, $message = '')` | Check that a value is not an `instanceof` at least one class on the array of classes
111+
`isAOf($value, $class, $message = '')` | Check that a value is of the class or has one of its parents
112+
`isAnyOf($value, array $classes, $message = '')` | Check that a value is of at least one of the classes or has one of its parents
113+
`isNotA($value, $class, $message = '')` | Check that a value is not of the class or has not one of its parents
114+
`isArrayAccessible($value, $message = '')` | Check that a value can be accessed as an array
115+
`uniqueValues($values, $message = '')` | Check that the given array contains unique values
115116

116117
### Comparison Assertions
117118

src/Assert.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,36 @@ public static function isInstanceOfAny(mixed $value, mixed $classes, string $mes
552552
));
553553
}
554554

555+
/**
556+
* @template T
557+
*
558+
* @psalm-assert T $value
559+
*
560+
* @param T $value
561+
*
562+
* @return T
563+
*
564+
* @throws InvalidArgumentException
565+
*/
566+
public static function isNotInstanceOfAny(mixed $value, mixed $classes, string $message = ''): mixed
567+
{
568+
static::isIterable($classes);
569+
570+
foreach ($classes as $class) {
571+
static::string($class, 'Expected class as a string. Got: %s');
572+
573+
if ($value instanceof $class) {
574+
static::reportInvalidArgument(\sprintf(
575+
$message ?: 'Expected not an instance of %2$s. Got: %s',
576+
static::typeToString($value),
577+
\implode(', ', \array_map(static::valueToString(...), \iterator_to_array($classes)))
578+
));
579+
}
580+
}
581+
582+
return $value;
583+
}
584+
555585
/**
556586
* @psalm-pure
557587
*

src/Mixin.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,65 @@ public static function allNullOrIsInstanceOfAny(mixed $value, mixed $classes, st
13131313
return $value;
13141314
}
13151315

1316+
/**
1317+
* @template T
1318+
* @psalm-assert T|null $value
1319+
*
1320+
* @param T|null $value
1321+
*
1322+
* @return T|null
1323+
*
1324+
* @throws InvalidArgumentException
1325+
*/
1326+
public static function nullOrIsNotInstanceOfAny(mixed $value, mixed $classes, string $message = ''): mixed
1327+
{
1328+
null === $value || static::isNotInstanceOfAny($value, $classes, $message);
1329+
1330+
return $value;
1331+
}
1332+
1333+
/**
1334+
* @template T
1335+
* @psalm-assert iterable<T> $value
1336+
*
1337+
* @param iterable<T> $value
1338+
*
1339+
* @return iterable<T>
1340+
*
1341+
* @throws InvalidArgumentException
1342+
*/
1343+
public static function allIsNotInstanceOfAny(mixed $value, mixed $classes, string $message = ''): iterable
1344+
{
1345+
static::isIterable($value);
1346+
1347+
foreach ($value as $entry) {
1348+
static::isNotInstanceOfAny($entry, $classes, $message);
1349+
}
1350+
1351+
return $value;
1352+
}
1353+
1354+
/**
1355+
* @template T
1356+
* @psalm-assert iterable<T|null> $value
1357+
*
1358+
* @param iterable<T|null> $value
1359+
*
1360+
* @return iterable<T|null>
1361+
*
1362+
* @throws InvalidArgumentException
1363+
*/
1364+
public static function allNullOrIsNotInstanceOfAny(mixed $value, mixed $classes, string $message = ''): iterable
1365+
{
1366+
static::isIterable($value);
1367+
1368+
foreach ($value as $entry) {
1369+
null === $entry || static::isNotInstanceOfAny($entry, $classes, $message);
1370+
}
1371+
1372+
return $value;
1373+
}
1374+
13161375
/**
13171376
* @psalm-pure
13181377
*

tests/AssertTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ public static function getTests(): array
196196
['isInstanceOfAny', [new Exception(), ['ArrayAccess', 'Countable']], false],
197197
['isInstanceOfAny', [123, ['stdClass']], false],
198198
['isInstanceOfAny', [[], ['stdClass']], false],
199+
['isNotInstanceOfAny', [new ArrayIterator(), ['Exception', 'Countable']], false],
200+
['isNotInstanceOfAny', [new Exception(), ['ArrayAccess', 'Countable']], true],
201+
['isNotInstanceOfAny', [new Exception(), ['Exception', 'Countable']], false],
202+
['isNotInstanceOfAny', [123, ['stdClass']], true],
203+
['isNotInstanceOfAny', [[], ['stdClass']], true],
199204
['isAOf', ['stdClass', 'stdClass'], true],
200205
['isAOf', ['stdClass', 123], false],
201206
['isAOf', ['Iterator', 'ArrayIterator'], false],
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Webmozart\Assert\Tests\StaticAnalysis;
6+
7+
use Webmozart\Assert\Assert;
8+
9+
/**
10+
* @param mixed $value
11+
* @param array<class-string> $classes
12+
*/
13+
function isNotInstanceOfAny($value, array $classes): mixed
14+
{
15+
Assert::isNotInstanceOfAny($value, $classes);
16+
17+
return $value;
18+
}
19+
20+
/**
21+
* @param mixed $value
22+
* @param array<class-string> $classes
23+
*/
24+
function nullOrIsNotInstanceOfAny($value, array $classes): mixed
25+
{
26+
Assert::nullOrIsNotInstanceOfAny($value, $classes);
27+
28+
return $value;
29+
}
30+
31+
/**
32+
* @param mixed $value
33+
* @param array<class-string> $classes
34+
*/
35+
function allIsNotInstanceOfAny($value, array $classes): mixed
36+
{
37+
Assert::allIsNotInstanceOfAny($value, $classes);
38+
39+
return $value;
40+
}
41+
42+
/**
43+
* @param mixed $value
44+
* @param array<class-string> $classes
45+
*/
46+
function allNullOrIsNotInstanceOfAny($value, array $classes): mixed
47+
{
48+
Assert::allNullOrIsNotInstanceOfAny($value, $classes);
49+
50+
return $value;
51+
}

0 commit comments

Comments
 (0)