aboutsummaryrefslogtreecommitdiffstats
path: root/yarp
diff options
context:
space:
mode:
authorKevin Newton <kddnewton@gmail.com>2023-09-22 10:32:34 -0400
committerKevin Newton <kddnewton@gmail.com>2023-09-27 12:10:23 -0400
commitaf8d475281858eccdbc1e557c795d81d6badd589 (patch)
treea192ee0fea947489cf2627132be3d7e75253e302 /yarp
parentbe861053c5e19783d75c1d2cd66d6007b9ba5072 (diff)
downloadruby-af8d475281858eccdbc1e557c795d81d6badd589.tar.gz
[ruby/yarp] Move dispatcher into its own autoload
https://github.com/ruby/yarp/commit/52bd001ea2
Diffstat (limited to 'yarp')
-rw-r--r--yarp/templates/lib/yarp/dispatcher.rb.erb88
-rw-r--r--yarp/templates/lib/yarp/node.rb.erb84
-rwxr-xr-xyarp/templates/template.rb1
3 files changed, 89 insertions, 84 deletions
diff --git a/yarp/templates/lib/yarp/dispatcher.rb.erb b/yarp/templates/lib/yarp/dispatcher.rb.erb
new file mode 100644
index 0000000000..40d66ff6f1
--- /dev/null
+++ b/yarp/templates/lib/yarp/dispatcher.rb.erb
@@ -0,0 +1,88 @@
+module YARP
+ # The dispatcher class fires events for nodes that are found while walking an
+ # AST to all registered listeners. It's useful for performing different types
+ # of analysis on the AST while only having to walk the tree once.
+ #
+ # To use the dispatcher, you would first instantiate it and register listeners
+ # for the events you're interested in:
+ #
+ # class OctalListener
+ # def on_integer_node_enter(node)
+ # if node.octal? && !node.slice.start_with?("0o")
+ # warn("Octal integers should be written with the 0o prefix")
+ # end
+ # end
+ # end
+ #
+ # dispatcher = Dispatcher.new
+ # dispatcher.register(listener, :on_integer_node_enter)
+ #
+ # Then, you can walk any number of trees and dispatch events to the listeners:
+ #
+ # result = YARP.parse("001 + 002 + 003")
+ # dispatcher.dispatch(result.value)
+ #
+ # Optionally, you can also use `#dispatch_once` to dispatch enter and leave
+ # events for a single node without recursing further down the tree. This can
+ # be useful in circumstances where you want to reuse the listeners you already
+ # have registers but want to stop walking the tree at a certain point.
+ #
+ # integer = result.value.statements.body.first.receiver.receiver
+ # dispatcher.dispatch_once(integer)
+ #
+ class Dispatcher < Visitor
+ # attr_reader listeners: Hash[Symbol, Array[Listener]]
+ attr_reader :listeners
+
+ def initialize
+ @listeners = {}
+ end
+
+ # Register a listener for one or more events
+ #
+ # def register: (Listener, *Symbol) -> void
+ def register(listener, *events)
+ events.each { |event| (listeners[event] ||= []) << listener }
+ end
+
+ # Walks `root` dispatching events to all registered listeners
+ #
+ # def dispatch: (Node) -> void
+ alias dispatch visit
+
+ # Dispatches a single event for `node` to all registered listeners
+ #
+ # def dispatch_once: (Node) -> void
+ def dispatch_once(node)
+ node.accept(DispatchOnce.new(listeners))
+ end
+ <%- nodes.each do |node| -%>
+
+ # Dispatch enter and leave events for <%= node.name %> nodes and continue
+ # walking the tree.
+ def visit_<%= node.human %>(node)
+ listeners[:on_<%= node.human %>_enter]&.each { |listener| listener.on_<%= node.human %>_enter(node) }
+ super
+ listeners[:on_<%= node.human %>_leave]&.each { |listener| listener.on_<%= node.human %>_leave(node) }
+ end
+ <%- end -%>
+
+ class DispatchOnce < Visitor
+ attr_reader :listeners
+
+ def initialize(listeners)
+ @listeners = listeners
+ end
+ <%- nodes.each do |node| -%>
+
+ # Dispatch enter and leave events for <%= node.name %> nodes.
+ def visit_<%= node.human %>(node)
+ listeners[:on_<%= node.human %>_enter]&.each { |listener| listener.on_<%= node.human %>_enter(node) }
+ listeners[:on_<%= node.human %>_leave]&.each { |listener| listener.on_<%= node.human %>_leave(node) }
+ end
+ <%- end -%>
+ end
+
+ private_constant :DispatchOnce
+ end
+end
diff --git a/yarp/templates/lib/yarp/node.rb.erb b/yarp/templates/lib/yarp/node.rb.erb
index c6362e7197..91de6f46f4 100644
--- a/yarp/templates/lib/yarp/node.rb.erb
+++ b/yarp/templates/lib/yarp/node.rb.erb
@@ -182,90 +182,6 @@ module YARP
<%- end -%>
end
- # The dispatcher class fires events for nodes that are found while walking an
- # AST to all registered listeners. It's useful for performing different types
- # of analysis on the AST while only having to walk the tree once.
- #
- # To use the dispatcher, you would first instantiate it and register listeners
- # for the events you're interested in:
- #
- # class OctalListener
- # def on_integer_node_enter(node)
- # if node.octal? && !node.slice.start_with?("0o")
- # warn("Octal integers should be written with the 0o prefix")
- # end
- # end
- # end
- #
- # dispatcher = Dispatcher.new
- # dispatcher.register(listener, :on_integer_node_enter)
- #
- # Then, you can walk any number of trees and dispatch events to the listeners:
- #
- # result = YARP.parse("001 + 002 + 003")
- # dispatcher.dispatch(result.value)
- #
- # Optionally, you can also use `#dispatch_once` to dispatch enter and leave
- # events for a single node without recursing further down the tree. This can
- # be useful in circumstances where you want to reuse the listeners you already
- # have registers but want to stop walking the tree at a certain point.
- #
- # integer = result.value.statements.body.first.receiver.receiver
- # dispatcher.dispatch_once(integer)
- #
- class Dispatcher < Visitor
- # attr_reader listeners: Hash[Symbol, Array[Listener]]
- attr_reader :listeners
-
- def initialize
- @listeners = {}
- end
-
- # Register a listener for one or more events
- #
- # def register: (Listener, *Symbol) -> void
- def register(listener, *events)
- events.each { |event| (listeners[event] ||= []) << listener }
- end
-
- # Walks `root` dispatching events to all registered listeners
- #
- # def dispatch: (Node) -> void
- alias dispatch visit
-
- # Dispatches a single event for `node` to all registered listeners
- #
- # def dispatch_once: (Node) -> void
- def dispatch_once(node)
- node.accept(DispatchOnce.new(listeners))
- end
- <%- nodes.each do |node| -%>
-
- def visit_<%= node.human %>(node)
- listeners[:on_<%= node.human %>_enter]&.each { |listener| listener.on_<%= node.human %>_enter(node) }
- super
- listeners[:on_<%= node.human %>_leave]&.each { |listener| listener.on_<%= node.human %>_leave(node) }
- end
- <%- end -%>
-
- class DispatchOnce < Visitor
- attr_reader :listeners
-
- def initialize(listeners)
- @listeners = listeners
- end
- <%- nodes.each do |node| -%>
-
- def visit_<%= node.human %>(node)
- listeners[:on_<%= node.human %>_enter]&.each { |listener| listener.on_<%= node.human %>_enter(node) }
- listeners[:on_<%= node.human %>_leave]&.each { |listener| listener.on_<%= node.human %>_leave(node) }
- end
- <%- end -%>
- end
-
- private_constant :DispatchOnce
- end
-
module DSL
private
diff --git a/yarp/templates/template.rb b/yarp/templates/template.rb
index 8d02b22231..17cb52a2ff 100755
--- a/yarp/templates/template.rb
+++ b/yarp/templates/template.rb
@@ -366,6 +366,7 @@ module YARP
"java/org/yarp/Loader.java",
"java/org/yarp/Nodes.java",
"java/org/yarp/AbstractNodeVisitor.java",
+ "lib/yarp/dispatcher.rb",
"lib/yarp/mutation_visitor.rb",
"lib/yarp/node.rb",
"lib/yarp/serialize.rb",