2017-10-26 16:43:43 +00:00
|
|
|
<?php declare(strict_types=1);
|
|
|
|
|
2018-11-08 11:56:06 +00:00
|
|
|
namespace Rector\PhpParser\Node;
|
2017-10-26 16:43:43 +00:00
|
|
|
|
|
|
|
use PhpParser\Node;
|
2019-01-14 18:21:23 +00:00
|
|
|
use PhpParser\Node\Stmt;
|
2018-10-09 10:18:42 +00:00
|
|
|
use PhpParser\Node\Stmt\Expression;
|
2017-10-26 16:43:43 +00:00
|
|
|
use PhpParser\NodeFinder;
|
2018-08-14 09:35:18 +00:00
|
|
|
use Rector\NodeTypeResolver\Node\Attribute;
|
2017-10-26 16:43:43 +00:00
|
|
|
|
|
|
|
final class BetterNodeFinder
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @var NodeFinder
|
|
|
|
*/
|
|
|
|
private $nodeFinder;
|
|
|
|
|
|
|
|
public function __construct(NodeFinder $nodeFinder)
|
|
|
|
{
|
|
|
|
$this->nodeFinder = $nodeFinder;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function findFirstAncestorInstanceOf(Node $node, string $type): ?Node
|
|
|
|
{
|
|
|
|
$currentNode = $node->getAttribute(Attribute::PARENT_NODE);
|
|
|
|
while ($currentNode !== null) {
|
|
|
|
if ($currentNode instanceof $type) {
|
|
|
|
return $currentNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
$currentNode = $currentNode->getAttribute(Attribute::PARENT_NODE);
|
|
|
|
}
|
|
|
|
|
2017-10-26 19:06:11 +00:00
|
|
|
return null;
|
2017-10-26 16:43:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-01-14 18:21:23 +00:00
|
|
|
* @param Node|Node[]|Stmt[] $nodes
|
2017-10-26 16:43:43 +00:00
|
|
|
* @return Node[]
|
|
|
|
*/
|
|
|
|
public function findInstanceOf($nodes, string $type): array
|
|
|
|
{
|
|
|
|
return $this->nodeFinder->findInstanceOf($nodes, $type);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param Node|Node[] $nodes
|
|
|
|
*/
|
|
|
|
public function findFirstInstanceOf($nodes, string $type): ?Node
|
|
|
|
{
|
|
|
|
return $this->nodeFinder->findFirstInstanceOf($nodes, $type);
|
|
|
|
}
|
2017-10-26 19:20:05 +00:00
|
|
|
|
2018-01-15 22:14:44 +00:00
|
|
|
/**
|
|
|
|
* @param Node|Node[] $nodes
|
|
|
|
*/
|
|
|
|
public function findLastInstanceOf($nodes, string $type): ?Node
|
|
|
|
{
|
|
|
|
$foundInstances = $this->nodeFinder->findInstanceOf($nodes, $type);
|
2019-02-17 14:12:47 +00:00
|
|
|
if ($foundInstances === []) {
|
2018-01-15 22:14:44 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return array_pop($foundInstances);
|
|
|
|
}
|
|
|
|
|
2017-10-26 19:20:05 +00:00
|
|
|
/**
|
|
|
|
* @param Node|Node[] $nodes
|
|
|
|
* @return Node[]
|
|
|
|
*/
|
|
|
|
public function find($nodes, callable $filter): array
|
|
|
|
{
|
|
|
|
return $this->nodeFinder->find($nodes, $filter);
|
|
|
|
}
|
2017-11-01 21:37:57 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @param Node|Node[] $nodes
|
|
|
|
*/
|
|
|
|
public function findFirst($nodes, callable $filter): ?Node
|
|
|
|
{
|
|
|
|
return $this->nodeFinder->findFirst($nodes, $filter);
|
|
|
|
}
|
2018-10-09 10:18:42 +00:00
|
|
|
|
|
|
|
public function findFirstPrevious(Node $node, callable $filter): ?Node
|
|
|
|
{
|
2018-10-11 04:49:49 +00:00
|
|
|
$node = $node instanceof Expression ? $node : $node->getAttribute(Attribute::CURRENT_EXPRESSION);
|
2019-01-25 00:49:26 +00:00
|
|
|
if ($node === null) {
|
|
|
|
return null;
|
|
|
|
}
|
2018-10-09 10:18:42 +00:00
|
|
|
|
|
|
|
$foundNode = $this->findFirst([$node], $filter);
|
|
|
|
// we found what we need
|
2019-02-17 14:12:47 +00:00
|
|
|
if ($foundNode !== null) {
|
2018-10-09 10:18:42 +00:00
|
|
|
return $foundNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
// move to next expression
|
2018-10-11 04:49:49 +00:00
|
|
|
$previousExpression = $node->getAttribute(Attribute::PREVIOUS_EXPRESSION);
|
2018-10-09 10:18:42 +00:00
|
|
|
if ($previousExpression === null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->findFirstPrevious($previousExpression, $filter);
|
|
|
|
}
|
2017-10-26 16:43:43 +00:00
|
|
|
}
|