Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector\Fixture;

final class RemoveWithArrayCallableOfOtherClass
{
public function run()
{
$this->format('unused', 'value');

return [\DateTime::class, 'format'];
}

private function format(string $unused, string $value): string
{
return $value;
}
}

?>
-----
<?php

namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector\Fixture;

final class RemoveWithArrayCallableOfOtherClass
{
public function run()
{
$this->format('value');

return [\DateTime::class, 'format'];
}

private function format(string $value): string
{
return $value;
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector\Fixture;

final class SkipWithArrayCallableDynamicMethod
{
public function run(string $method)
{
return [$this, $method];
}

private function validate(string $attribute, mixed $value): bool
{
return $value === true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector\Fixture;

final class SkipWithArrayCallableInPropertyDefault
{
public array $callback = [self::class, 'validate'];

private static function validate(string $attribute, mixed $value): bool
{
return $value === true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector\Fixture;

final class SkipWithArrayCallableRequiredConstructorParam
{
public function __construct(private string $name)
{
}

public function run()
{
return [self::class, 'validate'];
}

private static function validate(string $attribute, mixed $value): bool
{
return $value === true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector\Fixture;

final class SkipWithArrayCallableSelfClass
{
public static function run()
{
return [self::class, 'validate'];
}

private static function validate(string $attribute, mixed $value): bool
{
return $value === true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector\Fixture;

final class SkipWithArrayCallableStaticClass
{
public static function run()
{
return [static::class, 'validate'];
}

private static function validate(string $attribute, mixed $value): bool
{
return $value === true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector\Fixture;

final class SkipWithArrayCallableThis
{
public function run()
{
return [$this, 'validate'];
}

private function validate(string $attribute, mixed $value): bool
{
return $value === true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector\Fixture;

final class SkipWithFirstClassCallableSelf
{
public static function run()
{
return self::validate(...);
}

private static function validate(string $attribute, mixed $value): bool
{
return $value === true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector\Fixture;

final class SkipWithFirstClassCallableSelfInInstanceMethod
{
public function run()
{
return self::validate(...);
}

private function validate(string $attribute, mixed $value): bool
{
return $value === true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector\Fixture;

final class SkipWithFirstClassCallableStatic
{
public static function run()
{
return static::validate(...);
}

private static function validate(string $attribute, mixed $value): bool
{
return $value === true;
}
}
38 changes: 38 additions & 0 deletions rules/DeadCode/NodeManipulator/PrivateMethodParamRemover.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Rector\DeadCode\NodeManipulator;

use PhpParser\Node;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Identifier;
Expand All @@ -16,9 +17,13 @@
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover;
use Rector\Comments\NodeDocBlock\DocBlockUpdater;
use Rector\NodeCollector\NodeAnalyzer\ArrayCallableMethodMatcher;
use Rector\NodeCollector\ValueObject\ArrayCallable;
use Rector\NodeCollector\ValueObject\ArrayCallableDynamicMethod;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\NodeTypeResolver;
use Rector\PhpParser\Node\BetterNodeFinder;
use Rector\PHPStan\ScopeFetcher;

final readonly class PrivateMethodParamRemover
{
Expand All @@ -29,6 +34,7 @@ public function __construct(
private BetterNodeFinder $betterNodeFinder,
private NodeNameResolver $nodeNameResolver,
private NodeTypeResolver $nodeTypeResolver,
private ArrayCallableMethodMatcher $arrayCallableMethodMatcher,
) {
}

Expand Down Expand Up @@ -73,6 +79,11 @@ private function removeCallerArgs(Class_ $class, ClassMethod $classMethod, array
return false;
}

// the code receiving the callable decides how many arguments it passes
if ($this->isUsedAsArrayCallable($class, $classMethod)) {
return false;
}

$keysArg = array_keys($paramsToRemove);

$classObjectType = new ObjectType((string) $this->nodeNameResolver->getName($class));
Expand Down Expand Up @@ -112,6 +123,33 @@ private function removeCallerArgs(Class_ $class, ClassMethod $classMethod, array
return true;
}

private function isUsedAsArrayCallable(Class_ $class, ClassMethod $classMethod): bool
{
$scope = ScopeFetcher::fetch($class);
$methodName = $this->nodeNameResolver->getName($classMethod);

/** @var Array_[] $arrays */
$arrays = $this->betterNodeFinder->findInstanceOf($class, Array_::class);

foreach ($arrays as $array) {
$arrayCallable = $this->arrayCallableMethodMatcher->match($array, $scope, $methodName);
if ($arrayCallable instanceof ArrayCallableDynamicMethod) {
return true;
}

if (! $arrayCallable instanceof ArrayCallable) {
continue;
}

if ($this->nodeNameResolver->isName($class, $arrayCallable->getClass())
&& $this->nodeNameResolver->isName($classMethod, $arrayCallable->getMethod())) {
return true;
}
}

return false;
}

/**
* @param int[] $keysArg
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,10 +382,6 @@ private function nodeScopeResolverProcessNodes(

private function processCallLike(CallLike $callLike, MutatingScope $mutatingScope): void
{
if ($callLike->isFirstClassCallable()) {
return;
}

if ($callLike instanceof StaticCall) {
$callLike->class->setAttribute(AttributeKey::SCOPE, $mutatingScope);
$callLike->name->setAttribute(AttributeKey::SCOPE, $mutatingScope);
Expand All @@ -398,6 +394,10 @@ private function processCallLike(CallLike $callLike, MutatingScope $mutatingScop
$callLike->class->setAttribute(AttributeKey::SCOPE, $mutatingScope);
}

if ($callLike->isFirstClassCallable()) {
return;
}

foreach ($callLike->getArgs() as $arg) {
$arg->value->setAttribute(AttributeKey::SCOPE, $mutatingScope);
}
Expand Down
Loading