Skip to content

Commit 24e837e

Browse files
committed
fix: static to self static method call on final class
Parent method calls should also be transformed to self::method() calls.
1 parent ab29a4a commit 24e837e

File tree

3 files changed

+56
-6
lines changed

3 files changed

+56
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace Rector\Tests\CodeQuality\Rector\Class_\StaticToSelfStaticMethodCallOnFinalClassRector\Fixture;
4+
5+
use Rector\Tests\CodeQuality\Rector\Class_\StaticToSelfStaticMethodCallOnFinalClassRector\Source\BaseClass;
6+
7+
final class ParentStaticMethod extends BaseClass
8+
{
9+
public function test(): string
10+
{
11+
return static::parentMethod();
12+
}
13+
}
14+
15+
?>
16+
-----
17+
<?php
18+
19+
namespace Rector\Tests\CodeQuality\Rector\Class_\StaticToSelfStaticMethodCallOnFinalClassRector\Fixture;
20+
21+
use Rector\Tests\CodeQuality\Rector\Class_\StaticToSelfStaticMethodCallOnFinalClassRector\Source\BaseClass;
22+
23+
final class ParentStaticMethod extends BaseClass
24+
{
25+
public function test(): string
26+
{
27+
return self::parentMethod();
28+
}
29+
}
30+
31+
?>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Rector\Tests\CodeQuality\Rector\Class_\StaticToSelfStaticMethodCallOnFinalClassRector\Source;
4+
5+
class BaseClass
6+
{
7+
protected static function parentMethod(): string
8+
{
9+
return 'parent method';
10+
}
11+
}

rules/CodeQuality/Rector/Class_/StaticToSelfStaticMethodCallOnFinalClassRector.php

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@
99
use PhpParser\Node\Identifier;
1010
use PhpParser\Node\Name;
1111
use PhpParser\Node\Stmt\Class_;
12-
use PhpParser\Node\Stmt\ClassMethod;
12+
use PHPStan\Reflection\ClassReflection;
1313
use Rector\Configuration\Parameter\FeatureFlags;
1414
use Rector\Enum\ObjectReference;
15+
use Rector\PHPStan\ScopeFetcher;
1516
use Rector\Rector\AbstractRector;
1617
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
1718
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
1819

1920
/**
21+
* @see https://3v4l.org/VbcrN
2022
* @see \Rector\Tests\CodeQuality\Rector\Class_\StaticToSelfStaticMethodCallOnFinalClassRector\StaticToSelfStaticMethodCallOnFinalClassRectorTest
2123
*/
2224
final class StaticToSelfStaticMethodCallOnFinalClassRector extends AbstractRector
@@ -76,8 +78,14 @@ public function refactor(Node $node): ?Class_
7678
}
7779

7880
$hasChanged = false;
81+
$scope = ScopeFetcher::fetch($node);
82+
$classReflection = $scope->getClassReflection();
7983

80-
$this->traverseNodesWithCallable($node->stmts, function (Node $subNode) use (&$hasChanged, $node): ?StaticCall {
84+
if (! $classReflection instanceof ClassReflection) {
85+
return null;
86+
}
87+
88+
$this->traverseNodesWithCallable($node->stmts, function (Node $subNode) use (&$hasChanged, $classReflection, $scope): ?StaticCall {
8189
if (! $subNode instanceof StaticCall) {
8290
return null;
8391
}
@@ -92,15 +100,15 @@ public function refactor(Node $node): ?Class_
92100
}
93101

94102
$methodName = (string) $this->getName($subNode->name);
95-
$targetClassMethod = $node->getMethod($methodName);
96103

97-
// skip call non-existing method from current class to ensure transformation is safe
98-
if (! $targetClassMethod instanceof ClassMethod) {
104+
if (! $classReflection->hasMethod($methodName)) {
99105
return null;
100106
}
101107

108+
$methodReflection = $classReflection->getMethod($methodName, $scope);
109+
102110
// avoid overlapped change
103-
if (! $targetClassMethod->isStatic()) {
111+
if (! $methodReflection->isStatic()) {
104112
return null;
105113
}
106114

0 commit comments

Comments
 (0)