All Files
    (
      
  100.0%
     
     covered at
     
       
         21.31
       
     hits/line
    )
  
  
  
    16 files in total.
  
  
    272 relevant lines,
    272 lines covered and
    0 lines missed. 
    (
  100.0%
)
  
  
    
      88 total branches, 
      88 branches covered and
      0 branches missed.
      (
  100.0%
)
    
  
  
 
        
       
      
      
      
        
  
  
    
      
        
          
- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
require "zeitwerk"
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
Zeitwerk::Loader.new.then do |loader|
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  loader.tag = File.basename __FILE__, ".rb"
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  loader.push_dir __dir__
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  loader.setup
           
        
      
        
          
- 
            
            
              
            
            
end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
            
              
            
            
# Main namespace.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Marameters
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  KINDS = %i[req opt rest nokey keyreq key keyrest block].freeze
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  def self.loader registry = Zeitwerk::Registry
           
        
      
        
          
- 
            
              4
            
            
              
            
            
    @loader ||= registry.loaders.each.find { |loader| loader.tag == File.basename(__FILE__, ".rb") }
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  def self.categorize parameters, arguments
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    @categorize ||= Categorizer.new
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    @categorize.call parameters, arguments
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  def self.of(...) = Probe.of(...)
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  def self.for(...) = Probe.new(...)
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  def self.signature(...) = Signature.new(...)
           
        
      
        
          
- 
            
            
              
            
            
end
           
        
      
    
  
 
      
        
  
  
    
      
        
          
- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Marameters
           
        
      
        
          
- 
            
            
              
            
            
  # Builds the primary argument categories based on method parameters and arguments.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  class Categorizer
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def initialize model: Models::Forward
           
        
      
        
          
- 
            
              29
            
            
              
            
            
      @model = model
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def call parameters, arguments
           
        
      
        
          
- 
            
              29
            
            
              
            
            
      @record = model.new
           
        
      
        
          
- 
            
              29
            
            
              
                
                  then: 28
                
              
                
                  else: 1
                
              
            
            
      map parameters, arguments.is_a?(Array) ? arguments : [arguments]
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    private
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    attr_reader :model, :record
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def map parameters, arguments
           
        
      
        
          
- 
            
              29
            
            
              
            
            
      size = arguments.size
           
        
      
        
          
- 
            
              130
            
            
              
                
                  then: 73
                
              
                
                  else: 28
                
              
            
            
      parameters.each.with_index { |pair, index| filter pair, arguments[index] if index < size }
           
        
      
        
          
- 
            
              27
            
            
              
            
            
      record
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def filter pair, value
           
        
      
        
          
- 
            
              73
            
            
              
                
                  in: 10
                
              
            
            
      case pair
           
        
      
        
          
- 
            
              10
            
            
              
                
                  in: 6
                
              
            
            
        in [:rest] | [:rest, :*] then to_array value
           
        
      
        
          
- 
            
              6
            
            
              
                
                  in: 16
                
              
            
            
        in [:keyrest] | [:keyrest, :**] then record.keywords = Hash value
           
        
      
        
          
- 
            
              16
            
            
              
                
                  in: 10
                
              
            
            
        in [:req, *] | [:opt, *] then record.positionals.append value
           
        
      
        
          
- 
            
              10
            
            
              
                
                  in: 2
                
              
            
            
        in [:rest, *] then record.positionals.append(*value)
           
        
      
        
          
- 
            
              2
            
            
              
                
                  in: 11
                
              
            
            
        in [:nokey] then nil
           
        
      
        
          
- 
            
              11
            
            
              
                
                  in: 6
                
              
                
                  then: 9
                
              
                
                  else: 2
                
              
            
            
        in [:keyreq, *] | [:key, *] then record.keywords.merge! value if value
           
        
      
        
          
- 
            
              6
            
            
              
                
                  in: 11
                
              
                
                  then: 4
                
              
                
                  else: 2
                
              
            
            
        in [:keyrest, *] then record.keywords.merge!(**value) if value
           
        
      
        
          
- 
            
              11
            
            
              
                
                  else: 1
                
              
            
            
        in [:block, *] then record.block = value
           
        
      
        
          
- 
            
              1
            
            
              
            
            
        else fail ArgumentError, "Invalid parameter kind: #{pair.first.inspect}."
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
    rescue TypeError
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      raise TypeError, "#{value.inspect} is an invalid #{pair.first.inspect} value."
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def to_array value
           
        
      
        
          
- 
            
              10
            
            
              
                
                  else: 7
                
              
                
                  then: 3
                
              
            
            
      return unless value
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              7
            
            
              
                
                  then: 5
                
              
                
                  else: 2
                
              
            
            
      record.positionals = value.is_a?(Array) ? value : [value]
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end
           
        
      
    
  
 
      
        
  
  
    
      
        
          
- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Marameters
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  module Models
           
        
      
        
          
- 
            
            
              
            
            
    # Models arguments, by category, for forwarding.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    Forward = Struct.new :positionals, :keywords, :block do
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def initialize(positionals: [], keywords: {}, block: nil) = super
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end
           
        
      
    
  
 
      
        
  
  
    
      
        
          
- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
require "forwardable"
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Marameters
           
        
      
        
          
- 
            
            
              
            
            
  # Provides information on a method's parameters.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  class Probe
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    extend Forwardable
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    CATEGORIES = {positionals: %i[req opt], keywords: %i[keyreq key]}.freeze
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def self.of klass, name, collection: []
           
        
      
        
          
- 
            
              6
            
            
              
            
            
      method = klass.instance_method name
           
        
      
        
          
- 
            
              5
            
            
              
            
            
      collection << new(method.parameters)
           
        
      
        
          
- 
            
              5
            
            
              
            
            
      super_method = method.super_method
           
        
      
        
          
- 
            
              5
            
            
              
            
            
      of super_method.owner, super_method.name, collection:
           
        
      
        
          
- 
            
            
              
            
            
    rescue NameError
           
        
      
        
          
- 
            
              5
            
            
              
            
            
      collection
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    delegate %i[any? deconstruct empty? hash include? inspect to_a] => :parameters
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    attr_reader :keywords, :positionals
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def initialize parameters, categories: CATEGORIES
           
        
      
        
          
- 
            
              170
            
            
              
            
            
      @parameters = parameters
           
        
      
        
          
- 
            
              510
            
            
              
            
            
      categories.each { |category, kinds| define_variable category, kinds }
           
        
      
        
          
- 
            
              170
            
            
              
            
            
      freeze
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def ==(other) = hash == other.hash
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    alias eql? ==
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def <=>(other) = to_a <=> other.to_a
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def keywords? = keywords.any?
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def keywords_for(*keys, **attributes)
           
        
      
        
          
- 
            
              9
            
            
              
            
            
      attributes.select { |key| !keys.include?(key) || keywords.include?(key) }
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              36
            
            
              
            
            
    def kind?(value) = parameters.any? { |kind, _name| kind == value }
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              8
            
            
              
            
            
    def kinds = parameters.map { |kind, _name| kind }
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              66
            
            
              
            
            
    def name?(value) = parameters.any? { |_kind, name| name == value }
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              15
            
            
              
            
            
    def names = parameters.map { |_kind, name| name }
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def only_bare_splats?
           
        
      
        
          
- 
            
              10
            
            
              
            
            
      parameters in [[:rest]] \
           
        
      
        
          
- 
            
            
              
            
            
                    | [[:rest, :*]] \
           
        
      
        
          
- 
            
            
              
            
            
                    | [[:keyrest]] \
           
        
      
        
          
- 
            
            
              
            
            
                    | [[:keyrest, :**]] \
           
        
      
        
          
- 
            
            
              
            
            
                    | [[:rest], [:keyrest]] \
           
        
      
        
          
- 
            
            
              
            
            
                    | [[:rest, :*], [:keyrest, :**]]
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              8
            
            
              
            
            
    def only_double_splats? = (parameters in [[:keyrest]] | [[:keyrest, *]])
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              9
            
            
              
            
            
    def only_single_splats? = (parameters in [[:rest]] | [[:rest, *]])
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def positionals? = positionals.any?
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def positionals_and_maybe_keywords?
           
        
      
        
          
- 
            
              42
            
            
              
            
            
      (positionals? && !keywords?) || (positionals? && keywords?)
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    private
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    attr_reader :parameters
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def define_variable category, kinds
           
        
      
        
          
- 
            
              1304
            
            
              
                
                  then: 276
                
              
                
                  else: 688
                
              
            
            
      parameters.filter_map { |kind, name| next name if kinds.include? kind }
           
        
      
        
          
- 
            
              340
            
            
              
            
            
                .then { |collection| instance_variable_set :"@#{category}", collection }
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end
           
        
      
    
  
 
      
        
  
  
    
      
        
          
- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Marameters
           
        
      
        
          
- 
            
            
              
            
            
  # Builds a method's parameter signature.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  class Signature
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def initialize parameters, builder: Signatures::Builder.new
           
        
      
        
          
- 
            
              46
            
            
              
            
            
      @parameters = parameters
           
        
      
        
          
- 
            
              46
            
            
              
            
            
      @builder = builder
           
        
      
        
          
- 
            
              46
            
            
              
            
            
      freeze
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              46
            
            
              
                
                  then: 2
                
              
                
                  else: 43
                
              
            
            
    def to_s = parameters == :all ? "..." : build.join(", ")
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    alias to_str to_s
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    private
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    attr_reader :parameters, :builder
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    def build
           
        
      
        
          
- 
            
              43
            
            
              
            
            
      parameters.reduce [] do |signature, (kind, name, default)|
           
        
      
        
          
- 
            
              59
            
            
              
            
            
        signature << builder.call(kind, name, default:)
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end
           
        
      
    
  
 
      
        
  
  
    
      
        
          
- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Marameters
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  module Signatures
           
        
      
        
          
- 
            
            
              
            
            
    # Builds a single parameter for a method's signature.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    class Builder
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def initialize defaulter: Defaulter
           
        
      
        
          
- 
            
              60
            
            
              
            
            
        @defaulter = defaulter
           
        
      
        
          
- 
            
              60
            
            
              
            
            
        freeze
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def call kind, name = nil, default: nil
           
        
      
        
          
- 
            
              72
            
            
              
                
                  when: 6
                
              
            
            
        case kind
           
        
      
        
          
- 
            
              6
            
            
              
                
                  when: 15
                
              
            
            
          when :req then name
           
        
      
        
          
- 
            
              15
            
            
              
                
                  when: 9
                
              
            
            
          when :opt then "#{name} = #{defaulter.call default}"
           
        
      
        
          
- 
            
              9
            
            
              
                
                  when: 3
                
              
            
            
          when :rest then "*#{name}"
           
        
      
        
          
- 
            
              3
            
            
              
                
                  when: 6
                
              
            
            
          when :nokey then "**nil"
           
        
      
        
          
- 
            
              6
            
            
              
                
                  when: 13
                
              
            
            
          when :keyreq then "#{name}:"
           
        
      
        
          
- 
            
              13
            
            
              
                
                  when: 9
                
              
            
            
          when :key then "#{name}: #{defaulter.call default}"
           
        
      
        
          
- 
            
              9
            
            
              
                
                  when: 9
                
              
            
            
          when :keyrest then "**#{name}"
           
        
      
        
          
- 
            
              9
            
            
              
                
                  else: 2
                
              
            
            
          when :block then "&#{name}"
           
        
      
        
          
- 
            
              2
            
            
              
            
            
          else fail ArgumentError, "Wrong kind (#{kind}), name (#{name}), or default (#{default})."
           
        
      
        
          
- 
            
            
              
            
            
        end
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      private
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      attr_reader :defaulter
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end
           
        
      
    
  
 
      
        
  
  
    
      
        
          
- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Marameters
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  module Signatures
           
        
      
        
          
- 
            
            
              
            
            
    # Computes a method parameter's default value.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    Defaulter = lambda do |value, extractor: Sourcers::Function.new|
           
        
      
        
          
- 
            
              35
            
            
              
            
            
      case value
           
        
      
        
          
- 
            
            
              
                
                  when: 7
                
              
            
            
        when Proc
           
        
      
        
          
- 
            
              7
            
            
              
                
                  then: 1
                
              
                
                  else: 6
                
              
            
            
          fail TypeError, "Use procs instead of lambdas for defaults." if value.lambda?
           
        
      
        
          
- 
            
              6
            
            
              
                
                  then: 1
                
              
                
                  else: 5
                
              
            
            
          fail ArgumentError, "Avoid using parameters for proc defaults." if value.arity.nonzero?
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              5
            
            
              
                
                  when: 7
                
              
            
            
          extractor.call value
           
        
      
        
          
- 
            
              7
            
            
              
                
                  when: 5
                
              
            
            
        when String then value.dump
           
        
      
        
          
- 
            
              5
            
            
              
                
                  when: 3
                
              
            
            
        when Symbol then value.inspect
           
        
      
        
          
- 
            
              3
            
            
              
                
                  else: 13
                
              
            
            
        when nil then "nil"
           
        
      
        
          
- 
            
              13
            
            
              
            
            
        else value
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end
           
        
      
    
  
 
      
        
  
  
    
      
        
          
- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Marameters
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  module Signatures
           
        
      
        
          
- 
            
            
              
            
            
    # Builds single argument for super method's signature when argument forwarding.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    Forwarder = lambda do |kind, name = nil|
           
        
      
        
          
- 
            
              39
            
            
              
                
                  when: 9
                
              
            
            
      case kind
           
        
      
        
          
- 
            
              9
            
            
              
                
                  when: 7
                
              
            
            
        when :req, :opt then name
           
        
      
        
          
- 
            
              7
            
            
              
                
                  when: 1
                
              
            
            
        when :rest then "*#{name}"
           
        
      
        
          
- 
            
              1
            
            
              
                
                  when: 7
                
              
            
            
        when :nokey then ""
           
        
      
        
          
- 
            
              7
            
            
              
                
                  when: 8
                
              
            
            
        when :keyreq, :key then "#{name}:"
           
        
      
        
          
- 
            
              8
            
            
              
                
                  when: 6
                
              
            
            
        when :keyrest then "**#{name}"
           
        
      
        
          
- 
            
              6
            
            
              
                
                  else: 1
                
              
            
            
        when :block then "&#{name}"
           
        
      
        
          
- 
            
              1
            
            
              
            
            
        else fail ArgumentError, "Unable to forward unknown kind: #{kind.inspect}."
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end
           
        
      
    
  
 
      
        
  
  
    
      
        
          
- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Marameters
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  module Signatures
           
        
      
        
          
- 
            
            
              
            
            
    # Blends ancestor and descendant method parameters together while allowing default overrides.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    class Inheritor
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def initialize key_length: 1, kinds: KINDS
           
        
      
        
          
- 
            
              22
            
            
              
            
            
        @key_length = key_length
           
        
      
        
          
- 
            
              22
            
            
              
            
            
        @kinds = kinds
           
        
      
        
          
- 
            
              22
            
            
              
            
            
        freeze
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def call ancestor, descendant
           
        
      
        
          
- 
            
              89
            
            
              
            
            
        merge(ancestor, descendant).values.sort_by! { |(kind, *)| kinds.index kind }
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      private
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      attr_reader :key_length, :kinds
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def merge ancestor, descendant
           
        
      
        
          
- 
            
              21
            
            
              
            
            
        ancestor.to_a.union(descendant.to_a).each.with_object({}) do |parameter, all|
           
        
      
        
          
- 
            
              122
            
            
              
            
            
          key = parameter[..key_length]
           
        
      
        
          
- 
            
              122
            
            
              
            
            
          kind = key.first
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              122
            
            
              
                
                  when: 34
                
              
            
            
          case kind
           
        
      
        
          
- 
            
              34
            
            
              
                
                  when: 1
                
              
                
                  then: 16
                
              
                
                  else: 18
                
              
            
            
            when :req, :opt then all[key] = parameter if descendant.positionals_and_maybe_keywords?
           
        
      
        
          
- 
            
              1
            
            
              
            
            
            when :nokey then all
           
        
      
        
          
- 
            
            
              
                
                  when: 40
                
              
            
            
            when :keyreq, :key
           
        
      
        
          
- 
            
              40
            
            
              
            
            
              different = ancestor.keywords? && ancestor.keywords.sort != descendant.keywords.sort
           
        
      
        
          
- 
            
              40
            
            
              
                
                  then: 32
                
              
                
                  else: 8
                
              
            
            
              all[:keyrest] = [:keyrest] if different
           
        
      
        
          
- 
            
              40
            
            
              
                
                  else: 47
                
              
                
                  then: 13
                
              
                
                  else: 27
                
              
            
            
              all[key] = parameter if descendant.include? parameter
           
        
      
        
          
- 
            
              47
            
            
              
            
            
            else all[kind] = parameter
           
        
      
        
          
- 
            
            
              
            
            
          end
           
        
      
        
          
- 
            
            
              
            
            
        end
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end
           
        
      
    
  
 
      
        
  
  
    
      
        
          
- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Marameters
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  module Signatures
           
        
      
        
          
- 
            
            
              
            
            
    # Blends ancestor and descendant method arguments for forwarding to the super keyword.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    class Super
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def initialize key_length: 1, kinds: KINDS, forwarder: Signatures::Forwarder
           
        
      
        
          
- 
            
              22
            
            
              
            
            
        @key_length = key_length
           
        
      
        
          
- 
            
              22
            
            
              
            
            
        @kinds = kinds
           
        
      
        
          
- 
            
              22
            
            
              
            
            
        @forwarder = forwarder
           
        
      
        
          
- 
            
              22
            
            
              
            
            
        freeze
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def call ancestor, descendant
           
        
      
        
          
- 
            
              21
            
            
              
                
                  then: 1
                
              
                
                  else: 20
                
              
            
            
        return "" if ancestor.empty?
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              20
            
            
              
            
            
        merge(ancestor, descendant).values
           
        
      
        
          
- 
            
              27
            
            
              
            
            
                                   .sort_by! { |(kind, *)| kinds.index kind }
           
        
      
        
          
- 
            
              20
            
            
              
            
            
                                   .then { |parameters| build parameters }
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      private
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      attr_reader :key_length, :kinds, :forwarder
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def merge ancestor, descendant
           
        
      
        
          
- 
            
              20
            
            
              
            
            
        ancestor.to_a.union(descendant.to_a).each.with_object({}) do |parameter, all|
           
        
      
        
          
- 
            
              45
            
            
              
            
            
          key = parameter[..key_length]
           
        
      
        
          
- 
            
              45
            
            
              
            
            
          kind, name = key
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              45
            
            
              
            
            
          case kind
           
        
      
        
          
- 
            
            
              
                
                  when: 14
                
              
            
            
            when :req, :opt
           
        
      
        
          
- 
            
              14
            
            
              
                
                  then: 2
                
              
                
                  else: 12
                
              
            
            
              if ancestor.positionals? && !descendant.positionals? then all[:rest] = [:rest]
           
        
      
        
          
- 
            
              12
            
            
              
                
                  then: 8
                
              
                
                  else: 4
                
              
            
            
              elsif ancestor.name? name then all[key] = parameter
           
        
      
        
          
- 
            
              4
            
            
              
            
            
              else all
           
        
      
        
          
- 
            
            
              
                
                  when: 2
                
              
            
            
              end
           
        
      
        
          
- 
            
              3
            
            
              
            
            
            when :nokey then all.delete_if { |nokey, _| %i[keyreq key keyrest].include? nokey }
           
        
      
        
          
- 
            
            
              
                
                  when: 15
                
              
            
            
            when :keyreq, :key
           
        
      
        
          
- 
            
              15
            
            
              
            
            
              included = ancestor.name?(name) && descendant.name?(name)
           
        
      
        
          
- 
            
              15
            
            
              
            
            
              different = ancestor.keywords? && ancestor.keywords.sort != descendant.keywords.sort
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              15
            
            
              
                
                  then: 6
                
              
                
                  else: 9
                
              
            
            
              all[key] = parameter if included
           
        
      
        
          
- 
            
              15
            
            
              
                
                  else: 14
                
              
                
                  then: 7
                
              
                
                  else: 8
                
              
            
            
              all[:keyrest] = [:keyrest] if different
           
        
      
        
          
- 
            
              14
            
            
              
                
                  then: 13
                
              
                
                  else: 1
                
              
            
            
            else all[kind] = parameter if ancestor.kind? kind
           
        
      
        
          
- 
            
            
              
            
            
          end
           
        
      
        
          
- 
            
            
              
            
            
        end
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def build parameters
           
        
      
        
          
- 
            
              47
            
            
              
            
            
        parameters.filter_map { |kind, name| forwarder.call kind, name }
           
        
      
        
          
- 
            
            
              
            
            
                  .join ", "
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end
           
        
      
    
  
 
      
        
  
  
    
      
        
          
- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Marameters
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  module Sourcers
           
        
      
        
          
- 
            
            
              
            
            
    # Obtains the literal source of a function's body.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    class Function
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      PATTERN = /
           
        
      
        
          
- 
            
            
              
            
            
        (?:(?<function>proc|->))?  # Statement.
           
        
      
        
          
- 
            
            
              
            
            
        \s*                        # Optional space.
           
        
      
        
          
- 
            
            
              
            
            
        \{                         # Block open.
           
        
      
        
          
- 
            
            
              
            
            
        (?<body>.*?)               # Source code body.
           
        
      
        
          
- 
            
            
              
            
            
        \}                         # Block close.
           
        
      
        
          
- 
            
            
              
            
            
      /x
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def initialize pattern: PATTERN, reader: Readers::Any.new
           
        
      
        
          
- 
            
              39
            
            
              
            
            
        @pattern = pattern
           
        
      
        
          
- 
            
              39
            
            
              
            
            
        @reader = reader
           
        
      
        
          
- 
            
              39
            
            
              
            
            
        freeze
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              8
            
            
              
            
            
      def call(function) = reader.call(function).then { |line| line.match(pattern)[:body].strip }
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      private
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      attr_reader :pattern, :reader
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end
           
        
      
    
  
 
      
        
  
  
    
      
        
          
- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Marameters
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  module Sourcers
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    module Readers
           
        
      
        
          
- 
            
            
              
            
            
      # Reads source code of callable from disk or memory.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      class Any
           
        
      
        
          
- 
            
              1
            
            
              
            
            
        def initialize parser: RubyVM::InstructionSequence, disk: Disk, memory: Memory
           
        
      
        
          
- 
            
              43
            
            
              
            
            
          @parser = parser
           
        
      
        
          
- 
            
              43
            
            
              
            
            
          @disk = disk
           
        
      
        
          
- 
            
              43
            
            
              
            
            
          @memory = memory
           
        
      
        
          
- 
            
              43
            
            
              
            
            
          freeze
           
        
      
        
          
- 
            
            
              
            
            
        end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
        def call callable
           
        
      
        
          
- 
            
              11
            
            
              
            
            
          instructions = parser.of callable
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              11
            
            
              
                
                  else: 9
                
              
                
                  then: 2
                
              
            
            
          fail StandardError, "Unable to load source for: #{callable.inspect}." unless instructions
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              9
            
            
              
                
                  then: 8
                
              
                
                  else: 1
                
              
            
            
          instructions.absolute_path ? disk.call(instructions) : memory.call(instructions)
           
        
      
        
          
- 
            
            
              
            
            
        end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
        private
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
        attr_reader :parser, :disk, :memory
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end
           
        
      
    
  
 
      
        
  
  
    
      
        
          
- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Marameters
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  module Sourcers
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    module Readers
           
        
      
        
          
- 
            
            
              
            
            
      # Reads source code from on-disk instruction sequence.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      Disk = lambda do |instructions|
           
        
      
        
          
- 
            
              10
            
            
              
            
            
        path = instructions.absolute_path
           
        
      
        
          
- 
            
              10
            
            
              
            
            
        line_start, column_start, line_end, column_end = instructions.to_a.dig 4, :code_location
           
        
      
        
          
- 
            
              10
            
            
              
            
            
        lines = File.read(path).lines[(line_start - 1)..(line_end - 1)]
           
        
      
        
          
- 
            
              10
            
            
              
            
            
        lines[-1] = lines.last.byteslice(...column_end)
           
        
      
        
          
- 
            
              10
            
            
              
            
            
        lines[0] = lines.first.byteslice(column_start..)
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              10
            
            
              
            
            
        lines.join
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end
           
        
      
    
  
 
      
        
  
  
    
      
        
          
- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Marameters
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  module Sourcers
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    module Readers
           
        
      
        
          
- 
            
            
              
            
            
      # Reads source code from in-memory instruction sequence.
           
        
      
        
          
- 
            
              4
            
            
              
            
            
      Memory = -> instructions { instructions.script_lines.join.chomp }
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end
           
        
      
    
  
 
      
        
  
  
    
      
        
          
- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Marameters
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  module Sources
           
        
      
        
          
- 
            
            
              
            
            
    # Extracts the literal source of a Proc's body.
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    class Extractor
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      PATTERN = /
           
        
      
        
          
- 
            
            
              
            
            
        proc          # Proc statement.
           
        
      
        
          
- 
            
            
              
            
            
        \s*           # Optional space.
           
        
      
        
          
- 
            
            
              
            
            
        \{            # Block open.
           
        
      
        
          
- 
            
            
              
            
            
        (?<body>.*?)  # Source code body.
           
        
      
        
          
- 
            
            
              
            
            
        \}            # Block close.
           
        
      
        
          
- 
            
            
              
            
            
      /x
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def initialize pattern: PATTERN, reader: Reader.new
           
        
      
        
          
- 
            
              4
            
            
              
            
            
        warn "`#{self.class}` is deprecated, use `Sourcers::Function` instead.",
           
        
      
        
          
- 
            
            
              
            
            
             category: :deprecated
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              4
            
            
              
            
            
        @pattern = pattern
           
        
      
        
          
- 
            
              4
            
            
              
            
            
        @reader = reader
           
        
      
        
          
- 
            
              4
            
            
              
            
            
        @fallback = "nil"
           
        
      
        
          
- 
            
              4
            
            
              
            
            
        freeze
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def call function
           
        
      
        
          
- 
            
              3
            
            
              
            
            
        reader.call(function).then do |line|
           
        
      
        
          
- 
            
              2
            
            
              
                
                  then: 1
                
              
                
                  else: 1
                
              
            
            
          line.match?(pattern) ? line.match(pattern)[:body].strip : fallback
           
        
      
        
          
- 
            
            
              
            
            
        end
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      private
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      attr_reader :pattern, :reader, :fallback
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end
           
        
      
    
  
 
      
        
  
  
    
      
        
          
- 
            
            
              
            
            
# frozen_string_literal: true
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
module Marameters
           
        
      
        
          
- 
            
              1
            
            
              
            
            
  module Sources
           
        
      
        
          
- 
            
            
              
            
            
    # Reads object source code from memory or file (assumes implementation is a one-liner).
           
        
      
        
          
- 
            
              1
            
            
              
            
            
    class Reader
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def initialize offset: 1, parser: RubyVM::InstructionSequence, io: File
           
        
      
        
          
- 
            
              9
            
            
              
            
            
        warn "`#{self.class}` is deprecated, use `Sourcers::Readers::Any` instead.",
           
        
      
        
          
- 
            
            
              
            
            
             category: :deprecated
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              9
            
            
              
            
            
        @offset = offset
           
        
      
        
          
- 
            
              9
            
            
              
            
            
        @parser = parser
           
        
      
        
          
- 
            
              9
            
            
              
            
            
        @io = io
           
        
      
        
          
- 
            
              9
            
            
              
            
            
        freeze
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def call object
           
        
      
        
          
- 
            
              7
            
            
              
            
            
        instructions = parser.of object
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              7
            
            
              
                
                  else: 5
                
              
                
                  then: 2
                
              
            
            
        fail StandardError, "Unable to load source for: #{object.inspect}." unless instructions
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              5
            
            
              
            
            
        process object, instructions
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      private
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      attr_reader :offset, :parser, :io
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def process object, instructions
           
        
      
        
          
- 
            
              5
            
            
              
            
            
        lines = instructions.script_lines
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              5
            
            
              
                
                  then: 1
                
              
                
                  else: 4
                
              
            
            
        return lines.first if lines
           
        
      
        
          
- 
            
              4
            
            
              
                
                  then: 3
                
              
                
                  else: 1
                
              
            
            
        return extract(*object.source_location) if io.readable? instructions.absolute_path
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
        fail StandardError, "Unable to load source for: #{object.inspect}."
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              4
            
            
              
            
            
      def extract(path, line_number) = io.open(path) { |body| pluck body, line_number }
           
        
      
        
          
- 
            
            
              
            
            
           
        
      
        
          
- 
            
              1
            
            
              
            
            
      def pluck body, line_number
           
        
      
        
          
- 
            
              3
            
            
              
            
            
        body.each_line
           
        
      
        
          
- 
            
            
              
            
            
            .with_index
           
        
      
        
          
- 
            
              67
            
            
              
            
            
            .find { |_line, index| index + offset == line_number }
           
        
      
        
          
- 
            
            
              
            
            
            .first
           
        
      
        
          
- 
            
            
              
            
            
      end
           
        
      
        
          
- 
            
            
              
            
            
    end
           
        
      
        
          
- 
            
            
              
            
            
  end
           
        
      
        
          
- 
            
            
              
            
            
end