Skip to content

Commit

Permalink
[Php81] Skip const Fetch non static method on FirstClassCallableRector (
Browse files Browse the repository at this point in the history
#3183)

Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
samsonasik and actions-user committed Dec 11, 2022
1 parent 5ccf468 commit 8bf7073
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Rector\Tests\Php81\Rector\Array_\FirstClassCallableRector\Fixture;

use Rector\Tests\Php81\Rector\Array_\FirstClassCallableRector\Source\SomeExternalObject;

final class SkipNonStaticPrivateMethodWithOtherObjectConstFetch
{
public function provideListenerPriority(): array
{
return [
'listener' => [
[SomeExternalObject::class, 'sleepPrivateStatic'],
],
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Rector\Tests\Php81\Rector\Array_\FirstClassCallableRector\Fixture;

use Rector\Tests\Php81\Rector\Array_\FirstClassCallableRector\Source\SomeExternalObject;

final class SkipNonStaticWithOtherObjectConstFetch
{
public function provideListenerPriority(): array
{
return [
'listener' => [
[SomeExternalObject::class, 'sleepOver'],
],
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Rector\Tests\Php81\Rector\Array_\FirstClassCallableRector\Fixture;

use Rector\Tests\Php81\Rector\Array_\FirstClassCallableRector\Source\SomeExternalObject;

final class StaticWithOtherObjectConstFetch
{
public function provideListenerPriority(): array
{
return [SomeExternalObject::class, 'sleepStatic'];
}
}

?>
-----
<?php

namespace Rector\Tests\Php81\Rector\Array_\FirstClassCallableRector\Fixture;

use Rector\Tests\Php81\Rector\Array_\FirstClassCallableRector\Source\SomeExternalObject;

final class StaticWithOtherObjectConstFetch
{
public function provideListenerPriority(): array
{
return SomeExternalObject::sleepStatic(...);
}
}

?>
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,12 @@ final class SomeExternalObject
public function sleepOver()
{
}

public static function sleepStatic()
{
}

private static function sleepPrivateStatic()
{
}
}
56 changes: 52 additions & 4 deletions rules/Php81/Rector/Array_/FirstClassCallableRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,17 @@
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\VariadicPlaceholder;
use Rector\Core\Rector\AbstractRector;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use Rector\Core\PhpParser\AstResolver;
use Rector\Core\Rector\AbstractScopeAwareRector;
use Rector\Core\ValueObject\PhpVersion;
use Rector\NodeCollector\NodeAnalyzer\ArrayCallableMethodMatcher;
use Rector\NodeCollector\ValueObject\ArrayCallable;
use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType;
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
Expand All @@ -25,10 +31,11 @@
*
* @see \Rector\Tests\Php81\Rector\Array_\FirstClassCallableRector\FirstClassCallableRectorTest
*/
final class FirstClassCallableRector extends AbstractRector implements MinPhpVersionInterface
final class FirstClassCallableRector extends AbstractScopeAwareRector implements MinPhpVersionInterface
{
public function __construct(
private readonly ArrayCallableMethodMatcher $arrayCallableMethodMatcher
private readonly ArrayCallableMethodMatcher $arrayCallableMethodMatcher,
private readonly AstResolver $astResolver
) {
}

Expand Down Expand Up @@ -79,7 +86,7 @@ public function getNodeTypes(): array
/**
* @param Array_ $node
*/
public function refactor(Node $node): ?Node
public function refactorWithScope(Node $node, Scope $scope)
{
$arrayCallable = $this->arrayCallableMethodMatcher->match($node);
if (! $arrayCallable instanceof ArrayCallable) {
Expand All @@ -93,6 +100,15 @@ public function refactor(Node $node): ?Node

$args = [new VariadicPlaceholder()];
if ($callerExpr instanceof ClassConstFetch) {
$type = $this->getType($callerExpr->class);
if ($type instanceof FullyQualifiedObjectType && $this->isNonStaticOtherObject(
$type,
$arrayCallable,
$scope
)) {
return null;
}

return new StaticCall($callerExpr->class, $arrayCallable->getMethod(), $args);
}

Expand All @@ -103,4 +119,36 @@ public function provideMinPhpVersion(): int
{
return PhpVersion::PHP_81;
}

private function isNonStaticOtherObject(
FullyQualifiedObjectType $fullyQualifiedObjectType,
ArrayCallable $arrayCallable,
Scope $scope
): bool {
$classReflection = $scope->getClassReflection();
if (! $classReflection instanceof ClassReflection) {
return false;
}

if ($classReflection->getName() === $fullyQualifiedObjectType->getClassName()) {
return false;
}

$class = $this->astResolver->resolveClassFromName($arrayCallable->getClass());
if (! $class instanceof ClassLike) {
return false;
}

$classMethod = $class->getMethod($arrayCallable->getMethod());

if (! $classMethod instanceof ClassMethod) {
return false;
}

if (! $classMethod->isStatic()) {
return true;
}

return ! $classMethod->isPublic();
}
}

0 comments on commit 8bf7073

Please sign in to comment.