mirror of
https://github.com/rectorphp/rector.git
synced 2025-02-16 05:44:59 +01:00
f7eeebaa7b
[DeadCode] Fix non-null type check on RemoveUnusedNonEmptyArrayBeforeForeachRector (#430)
84 lines
3.4 KiB
PHP
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);
|
|
}
|
|
}
|