diff --git a/lib/rbs/test/hook.rb b/lib/rbs/test/hook.rb index ed6026a13..e5c2d1b03 100644 --- a/lib/rbs/test/hook.rb +++ b/lib/rbs/test/hook.rb @@ -96,50 +96,55 @@ def #{with_name}(#{param_source.join(", ")}, &#{block_param}) block_calls = [] if block_given? - receiver = self block_receives_block = #{block_param}.parameters.last&.yield_self {|type, _| type == :block } - wrapped_block = proc do |*block_args, &block2| - return_from_block = false - - begin - block_result = if receiver.equal?(self) - if block_receives_block - #{block_param}.call(*block_args, &block2) - else - yield(*block_args) - end - else - instance_exec(*block_args, &#{block_param}) - end - - return_from_block = true - ensure - exn = $! - - case - when return_from_block - # Returned from yield - block_calls << ::RBS::Test::ArgumentsReturn.return( - arguments: block_args, - value: block_result - ) - when exn - # Exception - block_calls << ::RBS::Test::ArgumentsReturn.exception( - arguments: block_args, - exception: exn - ) - else - # break? - block_calls << ::RBS::Test::ArgumentsReturn.break( - arguments: block_args - ) + wrapped_block = Object.new.instance_exec do + new_object = self + + proc do |*block_args, &block2| + return_from_block = false + + begin + block_result = if self.equal?(new_object) + if block_receives_block + #{block_param}.call(*block_args, &block2) + else + yield(*block_args) + end + else + # Detected that `self` inside `proc` is not equal to the `self` outside block (which is saved to `new_object`). + # This means that the block is called with `instance_exec` or `instance_eval`. + self.instance_exec(*block_args, &#{block_param}) + end + + return_from_block = true + ensure + exn = $! + + case + when return_from_block + # Returned from yield + block_calls << ::RBS::Test::ArgumentsReturn.return( + arguments: block_args, + value: block_result + ) + when exn + # Exception + block_calls << ::RBS::Test::ArgumentsReturn.exception( + arguments: block_args, + exception: exn + ) + else + # break? + block_calls << ::RBS::Test::ArgumentsReturn.break( + arguments: block_args + ) + end end - end - block_result - end.ruby2_keywords + block_result + end.ruby2_keywords + end result = __send__(:"#{without_name}", *args, &wrapped_block) else diff --git a/test/rbs/test/runtime_test_test.rb b/test/rbs/test/runtime_test_test.rb index ddd4e0cc9..d1735af1a 100644 --- a/test/rbs/test/runtime_test_test.rb +++ b/test/rbs/test/runtime_test_test.rb @@ -358,6 +358,66 @@ def test_String ruby_content: < "::Base,::DSL::ParameterBuilder" }, + rbs_content: < void } -> void + + def self.parameter_builder: () -> DSL::ParameterBuilder +end + +module DSL + class ParameterBuilder + def define: (Symbol) ?{ () [self: self] -> void } -> self + + def build!: () -> void + + def description: (String) -> void + + alias desc description + end +end +RBS +class Base + class << self + def parameter(parameter_name, &) + parameter_builder.define(parameter_name, &).build! + end + + private + + def parameter_builder + @parameter_builder ||= DSL::ParameterBuilder.new() + end + end +end + +module DSL + class ParameterBuilder + def define(parameter_name, &) + instance_exec(&) if block_given? + self + end + + def build! + end + + def description(description_string) + self + end + alias desc description + end +end + +Base.parameter(:foo) do + desc "Some message here" +end RUBY ) end