6.3 KiB
Supported docblock annotations
Psalm supports a wide range of docblock annotations.
Table of contents
- PHPDoc tags
- Psalm-specific tags
- [@psalm-var, @psalm-param and @psalm-return][#psalm-var-psalm-param-and-psalm-return]
- @psalm-suppress
- @psalm-ignore-nullable-return
- @psalm-ignore-falsable-return
- @template
- @psalm-seal-properties
- Type Syntax
PHPDoc tags
Psalm uses the following PHPDoc tags to understand your code:
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.
If no VariableReference
is given, the annotation tells Psalm that the RHS of the expression, whether an assignment or a return, is of type Type
.
/** @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.
@psalm-var
, @psalm-param
and @psalm-return
When specifying types in a format not supported phpDocumentor (but supported by Psalm) 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.
@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:
/**
* @psalm-suppress PossiblyNullOperand
*/
function addString(?string $s) {
echo "hello " . $s;
}
Inline example:
function addString(?string $s) {
/** @psalm-suppress PossiblyNullOperand */
echo "hello " . $s;
}
For example, we can suppress the possible
@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.
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.
@template
and @template-typeof
Phan first introduced the template annotation to allow classes to implement generic-like features.
Psalm extends this with @template-typeof
to allow you to type methods that instantiate objects e.g.
/**
* @template T
* @template-typeof T $class_name
* @return T
*/
function instantiator(string $class_name) {
return new $class_name();
}
Psalm also uses @template
annotations in its stubbed versions of PHP array functions e.g.
/**
* Takes one array with keys and another with values and combines them
*
* @template TKey
* @template TValue
*
* @param array<mixed, TKey> $arr
* @param array<mixed, TValue> $arr2
* @return array<TKey, TValue>
*/
function array_combine(array $arr, array $arr2) {}
@psalm-seal-properties
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(-read|-write)
annotations.
/**
* @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;
Type Syntax
Psalm supports PHPDoc’s type syntax, and also the proposed PHPDoc PSR type syntax.
Beyond that, in order to support a very common style of PHP code, Psalm supports a special format for arrays where the key offsets are known: object-like arrays.
Object-like Arrays
Given an array
["hello", "world", "foo" => new stdClass, 28 => false];
Psalm will type it internally as:
array{0: string, 1: string, foo: stdClass, 28: false}
If you want to be explicit about this, you can use this same format in @var
, @param
and @return
types (or @psalm-var
, @psalm-param
and @psalm-return
if you prefer to keep this special format separate).
function takesInt(int $i): void {}
function takesString(string $s): void {}
/**
* @param (string|int)[] $arr
* @psalm-param array{0: string, 1: int} $arr
*/
function foo(array $arr): void {
takesString($arr[0]);
takesInt($arr[1]);
}
foo(["cool", 4]); // passes
foo([4, "cool"]); // fails