Created
January 3, 2020 13:45
-
-
Save pocke/780ccfe41fbd03bfd2bb93c3a7c5ec36 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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