From 74d3e26652296938682b6334b5830a0d2a1fbc85 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Fri, 5 Jun 2026 20:48:55 +0700 Subject: [PATCH 1/5] [Php70] Fix rewriting to $this on static method or static closure --- ...skip_static_closure_same_class_call.php.inc | 18 ++++++++++++++++++ .../skip_static_method_same_class_call.php.inc | 17 +++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 rules-tests/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector/Fixture/skip_static_closure_same_class_call.php.inc create mode 100644 rules-tests/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector/Fixture/skip_static_method_same_class_call.php.inc diff --git a/rules-tests/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector/Fixture/skip_static_closure_same_class_call.php.inc b/rules-tests/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector/Fixture/skip_static_closure_same_class_call.php.inc new file mode 100644 index 00000000000..060ad4432a2 --- /dev/null +++ b/rules-tests/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector/Fixture/skip_static_closure_same_class_call.php.inc @@ -0,0 +1,18 @@ + Date: Fri, 5 Jun 2026 21:01:55 +0700 Subject: [PATCH 2/5] fix --- .../StaticCall/StaticCallOnNonStaticToInstanceCallRector.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rules/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector.php b/rules/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector.php index 23d3004f249..18cf8c1b0f4 100644 --- a/rules/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector.php +++ b/rules/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector.php @@ -126,6 +126,10 @@ public function refactor(Node $node): ?Node $classReflection = $scope->getClassReflection(); if ($classReflection instanceof ClassReflection && $classReflection->getName() === $className) { + if ($scope->getFunction()->isStatic()) { + return null; + } + return new MethodCall(new Variable('this'), $node->name, $node->args); } From 2d91cb7a8480cb75ce5584a54e2bde0ebd4fadb7 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Fri, 5 Jun 2026 21:04:13 +0700 Subject: [PATCH 3/5] Fix --- .../StaticCall/StaticCallOnNonStaticToInstanceCallRector.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rules/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector.php b/rules/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector.php index 18cf8c1b0f4..79c0faee1fc 100644 --- a/rules/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector.php +++ b/rules/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector.php @@ -14,6 +14,7 @@ use PHPStan\Analyser\Scope; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\MethodReflection; +use PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\ObjectType; use Rector\CodingStyle\ValueObject\ObjectMagicMethods; @@ -126,7 +127,8 @@ public function refactor(Node $node): ?Node $classReflection = $scope->getClassReflection(); if ($classReflection instanceof ClassReflection && $classReflection->getName() === $className) { - if ($scope->getFunction()->isStatic()) { + $function = $scope->getFunction(); + if ($function instanceof PhpFunctionFromParserNodeReflection && $function->isStatic()) { return null; } From eb938debed41e921b31ad9fc71a0c7c200b88d0f Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Fri, 5 Jun 2026 21:18:01 +0700 Subject: [PATCH 4/5] update static closure prove --- .../Fixture/skip_static_closure_same_class_call.php.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules-tests/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector/Fixture/skip_static_closure_same_class_call.php.inc b/rules-tests/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector/Fixture/skip_static_closure_same_class_call.php.inc index 060ad4432a2..62286271fdf 100644 --- a/rules-tests/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector/Fixture/skip_static_closure_same_class_call.php.inc +++ b/rules-tests/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector/Fixture/skip_static_closure_same_class_call.php.inc @@ -4,7 +4,7 @@ namespace Rector\Tests\Php70\Rector\StaticCall\StaticCallOnNonStaticToInstanceCa class SkipStaticClosureSameClassCall { - public static function boot(): void + public function boot(): void { // static closure — no $this, must not rewrite $callback = static function (): void { From f7fcd25ee8670e2af3eb55fe01045f47052ba5a9 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Fri, 5 Jun 2026 21:22:52 +0700 Subject: [PATCH 5/5] fix --- .../StaticCall/StaticCallOnNonStaticToInstanceCallRector.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rules/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector.php b/rules/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector.php index 79c0faee1fc..e506376819b 100644 --- a/rules/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector.php +++ b/rules/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector.php @@ -14,7 +14,6 @@ use PHPStan\Analyser\Scope; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\MethodReflection; -use PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\ObjectType; use Rector\CodingStyle\ValueObject\ObjectMagicMethods; @@ -127,8 +126,8 @@ public function refactor(Node $node): ?Node $classReflection = $scope->getClassReflection(); if ($classReflection instanceof ClassReflection && $classReflection->getName() === $className) { - $function = $scope->getFunction(); - if ($function instanceof PhpFunctionFromParserNodeReflection && $function->isStatic()) { + // detect any scope where $this is unavailable or possibly unavailable + if (! $scope->hasVariableType('this')->yes()) { return null; }