Module: InternalApi::Rewriter

Extended by:
Rewriter
Included in:
Rewriter
Defined in:
lib/internal_api/rewriter.rb

Overview

This uses the built-in Ruby callbacks for when new methods are defined: github.com/ruby/ruby/blob/c3cf1ef9bbacac6ae5abc99046db173e258dc7ca/object.c#L940-L954

Constant Summary collapse

SKIP_PATTERN =

rubocop:disable Metrics/MethodLength

/(^_internal_api)|(^(singleton_)?method_added$)/.freeze

Instance Method Summary collapse

Instance Method Details

#add_instance_rewrite_hooks!(protectee, protector) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/internal_api/rewriter.rb', line 11

def add_instance_rewrite_hooks!(protectee, protector)
  protectee.class_eval do
    define_method(:method_added) do |method_name|
      return unless InternalApi::Rewriter.should_overwrite?(
        method_name,
        instance_methods,
        public_instance_methods
      )

      InternalApi.debug "#{self}##{method_name} protected by #{protector}"
      InternalApi.rewrite_method!(self, method_name, protector)
    end
  end
end

#add_singleton_rewrite_hooks!(protectee, protector) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/internal_api/rewriter.rb', line 26

def add_singleton_rewrite_hooks!(protectee, protector)
  protectee.class_eval do
    define_method(:singleton_method_added) do |method_name|
      return unless InternalApi::Rewriter.should_overwrite?(
        method_name,
        methods,
        public_methods
      )

      eigen = (class << self; self; end)
      InternalApi.debug "#{eigen}.#{method_name} protected by #{protector}"
      InternalApi.rewrite_method!(eigen, method_name, protector)
    end
  end
end

#should_overwrite?(method_name, methods, public_methods) ⇒ Boolean

rubocop:enable Metrics/MethodLength

Returns:

  • (Boolean)


43
44
45
46
47
48
49
50
# File 'lib/internal_api/rewriter.rb', line 43

def should_overwrite?(method_name, methods, public_methods)
  # Don't interfere with the metaprogramming
  return false if method_name.to_s =~ SKIP_PATTERN
  # And definitely don't try to do this twice
  return false if methods.include?("_internal_api_#{method_name}".to_sym)

  public_methods.include?(method_name)
end