module Anyway::RBSGenerator

Constants

TYPE_TO_CLASS

Public Instance Methods

to_rbs() click to toggle source

Generate RBS signature from a config class

# File lib/anyway/rbs.rb, line 16
def to_rbs
  *namespace, class_name = name.split("::")

  buf = []
  indent = 0
  interface_name = "_Config"

  if namespace.empty?
    interface_name = "_#{class_name}"
  else
    buf << "module #{namespace.join("::")}"
    indent += 1
  end

  # Using interface emulates a module we include to provide getters and setters
  # (thus making `super` possible)
  buf << "#{"  " * indent}interface #{interface_name}"
  indent += 1

  # Generating setters and getters for config attributes
  config_attributes.each do |param|
    type = coercion_mapping[param] || defaults[param.to_s]

    type =
      case type
      in NilClass
        "untyped"
      in Symbol
        TYPE_TO_CLASS.fetch(type) { defaults[param] ? "Symbol" : "untyped" }
      in Array
        "Array[untyped]"
      in array: _, type:, **nil
        "Array[#{TYPE_TO_CLASS.fetch(type, "untyped")}]"
      in Hash
        "Hash[string,untyped]"
      in TrueClass | FalseClass
        "bool"
      else
        type.class.to_s
      end

    getter_type = type
    getter_type = "#{type}?" unless required_attributes.include?(param)

    buf << "#{"  " * indent}def #{param}: () -> #{getter_type}"
    buf << "#{"  " * indent}def #{param}=: (#{type}) -> void"

    if type == "bool" || type == "bool?"
      buf << "#{"  " * indent}def #{param}?: () -> #{getter_type}"
    end
  end

  indent -= 1
  buf << "#{"  " * indent}end"

  buf << ""

  buf << "#{"  " * indent}class #{class_name} < #{superclass.name}"
  indent += 1

  buf << "#{"  " * indent}include #{interface_name}"

  indent -= 1
  buf << "#{"  " * indent}end"

  unless namespace.empty?
    buf << "end"
  end

  buf << ""

  buf.join("\n")
end