app/lib/celery_script/tree_climber.rb
# PROBLEM THIS CLASS SOLVES: You need to run a function against every node in
# an abstract syntax tree, usually for validation or type checking.
module CeleryScript
class TreeClimber
def self.travel(node, callable)
visit_node(node, callable)
nil
end
def self.find_all_by_kind(node, name)
results = []
filter = ->(n) { results.push(n) if n.kind == name }
travel(node, filter)
results
end
def self.find_all_with_arg(node, arg_name)
results = []
filter = ->(n) { results.push(n) if n.args.has_key?(arg_name) }
travel(node, filter)
results
end
private
def self.visit_node(node, callable)
if node.is_a?(AstNode) # Keep recursing if it's not a leaf.
callable.call(node)
visit_each_arg(node, callable)
visit_each_body_item(node, callable)
end
end
def self.visit_each_arg(origin, callable)
origin.args.map { |_, node| visit_node(node, callable) }
end
def self.visit_each_body_item(origin, callable)
origin.body.map { |node| visit_node(node, callable) } if origin.body
end
end
end