vimeo / psalm

A static analysis tool for finding errors in PHP applications
https://psalm.dev
MIT License
5.55k stars 662 forks source link

Code comment that asserts a variable satisfies a type (@psalm-satisfies) #10893

Open annervisser opened 6 months ago

annervisser commented 6 months ago

Feature request: @psalm-satisfies comment annotation

Problem

It can be useful for multiple reasons to annotate the type of a variable that psalm already knows the type of:

Currently this can only be done by using @var or @psalm-var comments. But these tags are unsafe: Psalm treats those as gospel, and assumes whatever you put in them to be true.

Solution

I propose a new tag that specifies the type of a variable, but that Psalm actually verifies is correct. This would allow expressing type expectations in code.

Example:

/**
 * @psalm-return ($asList is true ? list<string> : array<string, string>)
 */
function getItems(bool $asList): array
{
    $arr = ['a' => 'item', 'another' => 'item'];
    return $asList ? array_values($arr) : $arr;
}

$a = getItems(true);
/** @psalm-satisfies list<string> $a */
// From here on out anyone reading can safely assume that $a is list<string>
// And with a bit of luck PhpStorm could start interpreting psalm-satisfies the same as a @var tag
Problems

Alternatives

psalm-github-bot[bot] commented 6 months ago

I found these snippets:

https://psalm.dev/r/721c3dae1b ```php : array) */ function getItems(bool $asList): array { $arr = ['a' => 'item', 'another' => 'item']; return $asList ? array_values($arr) : $arr; } $a = getItems(true); /** @psalm-satisfies list $a */ // From here on out I know that $a is list // And with a bit of luck PhpStorm could start interpreting psalm-satisfies the same as a @var tag ``` ``` Psalm output (using commit ef3b018): ERROR: InvalidDocblock - 14:99 - Unrecognised annotation @psalm-satisfies INFO: UnusedVariable - 11:1 - $a is never referenced or the value is not used ```
danog commented 6 months ago

See https://github.com/vimeo/psalm/pull/10577 for the WIP implementation