2018-01-30 06:14:36 +01:00
# Supported docblock annotations
Psalm supports a wide range of docblock annotations.
## PHPDoc tags
Psalm uses the following PHPDoc tags to understand your code:
2020-02-23 06:41:19 +01:00
2020-11-29 03:03:09 +01:00
- [`@var` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/var.html )
2020-11-28 03:48:16 +01:00
Used for specifying the types of properties and variables@
2020-11-29 03:03:09 +01:00
- [`@return` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/return.html )
2018-01-30 17:31:17 +01:00
Used for specifying the return types of functions, methods and closures
2020-11-29 03:03:09 +01:00
- [`@param` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/param.html )
2018-01-30 17:31:17 +01:00
Used for specifying types of parameters passed to functions, methods and closures
2020-11-29 03:03:09 +01:00
- [`@property` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/property.html )
2018-01-30 17:31:17 +01:00
Used to specify what properties can be accessed on an object that uses `__get` and `__set`
2020-11-29 03:03:09 +01:00
- [`@property-read` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/property-read.html )
2018-01-30 17:31:17 +01:00
Used to specify what properties can be read on object that uses `__get`
2020-11-29 03:03:09 +01:00
- [`@property-write` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/property-write.html )
2018-01-30 17:31:17 +01:00
Used to specify what properties can be written on object that uses `__set`
2020-11-29 03:03:09 +01:00
- [`@method` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/method.html )
2020-06-17 04:20:34 +02:00
Used to specify which magic methods are available on object that uses `__call` .
2020-11-29 03:03:09 +01:00
- [`@deprecated` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/deprecated.html )
2018-01-30 17:31:17 +01:00
Used to mark functions, methods, classes and interfaces as being deprecated
2020-11-29 03:03:09 +01:00
- [`@internal` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/internal.html )
2019-05-11 18:15:45 +02:00
used to mark classes, functions and properties that are internal to an application or library.
2018-01-30 06:14:36 +01:00
### Off-label usage of the `@var` tag
The `@var` tag is supposed to only be used for properties. Psalm, taking a lead from PHPStorm and other static analysis tools, allows its use inline in the form `@var Type [VariableReference]` .
If `VariableReference` is provided, it should be of the form `$variable` or `$variable->property` . If used above an assignment, Psalm checks whether the `VariableReference` matches the variable being assigned. If they differ, Psalm will assign the `Type` to `VariableReference` and use it in the expression below.
2022-04-27 07:46:13 +02:00
If no `VariableReference` is given, the annotation tells Psalm that the right-hand side of the expression, whether an assignment or a return, is of type `Type` .
2018-01-30 06:14:36 +01:00
```php
2020-03-21 14:24:41 +01:00
< ?php
2018-01-30 06:14:36 +01:00
/** @var string */
$a = $_GET['foo'];
/** @var string $b */
$b = $_GET['bar'];
function bat(): string {
/** @var string */
return $_GET['bat'];
}
```
## Psalm-specific tags
There are a number of custom tags that determine how Psalm treats your code.
2021-04-10 19:16:14 +02:00
### `@psalm-consistent-constructor`
See [UnsafeInstantiation ](../running_psalm/issues/UnsafeInstantiation.md )
### `@psalm-consistent-templates`
See [UnsafeGenericInstantiation ](../running_psalm/issues/UnsafeGenericInstantiation.md )
2020-11-27 23:05:26 +01:00
### `@param-out`, `@psalm-param-out`
2019-01-20 18:50:47 +01:00
This is used to specify that a by-ref type is different from the one that entered. In the function below the first param can be null, but once the function has executed the by-ref value is not null.
```php
2020-03-21 14:24:41 +01:00
< ?php
2019-01-20 18:50:47 +01:00
/**
* @param -out string $s
*/
function addFoo(?string & $s) : void {
if ($s === null) {
$s = "hello";
}
$s .= "foo";
}
```
2020-11-28 03:48:16 +01:00
### `@psalm-var`, `@psalm-param`, `@psalm-return`, `@psalm-property`, `@psalm-property-read`, `@psalm-property-write`, `@psalm-method`
2018-01-30 06:14:36 +01:00
2019-02-12 23:27:31 +01:00
When specifying types in a format not supported by phpDocumentor ([but supported by Psalm](#type-syntax)) you may wish to prepend `@psalm-` to the PHPDoc tag, so as to avoid confusing your IDE. If a `@psalm` -prefixed tag is given, Psalm will use it in place of its non-prefixed counterpart.
2018-01-30 06:14:36 +01:00
2021-03-27 02:20:23 +01:00
### `@psalm-ignore-var`
This annotation is used to ignore the `@var` annotation written in the same docblock. Some IDEs don't fully understand complex types like generics. To take advantage of such IDE's auto-completion, you may sometimes want to use explicit `@var` annotations even when psalm can infer the type just fine. This weakens the effectiveness of type checking in many cases since the explicit `@var` annotation overrides the types inferred by psalm. As psalm ignores the `@var` annotation which is co-located with `@psalm-ignore-var` , IDEs can use the type specified by the `@var` for auto-completion, while psalm can still use its own inferred type for type checking.
```php
< ?php
/** @return iterable< array-key , \DateTime > $f */
function getTimes(int $n): iterable {
while ($n--) {
yield new \DateTime();
}
};
/**
* @var \Datetime[] $times
* @psalm -ignore-var
*/
$times = getTimes(3);
// this trace shows "iterable< array-key , DateTime > " instead of "array< array-key , Datetime > "
/** @psalm -trace $times */
foreach ($times as $time) {
echo $time->format('Y-m-d H:i:s.u') . PHP_EOL;
}
```
2018-01-30 06:14:36 +01:00
### `@psalm-suppress SomeIssueName`
This annotation is used to suppress issues. It can be used in function docblocks, class docblocks and also inline, applying to the following statement.
Function docblock example:
```php
2020-03-21 14:24:41 +01:00
< ?php
2018-01-30 06:14:36 +01:00
/**
* @psalm -suppress PossiblyNullOperand
*/
function addString(?string $s) {
echo "hello " . $s;
}
```
Inline example:
```php
2020-03-21 14:24:41 +01:00
< ?php
2018-01-30 06:14:36 +01:00
function addString(?string $s) {
/** @psalm -suppress PossiblyNullOperand */
echo "hello " . $s;
}
```
2020-01-12 16:38:32 +01:00
`@psalm-suppress all` can be used to suppress all issues instead of listing them individually.
2021-10-28 10:44:37 +02:00
### `@psalm-assert`, `@psalm-assert-if-true`, `@psalm-assert-if-false`, `@psalm-if-this-is` and `@psalm-this-out`
2018-06-04 05:38:06 +02:00
2019-06-19 20:19:40 +02:00
See [Adding assertions ](adding_assertions.md ).
2019-06-19 07:09:46 +02:00
2018-01-30 06:14:36 +01:00
### `@psalm-ignore-nullable-return`
This can be used to tell Psalm not to worry if a function/method returns null. It’ s a bit of a hack, but occasionally useful for scenarios where you either have a very high confidence of a non-null value, or some other function guarantees a non-null value for that particular code path.
```php
2020-03-21 14:24:41 +01:00
< ?php
2018-01-30 06:14:36 +01:00
class Foo {}
function takesFoo(Foo $f): void {}
/** @psalm -ignore-nullable-return */
function getFoo(): ?Foo {
return rand(0, 10000) > 1 ? new Foo() : null;
}
takesFoo(getFoo());
```
### `@psalm-ignore-falsable-return`
This provides the same, but for `false` . Psalm uses this internally for functions like `preg_replace` , which can return false if the given input has encoding errors, but where 99.9% of the time the function operates as expected.
2019-01-30 05:26:37 +01:00
### `@psalm-seal-properties`
2018-01-30 06:14:36 +01:00
2019-01-30 05:26:37 +01:00
If you have a magic property getter/setter, you can use `@psalm-seal-properties` to instruct Psalm to disallow getting and setting any properties not contained in a list of `@property` (or `@property-read` /`@property-write`) annotations.
2018-01-30 06:14:36 +01:00
```php
2020-03-21 14:24:41 +01:00
< ?php
2018-01-30 06:14:36 +01:00
/**
2019-01-30 05:26:37 +01:00
* @property string $foo
* @psalm -seal-properties
*/
class A {
public function __get(string $name): ?string {
if ($name === "foo") {
return "hello";
}
}
public function __set(string $name, $value): void {}
}
$a = new A();
$a->bar = 5; // this call fails
```
2019-05-11 18:15:45 +02:00
### `@psalm-internal`
Used to mark a class, property or function as internal to a given namespace. Psalm treats this slightly differently to
2019-06-28 19:59:09 +02:00
the PHPDoc `@internal` tag. For `@internal` , an issue is raised if the calling code is in a namespace completely
2019-05-11 18:15:45 +02:00
unrelated to the namespace of the calling code, i.e. not sharing the first element of the namespace.
2022-04-27 07:46:13 +02:00
In contrast for `@psalm-internal` , the docblock line must specify a namespace. An issue is raised if the calling code
2019-05-11 18:15:45 +02:00
is not within the given namespace.
2019-09-08 21:21:30 +02:00
```php
2020-03-21 14:24:41 +01:00
< ?php
2019-05-11 18:15:45 +02:00
namespace A\B {
/**
2019-05-15 00:27:27 +02:00
* @internal
2019-05-11 18:15:45 +02:00
* @psalm -internal A\B
*/
class Foo { }
}
namespace A\B\C {
class Bat {
public function batBat(): void {
$a = new \A\B\Foo(); // this is fine
}
}
}
namespace A\C {
class Bat {
public function batBat(): void {
$a = new \A\B\Foo(); // error
}
}
}
```
2019-09-08 21:21:30 +02:00
### `@psalm-readonly` and `@readonly`
Used to annotate a property that can only be written to in its defining class's constructor.
```php
< ?php
class B {
/** @readonly */
public string $s;
2019-09-09 16:38:55 +02:00
2019-09-08 21:21:30 +02:00
public function __construct(string $s) {
$this->s = $s;
}
}
$b = new B("hello");
echo $b->s;
$b->s = "boo"; // disallowed
```
### `@psalm-mutation-free`
Used to annotate a class method that does not mutate state, either internally or externally of the class's scope.
2021-12-30 23:23:59 +01:00
This requires that the return value depend only on the instance's properties. For example, `random_int` is considered
mutating here because it mutates the random number generator's internal state.
2019-09-08 21:21:30 +02:00
```php
2020-03-21 14:24:41 +01:00
< ?php
2019-09-08 21:21:30 +02:00
class D {
private string $s;
2019-09-09 16:38:55 +02:00
2019-09-08 21:21:30 +02:00
public function __construct(string $s) {
$this->s = $s;
}
2019-09-09 16:38:55 +02:00
2019-09-08 21:21:30 +02:00
/**
* @psalm -mutation-free
*/
public function getShort() : string {
return substr($this->s, 0, 5);
}
2019-09-09 16:38:55 +02:00
2019-09-08 21:21:30 +02:00
/**
* @psalm -mutation-free
*/
public function getShortMutating() : string {
$this->s .= "hello"; // this is a bug
return substr($this->s, 0, 5);
}
}
```
### `@psalm-external-mutation-free`
2019-09-09 20:52:30 +02:00
Used to annotate a class method that does not mutate state externally of the class's scope.
2019-09-08 21:21:30 +02:00
```php
2020-03-21 14:24:41 +01:00
< ?php
2019-09-08 21:21:30 +02:00
class E {
private string $s;
2019-09-09 16:38:55 +02:00
2019-09-08 21:21:30 +02:00
public function __construct(string $s) {
$this->s = $s;
}
2019-09-09 16:38:55 +02:00
2019-09-08 21:21:30 +02:00
/**
* @psalm -external-mutation-free
*/
public function getShortMutating() : string {
$this->s .= "hello"; // this is fine
return substr($this->s, 0, 5);
}
/**
* @psalm -external-mutation-free
*/
public function save() : void {
file_put_contents("foo.txt", $this->s); // this is a bug
}
}
```
### `@psalm-immutable`
2019-09-09 16:38:55 +02:00
Used to annotate a class where every property is treated by consumers as `@psalm-readonly` and every instance method is treated as `@psalm-mutation-free` .
2019-09-08 21:21:30 +02:00
2020-01-02 20:09:11 +01:00
```php
2020-03-21 14:24:41 +01:00
< ?php
2020-01-02 20:09:11 +01:00
/**
* @psalm -immutable
*/
abstract class Foo
{
public string $baz;
2021-12-30 23:23:59 +01:00
2020-01-02 20:09:11 +01:00
abstract public function bar(): int;
}
/**
* @psalm -immutable
*/
final class ChildClass extends Foo
{
public function __construct(string $baz)
{
$this->baz = $baz;
}
2021-12-30 23:23:59 +01:00
2020-01-02 20:09:11 +01:00
public function bar(): int
{
return 0;
}
}
$anonymous = new /** @psalm -immutable */ class extends Foo
{
public string $baz = "B";
2021-12-30 23:23:59 +01:00
2020-01-02 20:09:11 +01:00
public function bar(): int
{
return 1;
}
};
```
2019-09-08 21:25:12 +02:00
### `@psalm-pure`
Used to annotate a [pure function ](https://en.wikipedia.org/wiki/Pure_function ) - one whose output is just a function of its input.
```php
2020-03-21 14:24:41 +01:00
< ?php
2019-09-08 21:25:12 +02:00
class Arithmetic {
/** @psalm -pure */
public static function add(int $left, int $right) : int {
return $left + $right;
}
/** @psalm -pure - this is wrong */
public static function addCumulative(int $left) : int {
/** @var int */
static $i = 0; // this is a side effect, and thus a bug
$i += $left;
return $i;
}
}
echo Arithmetic::add(40, 2);
echo Arithmetic::add(40, 2); // same value is emitted
echo Arithmetic::addCumulative(3); // outputs 3
echo Arithmetic::addCumulative(3); // outputs 6
```
2020-10-15 01:59:44 +02:00
On the other hand, `pure-callable` can be used to denote a callable which needs to be pure.
```php
/**
* @param pure-callable(mixed): int $callback
*/
function foo(callable $callback) {...}
// this fails since random_int is not pure
foo(
/** @param mixed $p */
fn($p) => random_int(1, 2)
);
```
2020-02-02 21:38:41 +01:00
### `@psalm-allow-private-mutation`
2020-02-02 13:46:39 +01:00
2020-02-02 21:38:41 +01:00
Used to annotate readonly properties that can be mutated in a private context. With this, public properties can be read from another class but only be mutated within a method of its own class.
2020-02-02 13:46:39 +01:00
```php
2020-03-21 14:24:41 +01:00
< ?php
2020-02-02 13:46:39 +01:00
class Counter {
2020-02-02 21:38:41 +01:00
/**
* @readonly
* @psalm -allow-private-mutation
2021-12-30 23:23:59 +01:00
*/
2020-02-02 13:46:39 +01:00
public int $count = 0;
2021-12-30 23:23:59 +01:00
2020-02-02 13:46:39 +01:00
public function increment() : void {
$this->count++;
}
}
$counter = new Counter();
echo $counter->count; // outputs 0
2020-02-02 21:03:17 +01:00
$counter->increment(); // Method can mutate property
2020-02-02 13:46:39 +01:00
echo $counter->count; // outputs 1
2020-02-02 21:38:41 +01:00
$counter->count = 5; // This will fail, as it's mutating a property directly
2020-02-02 13:46:39 +01:00
```
2020-02-02 21:56:08 +01:00
### `@psalm-readonly-allow-private-mutation`
This is a shorthand for the property annotations `@readonly` and `@psalm-allow-private-mutation` .
```php
2020-03-21 14:24:41 +01:00
< ?php
2020-02-02 21:56:08 +01:00
class Counter {
/**
* @psalm -readonly-allow-private-mutation
2021-12-30 23:23:59 +01:00
*/
2020-02-02 21:56:08 +01:00
public int $count = 0;
2021-12-30 23:23:59 +01:00
2020-02-02 21:56:08 +01:00
public function increment() : void {
$this->count++;
}
}
$counter = new Counter();
echo $counter->count; // outputs 0
$counter->increment(); // Method can mutate property
echo $counter->count; // outputs 1
$counter->count = 5; // This will fail, as it's mutating a property directly
```
2020-04-06 18:42:22 +02:00
### `@psalm-trace`
You can use this annotation to trace inferred type (applied to the *next* statement).
```php
< ?php
2021-12-30 23:23:59 +01:00
/** @psalm -trace $username */
2020-04-06 18:42:22 +02:00
$username = $_GET['username']; // prints something like "test.php:4 $username: mixed"
```
2020-04-09 03:03:05 +02:00
*Note*: it throws [special low-level issue ](../running_psalm/issues/Trace.md ), so you have to set errorLevel to 1, override it in config or invoke Psalm with `--show-info=true` .
2022-02-17 17:26:28 +01:00
### `@psalm-check-type`
You can use this annotation to ensure the inferred type matches what you expect.
```php
< ?php
/** @psalm -check-type $foo = int */
$foo = 1; // No issue
/** @psalm -check-type $bar = int */
$bar = "not-an-int"; // Checked variable $bar = int does not match $bar = 'not-an-int'
```
### `@psalm-check-type-exact`
Like `@psalm-check-type` , but checks the exact type of the variable without allowing subtypes.
```php
< ?php
/** @psalm -check-type-exact $foo = int */
$foo = 1; // Checked variable $foo = int does not match $foo = 1
```
2020-06-17 02:55:39 +02:00
### `@psalm-taint-*`
See [Security Analysis annotations ](../security_analysis/annotations.md ).
2020-10-07 00:58:25 +02:00
### `@psalm-type`
This allows you to define an alias for another type.
```php
< ?php
/**
2022-11-12 02:43:19 +01:00
* @psalm -type PhoneType = array{phone: string}
2020-10-07 00:58:25 +02:00
*/
class Phone {
/**
* @psalm -return PhoneType
*/
public function toArray(): array {
return ["phone" => "Nokia"];
}
}
```
### `@psalm-import-type`
You can use this annotation to import a type defined with [`@psalm-type` ](#psalm-type ) if it was defined somewhere else.
```php
< ?php
/**
* @psalm -import-type PhoneType from Phone
*/
class User {
/**
* @psalm -return PhoneType
*/
public function toArray(): array {
return array_merge([], (new Phone())->toArray());
}
}
```
You can also alias a type when you import it:
```php
< ?php
/**
* @psalm -import-type PhoneType from Phone as MyPhoneTypeAlias
*/
class User {
/**
* @psalm -return MyPhoneTypeAlias
*/
public function toArray(): array {
return array_merge([], (new Phone())->toArray());
}
}
```
2020-11-28 03:48:16 +01:00
### `@psalm-require-extends`
2022-08-20 23:29:03 +02:00
The `@psalm-require-extends` annotation allows you to define the requirements that a trait imposes on the using class.
2020-11-28 03:48:16 +01:00
```php
2021-04-13 05:50:52 +02:00
< ?php
2020-11-28 03:48:16 +01:00
abstract class DatabaseModel {
// methods, properties, etc.
}
/**
* @psalm -require-extends DatabaseModel
*/
trait SoftDeletingTrait {
// useful but scoped functionality, that depends on methods/properties from DatabaseModel
}
class MyModel extends DatabaseModel {
// valid
use SoftDeletingTrait;
}
class NormalClass {
// triggers an error
use SoftDeletingTrait;
}
```
### `@psalm-require-implements`
Behaves the same way as `@psalm-require-extends` , but for interfaces.
2021-04-21 07:02:25 +02:00
### `@no-named-arguments`
This will prevent access to the function or method tagged with named parameters (by emitting a `NamedArgumentNotAllowed` issue).
Incidentally, it will change the inferred type for the following code:
```php
< ?php
function a(int ...$a){
var_dump($a);
}
```
2022-04-27 07:46:13 +02:00
The type of `$a` is `array<array-key, int>` without `@no-named-arguments` but becomes `list<int>` with it, because it excludes the case where the offset would be a string with the name of the parameter
### `@psalm-ignore-variable-property` and `@psalm-ignore-variable-method`
Instructs Psalm to ignore variable property fetch / variable method call when looking for dead code.
```php
class Foo
{
// this property can be deleted by Psalter,
// as potential reference in get() is ignored
public string $bar = 'bar';
public function get(string $name): mixed
{
/** @psalm -ignore-variable-property */
return $this->{$name};
}
}
```
When Psalm encounters variable property, it treats all properties in given class as potentially referenced.
With `@psalm-ignore-variable-property` annotation, this reference is ignored.
While `PossiblyUnusedProperty` would be emitted in both cases, using `@psalm-ignore-variable-property`
would allow [Psalter ](../manipulating_code/fixing.md ) to delete `Foo::$bar` .
`@psalm-ignore-variable-method` behaves the same way, but for variable method calls.
### `@psalm-yield`
Used to specify the type of value which will be sent back to a generator when an annotated object instance is yielded.
```php
< ?php
/**
* @template -covariant TValue
* @psalm -yield TValue
*/
interface Promise {}
/**
* @template -covariant TValue
* @template -implements Promise< TValue >
*/
class Success implements Promise {
/**
* @psalm -param TValue $value
*/
public function __construct($value) {}
}
/**
* @return Promise< string >
*/
function fetch(): Promise {
2022-12-22 15:43:55 +01:00
return new Success('{"data":[]}');
2022-04-27 07:46:13 +02:00
}
function (): Generator {
$data = yield fetch();
// this is fine, Psalm knows that $data is a string
return json_decode($data);
};
```
This annotation supports only generic types, meaning that e.g. `@psalm-yield string` would be ignored.
2021-04-21 07:02:25 +02:00
2022-12-22 15:43:55 +01:00
### `@psalm-api`
Used to tell Psalm that a class is used, even if no references to it can be
found. Unused issues will be suppressed.
For example, in frameworks, controllers are often invoked "magically" without
any explicit references to them in your code. You should mark these classes with
`@psalm-api` .
```php
/**
* @psalm -api
*/
class UnreferencedClass {}
```
2018-01-30 06:14:36 +01:00
## Type Syntax
2020-11-29 03:03:09 +01:00
Psalm supports PHPDoc’ s [type syntax ](https://docs.phpdoc.org/latest/guide/guides/types.html ), and also the [proposed PHPDoc PSR type syntax ](https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc.md#appendix-a-types ).
2018-01-30 06:14:36 +01:00
2019-01-02 19:56:43 +01:00
A detailed write-up is found in [Typing in Psalm ](typing_in_psalm.md )