Skip to content

Commit 640b1e7

Browse files
authored
Merge pull request #3490 from sambostock/dynamic-dispatch
Dynamically register events to dispatch
2 parents 69dbc41 + 781ebed commit 640b1e7

File tree

3 files changed

+30
-5
lines changed

3 files changed

+30
-5
lines changed

sig/prism/dispatcher.rbs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ module Prism
44

55
def initialize: () -> void
66
def register: (untyped, *Symbol) -> void
7+
def register_public_methods: (untyped) -> void
78
def dispatch: (Prism::node) -> void
89
def dispatch_once: (Prism::node) -> void
910

11+
private def register_events: (untyped, Array[Symbol]) -> void
12+
1013
class DispatchOnce < Visitor
1114
attr_reader listeners: Hash[Symbol, Array[untyped]]
1215

templates/lib/prism/dispatcher.rb.erb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,19 @@ module Prism
4444
#
4545
# def register: (Listener, *Symbol) -> void
4646
def register(listener, *events)
47+
register_events(listener, events)
48+
end
49+
50+
# Register all public methods of a listener that match the pattern
51+
# `on_<node_name>_(enter|leave)`.
52+
#
53+
# def register_public_methods: (Listener) -> void
54+
def register_public_methods(listener)
55+
register_events(listener, listener.public_methods(false).grep(/\Aon_.+_(?:enter|leave)\z/))
56+
end
57+
58+
# Register a listener for the given events.
59+
private def register_events(listener, events)
4760
events.each { |event| (listeners[event] ||= []) << listener }
4861
end
4962

test/prism/ruby/dispatcher_test.rb

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@ def on_integer_node_enter(node)
2525
end
2626

2727
def test_dispatching_events
28-
listener = TestListener.new
28+
listener_manual = TestListener.new
29+
listener_public = TestListener.new
30+
2931
dispatcher = Dispatcher.new
30-
dispatcher.register(listener, :on_call_node_enter, :on_call_node_leave, :on_integer_node_enter)
32+
dispatcher.register(listener_manual, :on_call_node_enter, :on_call_node_leave, :on_integer_node_enter)
33+
dispatcher.register_public_methods(listener_public)
3134

3235
root = Prism.parse(<<~RUBY).value
3336
def foo
@@ -36,11 +39,17 @@ def foo
3639
RUBY
3740

3841
dispatcher.dispatch(root)
39-
assert_equal([:on_call_node_enter, :on_integer_node_enter, :on_integer_node_enter, :on_integer_node_enter, :on_call_node_leave], listener.events_received)
4042

41-
listener.events_received.clear
43+
[listener_manual, listener_public].each do |listener|
44+
assert_equal([:on_call_node_enter, :on_integer_node_enter, :on_integer_node_enter, :on_integer_node_enter, :on_call_node_leave], listener.events_received)
45+
listener.events_received.clear
46+
end
47+
4248
dispatcher.dispatch_once(root.statements.body.first.body.body.first)
43-
assert_equal([:on_call_node_enter, :on_call_node_leave], listener.events_received)
49+
50+
[listener_manual, listener_public].each do |listener|
51+
assert_equal([:on_call_node_enter, :on_call_node_leave], listener.events_received)
52+
end
4453
end
4554
end
4655
end

0 commit comments

Comments
 (0)