[ruby/prism] Dynamically register events to dispatch
Instead of requiring the consumer to provide a list of all events which they wish to handle, we can give them to option of dynamically detecting them, by scanning the listener's public methods. This approach is similar to that used by Minitest (scanning for `test_` methods) and Rails generators (running all public methods in the order they are defined). While this is slower than specifying a hard coded list, the penalty is only during registration. There is no change the the behaviour of dispatching the events. https://github.com/ruby/prism/commit/781ebed743
This commit is contained in:
parent
de097fbe5f
commit
f07af59a2f
@ -44,6 +44,19 @@ module Prism
|
||||
#
|
||||
# def register: (Listener, *Symbol) -> void
|
||||
def register(listener, *events)
|
||||
register_events(listener, events)
|
||||
end
|
||||
|
||||
# Register all public methods of a listener that match the pattern
|
||||
# `on_<node_name>_(enter|leave)`.
|
||||
#
|
||||
# def register_public_methods: (Listener) -> void
|
||||
def register_public_methods(listener)
|
||||
register_events(listener, listener.public_methods(false).grep(/\Aon_.+_(?:enter|leave)\z/))
|
||||
end
|
||||
|
||||
# Register a listener for the given events.
|
||||
private def register_events(listener, events)
|
||||
events.each { |event| (listeners[event] ||= []) << listener }
|
||||
end
|
||||
|
||||
|
@ -25,9 +25,12 @@ module Prism
|
||||
end
|
||||
|
||||
def test_dispatching_events
|
||||
listener = TestListener.new
|
||||
listener_manual = TestListener.new
|
||||
listener_public = TestListener.new
|
||||
|
||||
dispatcher = Dispatcher.new
|
||||
dispatcher.register(listener, :on_call_node_enter, :on_call_node_leave, :on_integer_node_enter)
|
||||
dispatcher.register(listener_manual, :on_call_node_enter, :on_call_node_leave, :on_integer_node_enter)
|
||||
dispatcher.register_public_methods(listener_public)
|
||||
|
||||
root = Prism.parse(<<~RUBY).value
|
||||
def foo
|
||||
@ -36,11 +39,17 @@ module Prism
|
||||
RUBY
|
||||
|
||||
dispatcher.dispatch(root)
|
||||
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)
|
||||
|
||||
[listener_manual, listener_public].each do |listener|
|
||||
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)
|
||||
listener.events_received.clear
|
||||
end
|
||||
|
||||
dispatcher.dispatch_once(root.statements.body.first.body.body.first)
|
||||
|
||||
[listener_manual, listener_public].each do |listener|
|
||||
assert_equal([:on_call_node_enter, :on_call_node_leave], listener.events_received)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user