diff --git a/lib/rbs/test/hook.rb b/lib/rbs/test/hook.rb index c6cfa1f45..e29835c20 100644 --- a/lib/rbs/test/hook.rb +++ b/lib/rbs/test/hook.rb @@ -81,13 +81,18 @@ def #{with_name}(*args, &block) if block_given? receiver = self + block_receives_block = block.parameters.last&.yield_self {|type, _| type == :block } - wrapped_block = proc do |*block_args| + wrapped_block = proc do |*block_args, &block2| return_from_block = false begin block_result = if receiver.equal?(self) - yield(*block_args) + if block_receives_block + block.call(*block_args, &block2) + else + yield(*block_args) + end else instance_exec(*block_args, &block) end diff --git a/test/rbs/test/runtime_test_test.rb b/test/rbs/test/runtime_test_test.rb index 924e0cf31..8ee251e7f 100644 --- a/test/rbs/test/runtime_test_test.rb +++ b/test/rbs/test/runtime_test_test.rb @@ -264,6 +264,43 @@ def call(val, &block) end A.new.call("foo") {|value:| puts value } +RUBY + end + + def test_method_callbacks + assert_test_success(other_env: { 'RBS_TEST_TARGET' => "Callbacks" }, rbs_content: < void } -> void + def emit: (Symbol event, *untyped args) ?{ (*untyped) -> void } -> void +end +RBS +module Callbacks + def on(e, &block) + (@callbacks[e] ||= []) << block + end + + def emit(e, *args, &block) + @callbacks[e].each do |callable| + callable.call(*args, &block) + end + end +end + +class A + def initialize + @callbacks = {} + end + + include Callbacks + + def bar(&block) + emit(:bar, &block) + end +end + +a = A.new +a.on(:bar) { |*args, &block| puts "bar: #{args}"; block.call(self) } +a.emit(:bar, 1, 2) { |a| "this is A: #{a}" } RUBY end end