[DeadCode] Skip used in compact() on RemoveUnusedConstructorParamRector (#2345)

* [DeadCode] Skip used in compact() on RemoveUnusedConstructorParamRector

* Fixed 🎉

* phpstan

* phpstan

* [ci-review] Rector Rectify

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Abdul Malik Ikhsan 2022-05-22 18:42:14 +07:00 committed by GitHub
parent 20731aedd2
commit 68906c7e17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 39 deletions

View File

@ -0,0 +1,13 @@
<?php
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUnusedConstructorParamRector\Fixture;
final class SkipUsedInCompact
{
public $data;
public function __construct($hey, $man)
{
$this->data = compact('hey', 'man');
}
}

View File

@ -6,12 +6,12 @@ namespace Rector\DeadCode\NodeCollector;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Core\NodeManipulator\ClassMethodManipulator;
use Rector\Core\NodeAnalyzer\ParamAnalyzer;
final class UnusedParameterResolver
{
public function __construct(
private readonly ClassMethodManipulator $classMethodManipulator
private readonly ParamAnalyzer $paramAnalyzer
) {
}
@ -30,7 +30,7 @@ final class UnusedParameterResolver
continue;
}
if ($this->classMethodManipulator->isParameterUsedInClassMethod($param, $classMethod)) {
if ($this->paramAnalyzer->isParamUsedInClassMethod($classMethod, $param)) {
continue;
}

View File

@ -7,20 +7,25 @@ namespace Rector\Core\NodeAnalyzer;
use PhpParser\Node;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\NullableType;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Core\NodeManipulator\FuncCallManipulator;
use Rector\Core\PhpParser\Comparing\NodeComparator;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\PhpParser\Node\Value\ValueResolver;
use Rector\NodeNameResolver\NodeNameResolver;
final class ParamAnalyzer
{
public function __construct(
private readonly BetterNodeFinder $betterNodeFinder,
private readonly NodeComparator $nodeComparator,
private readonly ValueResolver $valueResolver
private readonly ValueResolver $valueResolver,
private readonly NodeNameResolver $nodeNameResolver,
private readonly FuncCallManipulator $funcCallManipulator
) {
}
@ -29,7 +34,7 @@ final class ParamAnalyzer
return (bool) $this->betterNodeFinder->findFirstInFunctionLikeScoped($classMethod, function (Node $node) use (
$param
): bool {
if (! $node instanceof Variable && ! $node instanceof Closure) {
if (! $node instanceof Variable && ! $node instanceof Closure && ! $node instanceof FuncCall) {
return false;
}
@ -37,13 +42,16 @@ final class ParamAnalyzer
return $this->nodeComparator->areNodesEqual($node, $param->var);
}
foreach ($node->uses as $use) {
if ($this->nodeComparator->areNodesEqual($use->var, $param->var)) {
return true;
}
if ($node instanceof Closure) {
return $this->isVariableInClosureUses($node, $param->var);
}
return false;
if (! $this->nodeNameResolver->isName($node, 'compact')) {
return false;
}
$arguments = $this->funcCallManipulator->extractArgumentsFromCompactFuncCalls([$node]);
return $this->nodeNameResolver->isNames($param, $arguments);
});
}
@ -78,4 +86,15 @@ final class ParamAnalyzer
{
return $param->default instanceof ConstFetch && $this->valueResolver->isNull($param->default);
}
private function isVariableInClosureUses(Closure $closure, Variable $variable): bool
{
foreach ($closure->uses as $use) {
if ($this->nodeComparator->areNodesEqual($use->var, $variable)) {
return true;
}
}
return false;
}
}

View File

@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Rector\Core\NodeManipulator;
use PhpParser\Node;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Param;
@ -14,7 +13,6 @@ use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Type\ObjectType;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\PhpParser\Comparing\NodeComparator;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\Core\ValueObject\MethodName;
@ -27,37 +25,10 @@ final class ClassMethodManipulator
private readonly BetterNodeFinder $betterNodeFinder,
private readonly NodeNameResolver $nodeNameResolver,
private readonly NodeTypeResolver $nodeTypeResolver,
private readonly NodeComparator $nodeComparator,
private readonly FuncCallManipulator $funcCallManipulator,
private readonly ReflectionResolver $reflectionResolver
) {
}
public function isParameterUsedInClassMethod(Param $param, ClassMethod $classMethod): bool
{
$isUsedDirectly = (bool) $this->betterNodeFinder->findFirst(
(array) $classMethod->stmts,
fn (Node $node): bool => $this->nodeComparator->areNodesEqual($node, $param->var)
);
if ($isUsedDirectly) {
return true;
}
/** @var FuncCall[] $compactFuncCalls */
$compactFuncCalls = $this->betterNodeFinder->find((array) $classMethod->stmts, function (Node $node): bool {
if (! $node instanceof FuncCall) {
return false;
}
return $this->nodeNameResolver->isName($node, 'compact');
});
$arguments = $this->funcCallManipulator->extractArgumentsFromCompactFuncCalls($compactFuncCalls);
return $this->nodeNameResolver->isNames($param, $arguments);
}
public function isNamedConstructor(ClassMethod $classMethod): bool
{
if (! $this->nodeNameResolver->isName($classMethod, MethodName::CONSTRUCT)) {