module T::Utils

def self.arity(method)

Returns the arity of a method, unwrapping the sig if needed
def self.arity(method)
  arity = method.arity # rubocop:disable PrisonGuard/NoArity
  return arity if arity != -1 || method.is_a?(Proc)
  sig = T::Private::Methods.signature_for_method(method)
  sig ? sig.method.arity : arity # rubocop:disable PrisonGuard/NoArity
end

def self.coerce(val)

Used to convert from a type specification to a `T::Types::Base`.
def self.coerce(val)
  if val.is_a?(T::Private::Types::TypeAlias)
    val.aliased_type
  elsif val.is_a?(T::Types::Base)
    val
  elsif val == ::Array
    T::Array[T.untyped]
  elsif val == ::Set
    T::Set[T.untyped]
  elsif val == ::Hash
    T::Hash[T.untyped, T.untyped]
  elsif val == ::Enumerable
    T::Enumerable[T.untyped]
  elsif val == ::Enumerator
    T::Enumerator[T.untyped]
  elsif val == ::Range
    T::Range[T.untyped]
  elsif val.is_a?(Module)
    T::Types::Simple.new(val) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
  elsif val.is_a?(::Array)
    T::Types::FixedArray.new(val) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
  elsif val.is_a?(::Hash)
    T::Types::FixedHash.new(val) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
  elsif val.is_a?(T::Private::Methods::DeclBuilder)
    T::Private::Methods.finalize_proc(val.decl)
  elsif defined?(::Opus) && defined?(::Opus::Enum) && val.is_a?(::Opus::Enum)
    T::Types::OpusEnum.new(val) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
  elsif defined?(::T::Enum) && val.is_a?(::T::Enum)
    T::Types::OpusEnum.new(val) # rubocop:disable PrisonGuard/UseOpusTypesShortcut
  elsif val.is_a?(::String)
    raise "Invalid String literal for type constraint. Must be an #{T::Types::Base}, a " \
          "class/module, or an array. Got a String with value `#{val}`."
  else
    raise "Invalid value for type constraint. Must be an #{T::Types::Base}, a " \
          "class/module, or an array. Got a `#{val.class}`."
  end
end

def self.methods_excluding_object(mod)

ancestors) are included.
ancestors, excluding Object and its ancestors. Overrides of methods from Object (and its
Returns the set of all methods (public, protected, private) defined on a module or its
def self.methods_excluding_object(mod)
  # We can't just do mod.instance_methods - Object.instance_methods, because that would leave out
  # any methods from Object that are overridden in mod.
  mod.ancestors.flat_map do |ancestor|
    # equivalent to checking Object.ancestors.include?(ancestor)
    next [] if Object <= ancestor
    ancestor.instance_methods(false) + ancestor.private_instance_methods(false)
  end.uniq
end

def self.register_forwarder(from_method, to_method, remove_first_param: false)

such that the signature is accurate.
The caller of this method must ensure that the forwarder method properly forwards all parameters

so they cannot be validated as strictly.
splat parameters, rather than the exact set of parameters ultimately used by the target method,
forwards to. This is necessary because forwarder methods are often declared with catch-all
Associates a signature with a forwarder method that matches the signature of the method it
def self.register_forwarder(from_method, to_method, remove_first_param: false)
  T::Private::Methods.register_forwarder(
    from_method, to_method, remove_first_param: remove_first_param
  )
end

def self.resolve_alias(type)

Return the underlying type for a type alias. Otherwise returns type.
def self.resolve_alias(type)
  case type
  when T::Private::Types::TypeAlias
    type.aliased_type
  else
    type
  end
end

def self.run_all_sig_blocks

Unwraps all the sigs.
def self.run_all_sig_blocks
  T::Private::Methods.run_all_sig_blocks
end

def self.signature_for_instance_method(mod, method_name)

Other tags:
    Example: T::Utils.signature_for_instance_method(MyClass, :my_method) -
def self.signature_for_instance_method(mod, method_name)
  T::Private::Methods.signature_for_method(mod.instance_method(method_name))
end

def self.string_truncate_middle(str, start_len, end_len, ellipsis='...')

Returns:
  • (String) -

Parameters:
  • ellipsis (String) -- The string to add in place of the elided text
  • end_len (Fixnum) -- The length of string after the ellipsis
  • start_len (Fixnum) -- The length of string before the ellipsis
  • str (String) --
def self.string_truncate_middle(str, start_len, end_len, ellipsis='...')
  return unless str
  raise ArgumentError.new('must provide start_len') unless start_len
  raise ArgumentError.new('must provide end_len') unless end_len
  raise ArgumentError.new('start_len must be >= 0') if start_len < 0
  raise ArgumentError.new('end_len must be >= 0') if end_len < 0
  str = str.to_s
  return str if str.length <= start_len + end_len
  start_part = str[0...start_len - ellipsis.length]
  end_part = end_len == 0 ? '' : str[-end_len..-1]
  "#{start_part}#{ellipsis}#{end_part}"
end

def self.unwrap_nilable(type)

If so, returns the T::Types::Base of the something else. Otherwise, returns nil.
Give a type which is a subclass of T::Types::Base, determines if the type is a simple nilable type (union of NilClass and something else).
def self.unwrap_nilable(type)
  case type
  when T::Types::Union
    non_nil_types = type.types.reject {|t| t == T::Utils.coerce(NilClass)}
    if non_nil_types.length == 1
      non_nil_types.first
    else
      nil
    end
  else
    nil
  end
end

def self.wrap_method_with_call_validation_if_needed(mod, method_sig, original_method)

def self.wrap_method_with_call_validation_if_needed(mod, method_sig, original_method)
  T::Private::Methods::CallValidation.wrap_method_if_needed(mod, method_sig, original_method)
end