Skip to content

Commit

Permalink
Merge pull request #9164 from weirdan/do-not-allow-this-in-static-clo…
Browse files Browse the repository at this point in the history
…sures

Fixes #9148
Fixes #2813
  • Loading branch information
weirdan authored Jan 23, 2023
2 parents a5014c5 + bfce3a4 commit f0df119
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/Psalm/Internal/Analyzer/ClosureAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public static function analyzeExpression(

$codebase = $statements_analyzer->getCodebase();

if (!$statements_analyzer->isStatic()) {
if (!$statements_analyzer->isStatic() && !$closure_analyzer->isStatic()) {
if ($context->collect_mutations &&
$context->self &&
$codebase->classExtends(
Expand Down
4 changes: 3 additions & 1 deletion src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,9 @@ public function analyze(
$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;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Psalm/Internal/LanguageServer/Client/TextDocument.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public function xcontent(TextDocumentIdentifier $textDocument): Promise
/**
* @return Generator<int, Promise<object>, object, TextDocumentItem>
*/
static function () use ($textDocument) {
function () use ($textDocument) {
/** @var Promise<object> */
$promise = $this->handler->request(
'textDocument/xcontent',
Expand Down
4 changes: 2 additions & 2 deletions src/Psalm/Internal/LanguageServer/ClientHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public function request(string $method, $params): Promise
/**
* @return Generator<int, Promise, mixed, Promise<mixed>>
*/
static function () use ($id, $method, $params): Generator {
function () use ($id, $method, $params): Generator {
yield $this->protocolWriter->write(
new Message(
new Request($id, $method, (object) $params),
Expand All @@ -58,7 +58,7 @@ static function () use ($id, $method, $params): Generator {
$deferred = new Deferred();

$listener =
static function (Message $msg) use ($id, $deferred, &$listener): void {
function (Message $msg) use ($id, $deferred, &$listener): void {
error_log('request handler');
/**
* @psalm-suppress UndefinedPropertyFetch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1120,6 +1120,8 @@ private function createStorageForFunctionLike(

$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)) {
Expand Down
6 changes: 6 additions & 0 deletions src/Psalm/Storage/FunctionStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
28 changes: 28 additions & 0 deletions tests/ClosureTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1368,6 +1368,34 @@ public static function __callStatic(string $name, array $args): mixed {
'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',
],
];
}
}

0 comments on commit f0df119

Please sign in to comment.