Module: SuperModule::V1::SingletonMethodDefinitionStore

Defined in:
lib/super_module/v1/singleton_method_definition_store.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(base) ⇒ Object



106
107
108
109
110
111
112
# File 'lib/super_module/v1/singleton_method_definition_store.rb', line 106

def self.extended(base)
  base.extend(SuperModule::V1::ModuleBodyMethodCallRecorder) unless base.is_a?(SuperModule::V1::ModuleBodyMethodCallRecorder)
  base.singleton_method_added(:__method_signature)
  base.singleton_method_added(:__record_method_call)
  base.singleton_method_added(:__inside_super_module_included?)
  base.singleton_method_added(:__inside_super_module_included=)
end

Instance Method Details

#__all_methods(object) ⇒ Object



48
49
50
# File 'lib/super_module/v1/singleton_method_definition_store.rb', line 48

def __all_methods(object)
  object.public_methods + object.protected_methods + object.private_methods
end

#__build_singleton_method_body_source(method_name) ⇒ Object



72
73
74
75
76
77
78
79
80
81
# File 'lib/super_module/v1/singleton_method_definition_store.rb', line 72

def __build_singleton_method_body_source(method_name)
  the_method = self.method(method_name)
  method_body = the_method.source
  method_original_name = the_method.original_name
  aliased = method_original_name != method_name
  method_args = __singleton_method_args(method_original_name, method_body)
  method_body = "def #{method_name}\n#{method_body}\nend" if method_args.nil?
  class_self_method_def_enclosure = "class << self\n#{__singleton_method_access_level(method_name)}\ndef #{method_name}(#{method_args})\n#{__singleton_method_call_recorder(method_name, method_args)}\n"
  method_body.sub(__singleton_method_definition_regex(method_original_name), class_self_method_def_enclosure) + "\nend\n"
end

#__overwrite_singleton_method_from_current_super_module(method_name, method_body) ⇒ Object



88
89
90
91
92
93
# File 'lib/super_module/v1/singleton_method_definition_store.rb', line 88

def __overwrite_singleton_method_from_current_super_module(method_name, method_body)
  if __super_module_having_method(method_name).nil?
    __super_module_singleton_methods_excluded_from_base_definition << method_name
    class_eval(method_body)
  end
end

#__singleton_method_access_level(method_name) ⇒ Object



65
66
67
68
69
70
# File 'lib/super_module/v1/singleton_method_definition_store.rb', line 65

def __singleton_method_access_level(method_name)
  %w(private protected public).detect do |method_access|
    method_group = "#{method_access}_methods"
    send(method_group).map(&:to_s).include?(method_name.to_s)
  end
end

#__singleton_method_args(method_name, method_body) ⇒ Object



61
62
63
# File 'lib/super_module/v1/singleton_method_definition_store.rb', line 61

def __singleton_method_args(method_name, method_body)
  method_body.match(__singleton_method_definition_regex(method_name)).to_a[5]
end

#__singleton_method_body(method_name) ⇒ Object



83
84
85
86
# File 'lib/super_module/v1/singleton_method_definition_store.rb', line 83

def __singleton_method_body(method_name)
    super_module_having_method = __super_module_having_method(method_name)
    super_module_having_method ? __singleton_method_body_for(super_module_having_method, method_name) : __build_singleton_method_body_source(method_name)
end

#__singleton_method_body_for(super_module, method_name) ⇒ Object



40
41
42
# File 'lib/super_module/v1/singleton_method_definition_store.rb', line 40

def __singleton_method_body_for(super_module, method_name)
  super_module.__super_module_singleton_methods.detect {|sm_method_name, sm_method_body| sm_method_name == method_name}[1]
end

#__singleton_method_definition_regex(method_name) ⇒ Object



56
57
58
59
# File 'lib/super_module/v1/singleton_method_definition_store.rb', line 56

def __singleton_method_definition_regex(method_name)
  method_name = Regexp.escape(method_name.to_s)
  /(public|protected|private)?(send)?[ \t(:"']*def(ine_method)?[ \t,:"']+(self\.)?#{method_name}\)?[ \tdo{(|]*([^\n)|;]*)?[ \t)|;]*/m
end

#__super_module_having_method(method_name) ⇒ Object



52
53
54
# File 'lib/super_module/v1/singleton_method_definition_store.rb', line 52

def __super_module_having_method(method_name)
  included_super_modules.detect {|included_super_module| __all_methods(included_super_module).map(&:to_s).include?(method_name.to_s)}
end

#__super_module_singleton_methodsObject



36
37
38
# File 'lib/super_module/v1/singleton_method_definition_store.rb', line 36

def __super_module_singleton_methods
  @__super_module_singleton_methods ||= []
end

#__super_module_singleton_methods_excluded_from_base_definitionObject

excluded list of singleton methods to define (perhaps give a better name)



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/super_module/v1/singleton_method_definition_store.rb', line 8

def __super_module_singleton_methods_excluded_from_base_definition
  @__super_module_singleton_methods_excluded_from_base_definition ||= [
    :__all_module_body_method_calls_in_definition_order,
    :__build_singleton_method_body_source,
    :__define_super_module_singleton_methods,
    :__invoke_module_body_method_calls,
    :__module_body_method_calls,
    :__overwrite_singleton_method_from_current_super_module,
    :__singleton_method_args,
    :__singleton_method_body,
    :__singleton_method_body_for,
    :__singleton_method_call_recorder,
    :__singleton_method_definition_regex,
    :__super_module_having_method,
    :__super_module_singleton_methods,
    :__super_module_singleton_methods_excluded_from_base_definition,
    :__super_module_singleton_methods_excluded_from_call_recording,
    :class_eval,
    :dbg_print, #debugger library friendly exclusion
    :dbg_puts, #debugger library friendly exclusion
    :define,
    :included,
    :super_module_included,
    :included_super_modules,
    :singleton_method_added,
  ]
end

#included_super_modulesObject



44
45
46
# File 'lib/super_module/v1/singleton_method_definition_store.rb', line 44

def included_super_modules
  included_modules.select {|m| m.include?(SuperModule)}
end

#singleton_method_added(method_name) ⇒ Object



95
96
97
98
99
100
101
102
103
104
# File 'lib/super_module/v1/singleton_method_definition_store.rb', line 95

def singleton_method_added(method_name)
  if method_name.to_s == 'included' && !method(method_name).source_location.first.include?('super_module/v1')
    raise 'Do not implement "self.included(base)" hook for a super module! Use "super_module_included {|base| ... }" instead.'
  end
  unless __super_module_singleton_methods_excluded_from_base_definition.include?(method_name)
    method_body = __singleton_method_body(method_name)
    __super_module_singleton_methods << [method_name, method_body]
    __overwrite_singleton_method_from_current_super_module(method_name, method_body)
  end
end