class Tapioca::Dsl::Compiler

def add_error(error)

def add_error(error)
  @pipeline.add_error(error)
end

def all_classes

def all_classes
  @all_classes ||= T.let(
    T.cast(ObjectSpace.each_object(Class), T::Enumerable[T::Class[T.anything]]).each,
    T.nilable(T::Enumerable[T::Class[T.anything]]),
  )
end

def all_modules

def all_modules
  @all_modules ||= T.let(
    T.cast(ObjectSpace.each_object(Module), T::Enumerable[Module]).each,
    T.nilable(T::Enumerable[Module]),
  )
end

def compile_method_parameters_to_rbi(method_def)

def compile_method_parameters_to_rbi(method_def)
  signature = signature_of(method_def)
  method_def = signature.nil? ? method_def : signature.method
  method_types = parameters_types_from_signature(method_def, signature)
  parameters = T.let(method_def.parameters, T::Array[[Symbol, T.nilable(Symbol)]])
  parameters.each_with_index.map do |(type, name), index|
    fallback_arg_name = "_arg#{index}"
    name = name ? name.to_s : fallback_arg_name
    name = fallback_arg_name unless valid_parameter_name?(name)
    method_type = T.must(method_types[index])
    case type
    when :req
      create_param(name, type: method_type)
    when :opt
      create_opt_param(name, type: method_type, default: "T.unsafe(nil)")
    when :rest
      create_rest_param(name, type: method_type)
    when :keyreq
      create_kw_param(name, type: method_type)
    when :key
      create_kw_opt_param(name, type: method_type, default: "T.unsafe(nil)")
    when :keyrest
      create_kw_rest_param(name, type: method_type)
    when :block
      create_block_param(name, type: method_type)
    else
      raise "Unknown type `#{type}`."
    end
  end
end

def compile_method_return_type_to_rbi(method_def)

def compile_method_return_type_to_rbi(method_def)
  signature = signature_of(method_def)
  return_type = signature.nil? ? "T.untyped" : name_of_type(signature.return_type)
  sanitize_signature_types(return_type)
end

def compiler_enabled?(compiler_name)

def compiler_enabled?(compiler_name)
  @pipeline.compiler_enabled?(compiler_name)
end

def create_method_from_def(scope, method_def, class_method: false)

def create_method_from_def(scope, method_def, class_method: false)
  scope.create_method(
    method_def.name.to_s,
    parameters: compile_method_parameters_to_rbi(method_def),
    return_type: compile_method_return_type_to_rbi(method_def),
    class_method: class_method,
  )
end

def decorate; end

def decorate; end

def gather_constants; end

def gather_constants; end

def handles?(constant)

def handles?(constant)
  processable_constants.include?(constant)
end

def initialize(pipeline, root, constant)

def initialize(pipeline, root, constant)
  @pipeline = pipeline
  @root = root
  @constant = constant
  @errors = T.let([], T::Array[String])
end

def parameters_types_from_signature(method_def, signature)

def parameters_types_from_signature(method_def, signature)
  params = T.let([], T::Array[String])
  return method_def.parameters.map { "T.untyped" } unless signature
  # parameters types
  signature.arg_types.each { |arg_type| params << arg_type[1].to_s }
  # keyword parameters types
  signature.kwarg_types.each { |_, kwarg_type| params << kwarg_type.to_s }
  # rest parameter type
  params << signature.rest_type.to_s if signature.has_rest
  # keyrest parameter type
  params << signature.keyrest_type.to_s if signature.has_keyrest
  # special case `.void` in a proc
  unless signature.block_name.nil?
    params << signature.block_type.to_s.gsub("returns(<VOID>)", "void")
  end
  params
end

def processable_constants

def processable_constants
  @processable_constants ||= T.let(
    T::Set[Module].new.compare_by_identity.merge(gather_constants),
    T.nilable(T::Set[Module]),
  )
end