Skip to content

Commit 1ffb141

Browse files
committed
Add Node#breadth_first_search
1 parent d014386 commit 1ffb141

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

templates/lib/prism/node.rb.erb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,23 @@ module Prism
116116
result
117117
end
118118

119+
# Returns the first node that matches the given block when visited in a
120+
# depth-first search. This is useful for finding a node that matches a
121+
# particular condition.
122+
#
123+
# node.breadth_first_search { |node| node.node_id == node_id }
124+
#
125+
def breadth_first_search(&block)
126+
queue = [self] #: Array[Prism::node]
127+
128+
while (node = queue.shift)
129+
return node if yield node
130+
queue.concat(node.compact_child_nodes)
131+
end
132+
133+
nil
134+
end
135+
119136
# Returns a list of the fields that exist for this node class. Fields
120137
# describe the structure of the node. This kind of reflection is useful for
121138
# things like recursively visiting each node _and_ field in the tree.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# frozen_string_literal: true
2+
3+
require_relative "../test_helper"
4+
5+
module Prism
6+
class BreadthFirstSearchTest < TestCase
7+
def test_breadth_first_search
8+
result = Prism.parse("[1 + 2, 2]")
9+
found =
10+
result.value.breadth_first_search do |node|
11+
node.is_a?(IntegerNode) && node.value == 2
12+
end
13+
14+
refute_nil found
15+
assert_equal 8, found.start_offset
16+
end
17+
end
18+
end

0 commit comments

Comments
 (0)