sfp-psalm-typed-local-variable-plugin
finding mismatch type assignment in function/method scope with psalm.
Disclaimer
This is VERY VERY Experimental .
Limitation
- NOT support global variables.
- NOT support variables in namespace.
- NOT support Variable variables
- Non-each inline VariableReference.
- eg.
/** @var string $var1 */
/** @var bool $var2 */
$var1 = 'string'; // cannot determine type for $var1
// should fix like below
/** @var string $var1 */
$var1 = 'string';
/** @var bool $var2 */
$var2 = true;
Installation
$ composer require --dev struggle-for-php/sfp-psalm-typed-local-variable-plugin
$ vendor/bin/psalm-plugin enable struggle-for-php/sfp-psalm-typed-local-variable-plugin
Todo
- optional setting for only from_docblock typed.
- support Variable variables.
Demo
<?php
namespace X {
interface Mock{}
/** @return \DateTimeInterface&Mock */
function date_mock() {
return new class('now') extends \DateTime implements Mock{};
};
class Klass {
public function method() : void {
/** @var string|null $nullable_string */
$nullable_string = null;
$nullable_string = "a";
$nullable_string = true; // error
$bool = true; //direct typed without doc-block
$bool = 1; //error
/** @var \DateTimeInterface&Mock $intersection_type */
$intersection_type = new \DateTime('now'); // error
$intersection_type = date_mock();
(static function(): void {
/** @var \DateTimeImmutable $date */
$date = new \DateTimeImmutable('now');
if (rand() % 2 === 0) {
$date = new \DateTime('tomorrow'); // error
}
})();
}
}
}
$ ./vendor/bin/psalm -c demo.psalm.xml
Scanning files...
Analyzing files...
E
ERROR: InvalidScalarTypedLocalVariableIssue - demo/demo.php:16:32 - Type true should be a subtype of null|string (see https://psalm.dev/000)
$nullable_string = true; // error
ERROR: InvalidScalarTypedLocalVariableIssue - demo/demo.php:19:21 - Type int(1) should be a subtype of true (see https://psalm.dev/000)
$bool = 1; //error
ERROR: InvalidTypedLocalVariableIssue - demo/demo.php:22:34 - Type DateTime should be a subtype of DateTimeInterface&X\Mock (see https://psalm.dev/000)
$intersection_type = new \DateTime('now'); // error
ERROR: InvalidTypedLocalVariableIssue - demo/demo.php:30:29 - Type DateTime should be a subtype of DateTimeImmutable (see https://psalm.dev/000)
$date = new \DateTime('tomorrow'); // error
------------------------------
4 errors found
------------------------------
Checks took 17.10 seconds and used 194.889MB of memory
Psalm was able to infer types for 100% of the codebase