class Dry::Types::Printer

@api private

@api private

@api private

Constants

MAPPING

Public Class Methods

new() click to toggle source
# File lib/dry/types/printer.rb, line 38
def initialize
  @composition_printers = {}
  freeze
end

Public Instance Methods

call(type) click to toggle source
# File lib/dry/types/printer.rb, line 43
def call(type)
  output = "".dup
  visit(type) { |str| output << str }
  "#<Dry::Types[#{output}]>"
end
visit(type) { |inspect| ... } click to toggle source
# File lib/dry/types/printer.rb, line 49
def visit(type, &block)
  print_with = MAPPING.fetch(type.class) do
    if type.class < Constructor
      :visit_constructor
    elsif type.is_a?(Type)
      return yield type.inspect
    else
      raise ArgumentError, "Do not know how to print #{type.class}"
    end
  end
  send(print_with, type, &block)
end
visit_any(_) { |"Any"| ... } click to toggle source
# File lib/dry/types/printer.rb, line 62
def visit_any(_)
  yield "Any"
end
visit_array(type) { |"Array#{opts}"| ... } click to toggle source
# File lib/dry/types/printer.rb, line 66
def visit_array(type)
  visit_options(EMPTY_HASH, type.meta) do |opts|
    yield "Array#{opts}"
  end
end
visit_array_member(array) { |"Array<#{type}#{opts}>"| ... } click to toggle source
# File lib/dry/types/printer.rb, line 72
def visit_array_member(array)
  visit(array.member) do |type|
    visit_options(EMPTY_HASH, array.meta) do |opts|
      yield "Array<#{type}#{opts}>"
    end
  end
end
visit_callable(callable) { |"#{receiver}.#{name}"| ... } click to toggle source
# File lib/dry/types/printer.rb, line 155
def visit_callable(callable)
  fn = callable.is_a?(String) ? FnContainer[callable] : callable

  case fn
  when ::Method
    yield "#{fn.receiver}.#{fn.name}"
  when ::Proc
    path, line = fn.source_location

    if line&.zero?
      yield ".#{path}"
    elsif path
      yield "#{path.sub("#{Dir.pwd}/", EMPTY_STRING)}:#{line}"
    else
      match = fn.to_s.match(/\A#<Proc:0x\h+\(&:(?<name>\w+)\)(:? \(lambda\))?>\z/) # rubocop:disable Lint/MixedRegexpCaptureTypes

      if match
        yield ".#{match[:name]}"
      elsif fn.lambda?
        yield "(lambda)"
      else
        yield "(proc)"
      end
    end
  else
    call = fn.method(:call)

    if call.owner == fn.class
      yield "#{fn.class}#call"
    else
      yield "#{fn}.call"
    end
  end
end
visit_composition(composition, &block) click to toggle source
# File lib/dry/types/printer.rb, line 104
def visit_composition(composition, &block)
  klass = composition.class
  @composition_printers[klass] = Composition.new(self, klass)
  @composition_printers[klass].visit(composition, &block)
end
visit_constrained(constrained) { |"Constrained<#{type} rule=[#{rule}]>"| ... } click to toggle source
# File lib/dry/types/printer.rb, line 93
def visit_constrained(constrained)
  visit(constrained.type) do |type|
    options = constrained.options.dup
    rule = options.delete(:rule)

    visit_options(options) do |_opts|
      yield "Constrained<#{type} rule=[#{rule}]>"
    end
  end
end
visit_constructor(constructor) { |"Constructor<#{type} fn=#{fn}#{opts}>"| ... } click to toggle source
# File lib/dry/types/printer.rb, line 80
def visit_constructor(constructor)
  visit(constructor.type) do |type|
    visit_callable(constructor.fn.fn) do |fn|
      options = constructor.options.dup
      options.delete(:fn)

      visit_options(options) do |opts|
        yield "Constructor<#{type} fn=#{fn}#{opts}>"
      end
    end
  end
end
visit_default(default) { |"Default<#{type} value_fn=#{fn}#{opts}>"| ... } click to toggle source
# File lib/dry/types/printer.rb, line 129
def visit_default(default)
  visit(default.type) do |type|
    visit_options(default.options) do |opts|
      if default.is_a?(Default::Callable)
        visit_callable(default.value) do |fn|
          yield "Default<#{type} value_fn=#{fn}#{opts}>"
        end
      else
        yield "Default<#{type} value=#{default.value.inspect}#{opts}>"
      end
    end
  end
end
visit_enum(enum) { |"Enum<#{type} values={#{values}}#{opts}>"| ... } click to toggle source
# File lib/dry/types/printer.rb, line 110
def visit_enum(enum)
  visit(enum.type) do |type|
    options = enum.options.dup
    mapping = options.delete(:mapping)

    visit_options(options) do |opts|
      if mapping == enum.inverted_mapping
        values = mapping.values.map(&:inspect).join(", ")
        yield "Enum<#{type} values={#{values}}#{opts}>"
      else
        mapping_str = mapping.map { |key, value|
          "#{key.inspect}=>#{value.inspect}"
        }.join(", ")
        yield "Enum<#{type} mapping={#{mapping_str}}#{opts}>"
      end
    end
  end
end
visit_hash(hash) { |"Hash"| ... } click to toggle source
# File lib/dry/types/printer.rb, line 253
def visit_hash(hash)
  options = hash.options.dup
  type_fn_str = ""

  if (type_fn = options.delete(:type_transform_fn))
    visit_callable(type_fn) do |fn|
      type_fn_str = "type_fn=#{fn}"
    end
  end

  visit_options(options, hash.meta) do |opts|
    if opts.empty? && type_fn_str.empty?
      yield "Hash"
    else
      yield "Hash<#{type_fn_str}#{opts}>"
    end
  end
end
visit_key(key) { |"#{name}: #{type}"| ... } click to toggle source
# File lib/dry/types/printer.rb, line 243
def visit_key(key)
  visit(key.type) do |type|
    if key.required?
      yield "#{key.name}: #{type}"
    else
      yield "#{key.name}?: #{type}"
    end
  end
end
visit_lax(lax) { |"Lax<#{type}>"| ... } click to toggle source
# File lib/dry/types/printer.rb, line 149
def visit_lax(lax)
  visit(lax.type) do |type|
    yield "Lax<#{type}>"
  end
end
visit_map(map) { |"Map<#{key} => #{value}>"| ... } click to toggle source
# File lib/dry/types/printer.rb, line 229
def visit_map(map)
  visit(map.key_type) do |key|
    visit(map.value_type) do |value|
      options = map.options.dup
      options.delete(:key_type)
      options.delete(:value_type)

      visit_options(options) do |_opts|
        yield "Map<#{key} => #{value}>"
      end
    end
  end
end
visit_maybe(maybe) { |"Maybe<#{type}>"| ... } click to toggle source

@api private

# File lib/dry/types/extensions/maybe.rb, line 117
def visit_maybe(maybe)
  visit(maybe.type) do |type|
    yield "Maybe<#{type}>"
  end
end
visit_nominal(type) { |"Nominal<#{primitive}#{opts}>"| ... } click to toggle source
# File lib/dry/types/printer.rb, line 143
def visit_nominal(type)
  visit_options(type.options, type.meta) do |opts|
    yield "Nominal<#{type.primitive}#{opts}>"
  end
end
visit_options(options, meta = EMPTY_HASH) { |""| ... } click to toggle source
# File lib/dry/types/printer.rb, line 272
def visit_options(options, meta = EMPTY_HASH) # rubocop:disable Metrics/PerceivedComplexity
  if options.empty? && meta.empty?
    yield ""
  else
    opts = options.empty? ? "" : " options=#{options.inspect}"

    if meta.empty?
      yield opts
    else
      values = meta.map do |key, value|
        case key
        when Symbol
          "#{key}: #{value.inspect}"
        else
          "#{key.inspect}=>#{value.inspect}"
        end
      end

      yield "#{opts} meta={#{values.join(", ")}}"
    end
  end
end
visit_schema(schema) { |"#{header}}>"| ... } click to toggle source
# File lib/dry/types/printer.rb, line 190
def visit_schema(schema)
  options = schema.options.dup
  size = schema.count
  key_fn_str = ""
  type_fn_str = ""
  strict_str = ""

  strict_str = "strict " if options.delete(:strict)

  if (key_fn = options.delete(:key_transform_fn))
    visit_callable(key_fn) do |fn|
      key_fn_str = "key_fn=#{fn} "
    end
  end

  if (type_fn = options.delete(:type_transform_fn))
    visit_callable(type_fn) do |fn|
      type_fn_str = "type_fn=#{fn} "
    end
  end

  keys = options.delete(:keys)

  visit_options(options, schema.meta) do |opts|
    opts = "#{opts[1..]} " unless opts.empty?
    schema_parameters = "#{key_fn_str}#{type_fn_str}#{strict_str}#{opts}"

    header = "Schema<#{schema_parameters}keys={"

    if size.zero?
      yield "#{header}}>"
    else
      yield header.dup << keys.map { |key|
        visit(key) { |type| type }
      }.join(" ") << "}>"
    end
  end
end