-
# frozen_string_literal: true
-
-
1
require "marameters"
-
-
1
module Infusible
-
# Provides the automatic and complete resolution of all injected dependencies.
-
# :reek:TooManyInstanceVariables
-
1
class Builder < Module
-
1
def self.define_instance_variables target, keys, keywords
-
41
else: 4
then: 37
unless target.instance_variable_defined? :@infused_keys
-
37
target.instance_variable_set :@infused_keys, keys
-
end
-
-
41
keys.each do |key|
-
72
else: 70
then: 2
next unless keywords.key?(key) || !target.instance_variable_defined?(:"@#{key}")
-
-
70
target.instance_variable_set :"@#{key}", keywords[key]
-
end
-
end
-
-
1
private_class_method :define_instance_variables
-
-
1
def initialize container, *configuration, scope: :private
-
61
super()
-
-
61
@container = container
-
61
@dependencies = DependencyMap.new(*configuration)
-
61
@scope = scope
-
61
@class_module = Module.new
-
61
@instance_module = Module.new.set_temporary_name "infusible"
-
-
61
freeze
-
end
-
-
1
def included descendant
-
43
else: 42
then: 1
unless descendant.is_a? Class
-
1
fail TypeError,
-
"Can only infuse a class, invalid object: #{descendant} (#{descendant.class})."
-
end
-
-
42
super
-
42
define descendant
-
42
descendant.extend class_module
-
42
descendant.include instance_module
-
end
-
-
1
private
-
-
1
attr_reader :container, :dependencies, :scope, :class_module, :instance_module
-
-
1
def define descendant
-
42
define_new
-
42
define_initialize descendant
-
42
define_readers
-
end
-
-
1
def define_new
-
42
class_module.module_exec container, dependencies.to_h do |container, collection|
-
42
define_method :new do |*positionals, **keywords, &block|
-
113
else: 4
then: 68
collection.each { |name, id| keywords[name] = container[id] unless keywords.key? name }
-
41
super(*positionals, **keywords, &block)
-
end
-
end
-
end
-
-
1
def define_initialize descendant
-
42
super_parameters = Marameters.of(descendant, :initialize).map do |instance|
-
45
else: 3
then: 42
break instance unless instance.only_bare_splats?
-
end
-
-
42
variablizer = self.class.method :define_instance_variables
-
-
42
then: 3
if super_parameters.positionals? || super_parameters.only_single_splats?
-
3
define_initialize_with_positionals super_parameters, variablizer
-
else: 39
else
-
39
define_initialize_with_keywords super_parameters, variablizer
-
end
-
end
-
-
1
def define_initialize_with_positionals super_parameters, variablizer
-
3
instance_module.module_exec dependencies.keys, variablizer do |keys, definer|
-
3
define_method :initialize do |*positionals, **keywords, &block|
-
3
definer.call self, keys, keywords
-
-
3
then: 1
if super_parameters.only_single_splats?
-
1
super(*positionals, **keywords, &block)
-
else: 2
else
-
2
super(*positionals, **super_parameters.keywords_for(*keys, **keywords), &block)
-
end
-
end
-
end
-
end
-
-
1
def define_initialize_with_keywords super_parameters, variablizer
-
39
instance_module.module_exec dependencies.keys, variablizer do |keys, definer|
-
39
define_method :initialize do |**keywords, &block|
-
38
definer.call self, keys, keywords
-
38
super(**super_parameters.keywords_for(*keys, **keywords), &block)
-
end
-
end
-
end
-
-
1
def define_readers
-
116
methods = dependencies.keys.map { |key| ":#{key}" }
-
42
then: 41
else: 1
computed_scope = METHOD_SCOPES.include?(scope) ? scope : :private
-
-
42
instance_module.module_eval <<-READERS, __FILE__, __LINE__ + 1
-
1
attr_reader :infused_keys
-
1
#{computed_scope} attr_reader #{methods.join ", "}
-
READERS
-
end
-
end
-
end