Skip to content

Commit 0f57d62

Browse files
authored
Merge pull request #3878 from ruby/find-all
Add Prism::Node#find_all
2 parents 20dc949 + 51df90e commit 0f57d62

File tree

4 files changed

+38
-1
lines changed

4 files changed

+38
-1
lines changed

templates/lib/prism/node.rb.erb

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ module Prism
200200
end
201201

202202
# Returns the first node that matches the given block when visited in a
203-
# depth-first search. This is useful for finding a node that matches a
203+
# breadth-first search. This is useful for finding a node that matches a
204204
# particular condition.
205205
#
206206
# node.breadth_first_search { |node| node.node_id == node_id }
@@ -215,6 +215,26 @@ module Prism
215215

216216
nil
217217
end
218+
alias find breadth_first_search
219+
220+
# Returns all of the nodes that match the given block when visited in a
221+
# breadth-first search. This is useful for finding all nodes that match a
222+
# particular condition.
223+
#
224+
# node.breadth_first_search_all { |node| node.is_a?(Prism::CallNode) }
225+
#
226+
def breadth_first_search_all(&block)
227+
queue = [self] #: Array[Prism::node]
228+
results = [] #: Array[Prism::node]
229+
230+
while (node = queue.shift)
231+
results << node if yield node
232+
queue.concat(node.compact_child_nodes)
233+
end
234+
235+
results
236+
end
237+
alias find_all breadth_first_search_all
218238

219239
# Returns a list of the fields that exist for this node class. Fields
220240
# describe the structure of the node. This kind of reflection is useful for

templates/rbi/prism/node.rbi.erb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ class Prism::Node
4949
sig { params(block: T.proc.params(node: Prism::Node).returns(T::Boolean)).returns(T.nilable(Prism::Node)) }
5050
def breadth_first_search(&block); end
5151

52+
sig { params(block: T.proc.params(node: Prism::Node).returns(T::Boolean)).returns(T::Array[Prism::Node]) }
53+
def breadth_first_search_all(&block); end
54+
5255
sig { abstract.params(visitor: Prism::Visitor).returns(T.untyped) }
5356
def accept(visitor); end
5457

templates/sig/prism/node.rbs.erb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ module Prism
2525
def to_dot: () -> String
2626
def tunnel: (Integer line, Integer column) -> Array[Prism::node]
2727
def breadth_first_search: () { (Prism::node) -> bool } -> Prism::node?
28+
alias find breadth_first_search
29+
def breadth_first_search_all: () { (Prism::node) -> bool } -> Array[Prism::node]
30+
alias find_all breadth_first_search_all
2831
def newline!: (Array[untyped]) -> void
2932

3033
def save: (_Repository repository) -> void

test/prism/result/breadth_first_search_test.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,16 @@ def test_breadth_first_search
1414
refute_nil found
1515
assert_equal 8, found.start_offset
1616
end
17+
18+
def test_breadth_first_search_all
19+
result = Prism.parse("[1 + 2, 2]")
20+
found_nodes =
21+
result.value.breadth_first_search_all do |node|
22+
node.is_a?(IntegerNode)
23+
end
24+
25+
assert_equal 3, found_nodes.size
26+
assert_equal 8, found_nodes[0].start_offset
27+
end
1728
end
1829
end

0 commit comments

Comments
 (0)