Skip to content

Instantly share code, notes, and snippets.

@pocke
Created January 3, 2020 13:45
Show Gist options
  • Save pocke/780ccfe41fbd03bfd2bb93c3a7c5ec36 to your computer and use it in GitHub Desktop.
Save pocke/780ccfe41fbd03bfd2bb93c3a7c5ec36 to your computer and use it in GitHub Desktop.
diff --git a/lib/ruby/signature/test/hook.rb b/lib/ruby/signature/test/hook.rb
index ef0cc31..4b05887 100644
--- a/lib/ruby/signature/test/hook.rb
+++ b/lib/ruby/signature/test/hook.rb
@@ -19,6 +19,7 @@ module Ruby
INSTANCE_EVAL = BasicObject.instance_method(:instance_eval)
INSTANCE_EXEC = BasicObject.instance_method(:instance_exec)
METHOD = Kernel.instance_method(:method)
+ INSTANCE_METHOD = Module.method(:instance_method).unbind
CLASS = Kernel.instance_method(:class)
SINGLETON_CLASS = Kernel.instance_method(:singleton_class)
PP = Kernel.instance_method(:pp)
@@ -189,10 +190,23 @@ module Ruby
self
end
- def delegation(name, method_types, method_name)
+ def delegation(method, name, method_types, method_name)
+ body = delegation_body(name, method_types, method_name)
hook = self
+ if method.parameters.any? { |t, _name| %i[keyreq key keyrest].include?(t) }
+ proc do |*args, **kwargs, &block|
+ hook.call self, hook.class::INSTANCE_EXEC, args, kwargs, block, &body
+ end
+ else
+ proc do |*args, &block|
+ hook.call self, hook.class::INSTANCE_EXEC, args, nil, block, &body
+ end
+ end
+ end
- proc do |*args, &block|
+ def delegation_body(name, method_types, method_name)
+ hook = self
+ proc do |args, kwargs, block|
hook.logger.debug { "#{method_name} receives arguments: #{hook.inspect_(args)}" }
block_calls = []
@@ -228,10 +242,19 @@ module Ruby
end
prepended = klass.ancestors.include?(hook.instance_module) || singleton_klass&.ancestors&.include?(hook.singleton_module)
result = if prepended
- method.super_method.call(*args, &block)
+ if kwargs
+ method.super_method.call(*args, **kwargs, &block)
+ else
+ method.super_method.call(*args, &block)
+ end
else
# Using refinement
- method.call(*args, &block)
+ if kwargs
+ method.call(*args, **kwargs, &block)
+ else
+ p [method, args]
+ method.call(*args, &block)
+ end
end
hook.logger.debug { "#{method_name} returns: #{hook.inspect_(result)}" }
@@ -305,9 +328,21 @@ module Ruby
case
when instance_method
instance_methods << instance_method
- call(self.instance_module, DEFINE_METHOD, instance_method, &delegation(instance_method, method_types, "##{instance_method}"))
+ method =
+ begin
+ self.call(klass, INSTANCE_METHOD, instance_method)
+ rescue NameError
+ return self
+ end
+ call(self.instance_module, DEFINE_METHOD, instance_method, &delegation(method, instance_method, method_types, "##{instance_method}"))
when singleton_method
- call(self.singleton_module, DEFINE_METHOD, singleton_method, &delegation(singleton_method, method_types, ".#{singleton_method}"))
+ method =
+ begin
+ self.call(klass, METHOD, singleton_method)
+ rescue NameError
+ return self
+ end
+ call(self.singleton_module, DEFINE_METHOD, singleton_method, &delegation(method, singleton_method, method_types, ".#{singleton_method}"))
end
self
@@ -375,8 +410,8 @@ module Ruby
disable
end
- def call(receiver, method, *args, &block)
- method.bind(receiver).call(*args, &block)
+ def call(receiver, method, *args, **kwargs, &block)
+ method.bind(receiver).call(*args, **kwargs, &block)
end
def inspect_(obj)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment