module Dry::Cerberus::H

Constants

CONCAT

Public Instance Methods

alias_name(m, idx) click to toggle source
# File lib/dry/behaviour/cerberus.rb, line 57
def alias_name(m, idx)
  :"#{m && m.name}#{CONCAT}#{idx}"
end
extract_when(m) click to toggle source
# File lib/dry/behaviour/cerberus.rb, line 43
def extract_when(m)
  file, line = m.source_location
  raise ::Dry::Guards::NotGuardable.new(m, :nil) if file.nil?

  File.readlines(file)[line - 1..-1].join(' ')[/(?<=when:).*/].tap do |guard|
    raise ::Dry::Guards::NotGuardable.new(m, :when_is_nil) if guard.nil?
    clause = parse_hash guard
    raise ::Dry::Guards::NotGuardable.new(m, :when_not_hash) unless clause.is_a?(String)
    guard.replace clause
  end
rescue Errno::ENOENT => e
  raise ::Dry::Guards::NotGuardable.new(m, e)
end
parse_hash(input) click to toggle source
# File lib/dry/behaviour/cerberus.rb, line 61
def parse_hash(input)
  input.each_codepoint
       .drop_while { |cp| cp != 123 }
       .each_with_object(['', 0]) do |cp, acc|
    case cp
    when 123 then acc[-1] = acc.last.succ
    when 125 then acc[-1] = acc.last.pred
    end
    acc.first << cp
    break acc.first if acc.last.zero?
  end
end
umbrella(guarded, name, clauses) click to toggle source

rubocop:disable Metrics/MethodLength rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/PerceivedComplexity rubocop:disable Style/AsciiComments

# File lib/dry/behaviour/cerberus.rb, line 89
def umbrella(guarded, name, clauses)
  guarded.prepend(Module.new do
    define_method name do |*args, **params, &cb|
      found = clauses.each_with_index.detect do |(hash, m), idx|
        next if m.arity >= 0 && m.arity != args.size
        break [[hash, m], idx] if case hash
                                  when NilClass then m.arity < 0
                                  when Integer then hash == args.size
                                  end
        next if hash.nil?
        hash.all? do |param, condition|
          type_var, idx = m.parameters.each_with_index.detect { |(_type, var), _i| var == param }
          # rubocop:disable Style/CaseEquality
          idx && begin
                   case type_var.first
                   when :req, :opt then condition === args[idx]
                   when :block then condition === cb
                   end
                 rescue => _e
                   false # we don’t care
                 end
          # rubocop:enable Style/CaseEquality
        end
      end
      raise ::Dry::Guards::NotMatched.new(*args, **params, &cb) unless found
      ::Dry::DEFINE_METHOD.(H.alias_name(found.first.last, found.last), self, *args, **params, &cb)
    end
  end)
end
umbrellas(guarded) click to toggle source
# File lib/dry/behaviour/cerberus.rb, line 74
def umbrellas(guarded)
  guarded.guarded_methods.reject! do |_, hash|
    next unless hash.size == 1 && hash.keys.first.is_a?(Integer)
    guarded.send :remove_method, alias_name(hash.values.first, 0)
  end
  # guarded.guarded_methods.each(&H.method(:umbrella).to_proc.curry[guarded])
  guarded.guarded_methods.each do |name, clauses|
    H.umbrella(guarded, name, clauses)
  end
end