Skip to content

Commit 8e2adf2

Browse files
authored
[Symfony61] Skip non static external class callable on MagicClosureTwigExtensionToNativeMethodsRector (#927)
1 parent cfa7148 commit 8e2adf2

File tree

3 files changed

+58
-0
lines changed

3 files changed

+58
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace Rector\Symfony\Tests\Symfony61\Rector\Class_\MagicClosureTwigExtensionToNativeMethodsRector\Fixture;
4+
5+
use Twig\Extension\AbstractExtension;
6+
use Twig\TwigFunction;
7+
use Rector\Symfony\Tests\Symfony61\Rector\Class_\MagicClosureTwigExtensionToNativeMethodsRector\Source\ExternalResolverService;
8+
9+
final class SkipExternalNonStaticMethod extends AbstractExtension
10+
{
11+
public function getFunctions(): array
12+
{
13+
return [
14+
new TwigFunction('resolve', [ExternalResolverService::class, 'resolve']),
15+
];
16+
}
17+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Symfony\Tests\Symfony61\Rector\Class_\MagicClosureTwigExtensionToNativeMethodsRector\Source;
6+
7+
final class ExternalResolverService
8+
{
9+
public function resolve(mixed $value): mixed
10+
{
11+
return $value;
12+
}
13+
}

rules/Symfony61/Rector/Class_/MagicClosureTwigExtensionToNativeMethodsRector.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66

77
use PhpParser\Node;
88
use PhpParser\Node\Expr\Array_;
9+
use PhpParser\Node\Expr\ClassConstFetch;
910
use PhpParser\Node\Expr\MethodCall;
1011
use PhpParser\Node\Stmt\Class_;
1112
use PhpParser\Node\Stmt\ClassMethod;
1213
use PhpParser\Node\VariadicPlaceholder;
1314
use PHPStan\Analyser\Scope;
15+
use PHPStan\Reflection\ReflectionProvider;
1416
use PHPStan\Type\ObjectType;
1517
use Rector\NodeCollector\NodeAnalyzer\ArrayCallableMethodMatcher;
1618
use Rector\NodeCollector\ValueObject\ArrayCallable;
@@ -31,6 +33,7 @@ final class MagicClosureTwigExtensionToNativeMethodsRector extends AbstractRecto
3133
{
3234
public function __construct(
3335
private readonly ArrayCallableMethodMatcher $arrayCallableMethodMatcher,
36+
private readonly ReflectionProvider $reflectionProvider,
3437
) {
3538
}
3639

@@ -147,6 +150,10 @@ private function refactorClassMethod(ClassMethod $classMethod, Scope $scope): bo
147150
return null;
148151
}
149152

153+
if ($this->isNonStaticExternalClassCallable($arrayCallable, $scope)) {
154+
return null;
155+
}
156+
150157
$hasChanged = true;
151158

152159
return new MethodCall($arrayCallable->getCallerExpr(), $arrayCallable->getMethod(), [
@@ -156,4 +163,25 @@ private function refactorClassMethod(ClassMethod $classMethod, Scope $scope): bo
156163

157164
return $hasChanged;
158165
}
166+
167+
private function isNonStaticExternalClassCallable(ArrayCallable $arrayCallable, Scope $scope): bool
168+
{
169+
if (! $arrayCallable->getCallerExpr() instanceof ClassConstFetch) {
170+
return false;
171+
}
172+
173+
$className = $arrayCallable->getClass();
174+
if (! $this->reflectionProvider->hasClass($className)) {
175+
return false;
176+
}
177+
178+
$classReflection = $this->reflectionProvider->getClass($className);
179+
$methodName = $arrayCallable->getMethod();
180+
181+
if (! $classReflection->hasMethod($methodName)) {
182+
return false;
183+
}
184+
185+
return ! $classReflection->getMethod($methodName, $scope)->isStatic();
186+
}
159187
}

0 commit comments

Comments
 (0)