Skip to content

Commit 5ce62c7

Browse files
Fix StaticCallOnNonStaticToInstanceCallRector for same-class calls (#7876)
When calling a non-static method statically from within the same class, convert to $this->method() instead of skipping. This eliminates the PHP deprecation warning for non-static method called statically. Calls to ancestor methods (e.g., Grandpa::method() from a descendant) are still skipped as they are valid non-static usage.
1 parent ca9da16 commit 5ce62c7

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php70\Rector\StaticCall\StaticCallOnNonStaticToInstanceCallRector\Fixture;
4+
5+
class SameClassNonStatic
6+
{
7+
public function run()
8+
{
9+
return SameClassNonStatic::doWork();
10+
}
11+
12+
public function doWork()
13+
{
14+
return 'work done';
15+
}
16+
}
17+
18+
?>
19+
-----
20+
<?php
21+
22+
namespace Rector\Tests\Php70\Rector\StaticCall\StaticCallOnNonStaticToInstanceCallRector\Fixture;
23+
24+
class SameClassNonStatic
25+
{
26+
public function run()
27+
{
28+
return $this->doWork();
29+
}
30+
31+
public function doWork()
32+
{
33+
return 'work done';
34+
}
35+
}
36+
37+
?>

rules/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use PhpParser\Node\Expr\New_;
1111
use PhpParser\Node\Expr\PropertyFetch;
1212
use PhpParser\Node\Expr\StaticCall;
13+
use PhpParser\Node\Expr\Variable;
1314
use PHPStan\Analyser\Scope;
1415
use PHPStan\Reflection\ClassReflection;
1516
use PHPStan\Reflection\MethodReflection;
@@ -123,6 +124,11 @@ public function refactor(Node $node): ?Node
123124
return null;
124125
}
125126

127+
$classReflection = $scope->getClassReflection();
128+
if ($classReflection instanceof ClassReflection && $classReflection->getName() === $className) {
129+
return new MethodCall(new Variable('this'), $node->name, $node->args);
130+
}
131+
126132
if ($this->isInstantiable($className, $scope)) {
127133
$new = new New_($node->class);
128134
return new MethodCall($new, $node->name, $node->args);
@@ -168,8 +174,11 @@ private function shouldSkip(string $methodName, string $className, StaticCall $s
168174
return true;
169175
}
170176

171-
$reflection = $scope->getClassReflection();
172-
if ($reflection instanceof ClassReflection && $reflection->is($className)) {
177+
$currentClassReflection = $scope->getClassReflection();
178+
if ($currentClassReflection instanceof ClassReflection
179+
&& $this->reflectionProvider->hasClass($className)
180+
&& $currentClassReflection->isSubclassOfClass($this->reflectionProvider->getClass($className))
181+
) {
173182
return true;
174183
}
175184

0 commit comments

Comments
 (0)