66 lines
1.6 KiB
Ruby
66 lines
1.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module ActiveSupport
|
|
class CodeGenerator # :nodoc:
|
|
class MethodSet
|
|
METHOD_CACHES = Hash.new { |h, k| h[k] = Module.new }
|
|
|
|
def initialize(namespace)
|
|
@cache = METHOD_CACHES[namespace]
|
|
@sources = []
|
|
@methods = {}
|
|
end
|
|
|
|
def define_cached_method(name, as: name)
|
|
name = name.to_sym
|
|
as = as.to_sym
|
|
@methods.fetch(name) do
|
|
unless @cache.method_defined?(as)
|
|
yield @sources
|
|
end
|
|
@methods[name] = as
|
|
end
|
|
end
|
|
|
|
def apply(owner, path, line)
|
|
unless @sources.empty?
|
|
@cache.module_eval("# frozen_string_literal: true\n" + @sources.join(";"), path, line)
|
|
end
|
|
@methods.each do |name, as|
|
|
owner.define_method(name, @cache.instance_method(as))
|
|
end
|
|
end
|
|
end
|
|
|
|
class << self
|
|
def batch(owner, path, line)
|
|
if owner.is_a?(CodeGenerator)
|
|
yield owner
|
|
else
|
|
instance = new(owner, path, line)
|
|
result = yield instance
|
|
instance.execute
|
|
result
|
|
end
|
|
end
|
|
end
|
|
|
|
def initialize(owner, path, line)
|
|
@owner = owner
|
|
@path = path
|
|
@line = line
|
|
@namespaces = Hash.new { |h, k| h[k] = MethodSet.new(k) }
|
|
end
|
|
|
|
def define_cached_method(name, namespace:, as: name, &block)
|
|
@namespaces[namespace].define_cached_method(name, as: as, &block)
|
|
end
|
|
|
|
def execute
|
|
@namespaces.each_value do |method_set|
|
|
method_set.apply(@owner, @path, @line - 1)
|
|
end
|
|
end
|
|
end
|
|
end
|