2019-06-19 07:09:46 +02:00
|
|
|
|
# Assertion syntax
|
|
|
|
|
|
2019-06-19 20:21:07 +02:00
|
|
|
|
Psalm’s [assertion annotation](adding_assertions.md) supports a number of different assertions.
|
2019-06-19 07:09:46 +02:00
|
|
|
|
|
|
|
|
|
Psalm assertions are of the form
|
|
|
|
|
|
|
|
|
|
`@psalm-assert(-if-true|-if-false)? (Assertion) (Variable or Property)`
|
|
|
|
|
|
|
|
|
|
`Assertion` here can have many forms:
|
|
|
|
|
|
|
|
|
|
## Regular assertions
|
|
|
|
|
|
|
|
|
|
### is_xxx assertions
|
|
|
|
|
|
2019-06-19 07:21:29 +02:00
|
|
|
|
Most `is_xxx` PHP functions have companion assertions e.g. `int` for `is_int`. Here's the full list:
|
|
|
|
|
|
2019-06-19 07:09:46 +02:00
|
|
|
|
- `int`
|
|
|
|
|
- `float`
|
|
|
|
|
- `string`
|
|
|
|
|
- `bool`
|
|
|
|
|
- `scalar`
|
|
|
|
|
- `callable`
|
|
|
|
|
- `countable`
|
|
|
|
|
- `array`
|
|
|
|
|
- `iterable`
|
|
|
|
|
- `numeric`
|
|
|
|
|
- `resource`
|
|
|
|
|
- `object`
|
|
|
|
|
- `null`
|
|
|
|
|
|
|
|
|
|
So a custom version `is_int` could be annotated in Psalm as
|
|
|
|
|
|
|
|
|
|
```php
|
2020-03-21 14:24:41 +01:00
|
|
|
|
<?php
|
2019-06-19 07:09:46 +02:00
|
|
|
|
/** @psalm-assert-if-true int $x */
|
|
|
|
|
function custom_is_int($x) {
|
|
|
|
|
return is_int($x);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Object type assertions
|
|
|
|
|
|
|
|
|
|
Any class can be used as an assertion e.g.
|
|
|
|
|
|
|
|
|
|
`@psalm-assert SomeObjectType $foo`
|
|
|
|
|
|
|
|
|
|
### Generic assertions
|
|
|
|
|
|
|
|
|
|
Generic type parameters can also now be asserted e.g.
|
|
|
|
|
|
|
|
|
|
`@psalm-assert array<int, string> $foo`
|
|
|
|
|
|
|
|
|
|
## Negated assertions
|
|
|
|
|
|
|
|
|
|
Any assertion above can be negated:
|
|
|
|
|
|
|
|
|
|
This asserts that `$foo` is not an `int`:
|
|
|
|
|
|
|
|
|
|
```php
|
2020-03-21 14:24:41 +01:00
|
|
|
|
<?php
|
2019-06-19 07:09:46 +02:00
|
|
|
|
/** @psalm-assert !int $foo */
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This asserts that `$bar` is not an object of type `SomeObjectType`:
|
|
|
|
|
```php
|
2020-03-21 14:24:41 +01:00
|
|
|
|
<?php
|
2019-06-19 07:09:46 +02:00
|
|
|
|
/** @psalm-assert !SomeObjectType $bar */
|
|
|
|
|
```
|
|
|
|
|
|
2019-12-29 15:22:09 +01:00
|
|
|
|
## Bool assertions
|
|
|
|
|
|
|
|
|
|
This asserts that `$bar` is `true`:
|
|
|
|
|
```php
|
2020-03-21 14:24:41 +01:00
|
|
|
|
<?php
|
2019-12-29 15:22:09 +01:00
|
|
|
|
/** @psalm-assert true $bar */
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This asserts that `$bar` is not `false`:
|
|
|
|
|
```php
|
2020-03-21 14:24:41 +01:00
|
|
|
|
<?php
|
2019-12-29 15:22:09 +01:00
|
|
|
|
/** @psalm-assert !false $bar */
|
|
|
|
|
```
|
|
|
|
|
|
2019-06-19 07:09:46 +02:00
|
|
|
|
## Equality assertions
|
|
|
|
|
|
|
|
|
|
Psalm also supports the equivalent of `assert($some_int === $other_int)` in the form
|
|
|
|
|
```php
|
2020-03-21 14:24:41 +01:00
|
|
|
|
<?php
|
2019-06-19 07:09:46 +02:00
|
|
|
|
/** @psalm-assert =int $some_int */
|
|
|
|
|
```
|
|
|
|
|
|
2019-06-19 07:23:49 +02:00
|
|
|
|
There are two differences between the above assertion and
|
|
|
|
|
|
|
|
|
|
```php
|
2020-03-21 14:24:41 +01:00
|
|
|
|
<?php
|
2019-06-19 07:23:49 +02:00
|
|
|
|
/** @psalm-assert int $some_int */
|
|
|
|
|
```
|
2019-06-19 07:09:46 +02:00
|
|
|
|
|
2019-06-19 07:24:14 +02:00
|
|
|
|
Firstly, the negation of `=int` has no meaning:
|
2019-06-19 07:09:46 +02:00
|
|
|
|
|
|
|
|
|
```php
|
2020-03-21 14:24:41 +01:00
|
|
|
|
<?php
|
2019-06-19 07:09:46 +02:00
|
|
|
|
/** @psalm-assert-if-true =int $x */
|
|
|
|
|
function equalsFive($x) {
|
|
|
|
|
return is_int($x) && $x === 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function foo($y) : void {
|
|
|
|
|
if (equalsFive($y)) {
|
|
|
|
|
// $y is definitely an int
|
|
|
|
|
} else {
|
|
|
|
|
// $y might be an int, but it might not
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function bar($y) : void {
|
|
|
|
|
if (is_int($y)) {
|
|
|
|
|
// $y is definitely an int
|
|
|
|
|
} else {
|
|
|
|
|
// $y is definitely not an int
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Secondly, calling `equalsFive($some_int)` is not a `RedundantCondition` in Psalm, whereas calling `is_int($some_int)` is.
|
|
|
|
|
|
|
|
|
|
|