| 1 |
<?php declare(strict_types=1); |
| 2 |
|
| 3 |
namespace PhpParser; |
| 4 |
|
| 5 |
use PhpParser\NodeVisitor\FindingVisitor; |
| 6 |
use PhpParser\NodeVisitor\FirstFindingVisitor; |
| 7 |
|
| 8 |
class NodeFinder { |
| 9 |
/** |
| 10 |
* Find all nodes satisfying a filter callback. |
| 11 |
* |
| 12 |
* @param Node|Node[] $nodes Single node or array of nodes to search in |
| 13 |
* @param callable $filter Filter callback: function(Node $node) : bool |
| 14 |
* |
| 15 |
* @return Node[] Found nodes satisfying the filter callback |
| 16 |
*/ |
| 17 |
public function find($nodes, callable $filter): array { |
| 18 |
if ($nodes === []) { |
| 19 |
return []; |
| 20 |
} |
| 21 |
|
| 22 |
if (!is_array($nodes)) { |
| 23 |
$nodes = [$nodes]; |
| 24 |
} |
| 25 |
|
| 26 |
$visitor = new FindingVisitor($filter); |
| 27 |
|
| 28 |
$traverser = new NodeTraverser($visitor); |
| 29 |
$traverser->traverse($nodes); |
| 30 |
|
| 31 |
return $visitor->getFoundNodes(); |
| 32 |
} |
| 33 |
|
| 34 |
/** |
| 35 |
* Find all nodes that are instances of a certain class. |
| 36 |
|
| 37 |
* @template TNode as Node |
| 38 |
* |
| 39 |
* @param Node|Node[] $nodes Single node or array of nodes to search in |
| 40 |
* @param class-string<TNode> $class Class name |
| 41 |
* |
| 42 |
* @return TNode[] Found nodes (all instances of $class) |
| 43 |
*/ |
| 44 |
public function findInstanceOf($nodes, string $class): array { |
| 45 |
return $this->find($nodes, function ($node) use ($class) { |
| 46 |
return $node instanceof $class; |
| 47 |
}); |
| 48 |
} |
| 49 |
|
| 50 |
/** |
| 51 |
* Find first node satisfying a filter callback. |
| 52 |
* |
| 53 |
* @param Node|Node[] $nodes Single node or array of nodes to search in |
| 54 |
* @param callable $filter Filter callback: function(Node $node) : bool |
| 55 |
* |
| 56 |
* @return null|Node Found node (or null if none found) |
| 57 |
*/ |
| 58 |
public function findFirst($nodes, callable $filter): ?Node { |
| 59 |
if ($nodes === []) { |
| 60 |
return null; |
| 61 |
} |
| 62 |
|
| 63 |
if (!is_array($nodes)) { |
| 64 |
$nodes = [$nodes]; |
| 65 |
} |
| 66 |
|
| 67 |
$visitor = new FirstFindingVisitor($filter); |
| 68 |
|
| 69 |
$traverser = new NodeTraverser($visitor); |
| 70 |
$traverser->traverse($nodes); |
| 71 |
|
| 72 |
return $visitor->getFoundNode(); |
| 73 |
} |
| 74 |
|
| 75 |
/** |
| 76 |
* Find first node that is an instance of a certain class. |
| 77 |
* |
| 78 |
* @template TNode as Node |
| 79 |
* |
| 80 |
* @param Node|Node[] $nodes Single node or array of nodes to search in |
| 81 |
* @param class-string<TNode> $class Class name |
| 82 |
* |
| 83 |
* @return null|TNode Found node, which is an instance of $class (or null if none found) |
| 84 |
*/ |
| 85 |
public function findFirstInstanceOf($nodes, string $class): ?Node { |
| 86 |
return $this->findFirst($nodes, function ($node) use ($class) { |
| 87 |
return $node instanceof $class; |
| 88 |
}); |
| 89 |
} |
| 90 |
} |
| 91 |
|