rector/rules/DeadCode/NodeFinder/NextVariableUsageNodeFinder.php
Tomas Votruba adc6b8148a Updated Rector to commit f7eeebaa7bdb96a6bc7311b1fa4a4e8a19789b35
f7eeebaa7b [DeadCode] Fix non-null type check on RemoveUnusedNonEmptyArrayBeforeForeachRector (#430)
2021-07-13 05:50:47 +00:00

84 lines
3.4 KiB
PHP

<?php
declare (strict_types=1);
namespace Rector\DeadCode\NodeFinder;
use PhpParser\Node;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\Variable;
use PhpParser\NodeTraverser;
use Rector\Core\PhpParser\Comparing\NodeComparator;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeNestingScope\ParentScopeFinder;
use Rector\NodeTypeResolver\Node\AttributeKey;
use RectorPrefix20210713\Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser;
final class NextVariableUsageNodeFinder
{
/**
* @var \Rector\Core\PhpParser\Node\BetterNodeFinder
*/
private $betterNodeFinder;
/**
* @var \Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser
*/
private $simpleCallableNodeTraverser;
/**
* @var \Rector\NodeNameResolver\NodeNameResolver
*/
private $nodeNameResolver;
/**
* @var \Rector\NodeNestingScope\ParentScopeFinder
*/
private $parentScopeFinder;
/**
* @var \Rector\Core\PhpParser\Comparing\NodeComparator
*/
private $nodeComparator;
public function __construct(\Rector\Core\PhpParser\Node\BetterNodeFinder $betterNodeFinder, \RectorPrefix20210713\Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser $simpleCallableNodeTraverser, \Rector\NodeNameResolver\NodeNameResolver $nodeNameResolver, \Rector\NodeNestingScope\ParentScopeFinder $parentScopeFinder, \Rector\Core\PhpParser\Comparing\NodeComparator $nodeComparator)
{
$this->betterNodeFinder = $betterNodeFinder;
$this->simpleCallableNodeTraverser = $simpleCallableNodeTraverser;
$this->nodeNameResolver = $nodeNameResolver;
$this->parentScopeFinder = $parentScopeFinder;
$this->nodeComparator = $nodeComparator;
}
public function find(\PhpParser\Node\Expr\Assign $assign) : ?\PhpParser\Node
{
$scopeNode = $this->parentScopeFinder->find($assign);
if ($scopeNode === null) {
return null;
}
/** @var Variable $expr */
$expr = $assign->var;
$this->simpleCallableNodeTraverser->traverseNodesWithCallable((array) $scopeNode->stmts, function (\PhpParser\Node $currentNode) use($expr, &$nextUsageOfVariable) : ?int {
// used above the assign
if ($currentNode->getStartTokenPos() < $expr->getStartTokenPos()) {
return null;
}
// skip self
if ($this->nodeComparator->areSameNode($currentNode, $expr)) {
return null;
}
if (!$this->nodeComparator->areNodesEqual($currentNode, $expr)) {
return null;
}
$currentNodeParent = $currentNode->getAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::PARENT_NODE);
if ($currentNodeParent instanceof \PhpParser\Node\Expr\Assign && !$this->hasInParentExpression($currentNodeParent, $expr)) {
return \PhpParser\NodeTraverser::STOP_TRAVERSAL;
}
$nextUsageOfVariable = $currentNode;
return \PhpParser\NodeTraverser::STOP_TRAVERSAL;
});
return $nextUsageOfVariable;
}
private function hasInParentExpression(\PhpParser\Node\Expr\Assign $assign, \PhpParser\Node\Expr\Variable $variable) : bool
{
$name = $this->nodeNameResolver->getName($variable);
if ($name === null) {
return \false;
}
return $this->betterNodeFinder->hasVariableOfName($assign->expr, $name);
}
}