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: