- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
require "marameters"
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Initable
           
        
      
        
          
- 
            
            
              
            
            
  # Builds initialization behavior.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  class Builder < Module
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def initialize *parameters, method_scope: :private, **keywords
           
        
      
        
          
- 
            
              57
            
            
              
            
            
      super()
           
        
      
        
          
- 
            
              70
            
            
              
            
            
      keywords.each { |key, value| parameters.push [:key, key, value] }
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              57
            
            
              
            
            
      @parameters = Marameters.for parameters
           
        
      
        
          
- 
            
              57
            
            
              
            
            
      @method_scope = method_scope
           
        
      
        
          
- 
            
              57
            
            
              
            
            
      @names = @parameters.names.compact
           
        
      
        
          
- 
            
              57
            
            
              
            
            
      @instance_module = Module.new.set_temporary_name "initable"
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              57
            
            
              
            
            
      freeze
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def included descendant
           
        
      
        
          
- 
            
              57
            
            
              
            
            
      super
           
        
      
        
          
- 
            
              57
            
            
              
            
            
      define_initialize descendant
           
        
      
        
          
- 
            
              57
            
            
              
            
            
      descendant.include instance_module
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    private
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    attr_reader :method_scope, :parameters, :names, :instance_module
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def define_initialize descendant,
           
        
      
        
          
- 
            
            
              
            
            
                          inheritor: Marameters::Signatures::Inheritor.new,
           
        
      
        
          
- 
            
            
              
            
            
                          forwarder: Marameters::Signatures::Super.new
           
        
      
        
          
- 
            
              57
            
            
              
            
            
      ancestor = Marameters.of(descendant, :initialize).first
           
        
      
        
          
- 
            
              114
            
            
              
            
            
      signature = inheritor.call(ancestor, parameters).then { |params| Marameters.signature params }
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              57
            
            
              
            
            
      instance_module.module_eval <<-METHOD, __FILE__, __LINE__ + 1
           
        
      
        
          
- 
            
              1
            
            
              
            
            
        def initialize(#{signature})
           
        
      
        
          
- 
            
              1
            
            
              
            
            
          #{build_instance_variables ancestor}
           
        
      
        
          
- 
            
              1
            
            
              
            
            
          super(#{forwarder.call ancestor, parameters})
           
        
      
        
          
- 
            
              1
            
            
              
            
            
        end
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      METHOD
           
        
      
        
          
- 
            
              1
            
            
              
            
            
           
        
      
        
          
- 
            
              10
            
            
              
            
            
      define_readers ancestor
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    end
           
        
      
        
          
- 
            
              1
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def build_instance_variables ancestor
           
        
      
        
          
- 
            
              154
            
            
              
            
            
      (names - ancestor.names).map { |name| "@#{name} = #{name}" }
           
        
      
        
          
- 
            
            
              
            
            
                              .join "\n"
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def define_readers ancestor
           
        
      
        
          
- 
            
              57
            
            
              
            
            
      instance_module.module_eval <<-READERS, __FILE__, __LINE__ + 1
           
        
      
        
          
- 
            
              1
            
            
              
            
            
        #{compute_scope} attr_reader(*#{names - ancestor.names})
           
        
      
        
          
- 
            
            
              
            
            
      READERS
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              58
            
            
              
                
                  then: 54
                
              
                
                  else: 3
                
              
            
            
    def compute_scope = METHOD_SCOPES.include?(method_scope) ? method_scope : :private
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end