1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00

Check $this in static closures

Fixes vimeo/psalm#9148
Fixes vimeo/psalm#2813
This commit is contained in:
Bruce Weirdan 2023-01-23 05:16:12 -04:00
parent b63061a27f
commit 70f2fb7d1b
No known key found for this signature in database
GPG Key ID: CFC3AAB181751B0D
5 changed files with 40 additions and 2 deletions

View File

@ -84,7 +84,7 @@ class ClosureAnalyzer extends FunctionLikeAnalyzer
$codebase = $statements_analyzer->getCodebase();
if (!$statements_analyzer->isStatic()) {
if (!$statements_analyzer->isStatic() && !$closure_analyzer->isStatic()) {
if ($context->collect_mutations &&
$context->self &&
$codebase->classExtends(

View File

@ -217,7 +217,9 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer
$this->suppressed_issues += $appearing_class_storage->suppressed_issues;
}
if ($storage instanceof MethodStorage && $storage->is_static) {
if (($storage instanceof MethodStorage || $storage instanceof FunctionStorage)
&& $storage->is_static
) {
$this->is_static = true;
}

View File

@ -1120,6 +1120,8 @@ class FunctionLikeNodeScanner
$storage = $this->storage = $this->file_storage->functions[$function_id] = new FunctionStorage();
$storage->is_static = $stmt->static;
if ($stmt instanceof PhpParser\Node\Expr\Closure) {
foreach ($stmt->uses as $closure_use) {
if ($closure_use->byRef && is_string($closure_use->var->name)) {

View File

@ -6,4 +6,10 @@ final class FunctionStorage extends FunctionLikeStorage
{
/** @var array<string, bool> */
public $byref_uses = [];
/**
* @var bool
* @todo lift this property to FunctionLikeStorage in Psalm 6
*/
public $is_static = false;
}

View File

@ -1368,6 +1368,34 @@ class ClosureTest extends TestCase
'ignored_issues' => [],
'php_version' => '8.1',
],
'thisInStaticClosure' => [
'code' => '<?php
class C {
public string $a = "zzz";
public function f(): void {
$f = static function (): void {
echo $this->a;
};
$f();
}
}
',
'error_message' => 'InvalidScope',
],
'thisInStaticArrowFunction' => [
'code' => '<?php
class C {
public int $a = 1;
public function f(): int {
$f = static fn(): int => $this->a;
return $f();;
}
}
',
'error_message' => 'InvalidScope',
'ignored_issues' => [],
'php_version' => '7.4',
],
];
}
}