struggle-for-php / sfp-psalm-typed-local-variable-plugin
finding mismatch type assignment in function/method scope with psalm
Installs: 10
Dependents: 0
Suggesters: 0
Security: 0
Stars: 13
Watchers: 1
Forks: 1
Open Issues: 0
Type:psalm-plugin
Requires
- php: ^7.4.3|^8
- ext-simplexml: *
- nikic/php-parser: 4.6.*
- vimeo/psalm: ^3.13
Requires (Dev)
- doctrine/coding-standard: ^8.1
- infection/infection: ^0.16.4
- phpunit/phpunit: ^9.2
- squizlabs/php_codesniffer: ^3.3
README
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