module T::Utils

def self.DANGER_enable_checking_in_tests

def self.DANGER_enable_checking_in_tests
  T::Private::RuntimeLevels.enable_checking_in_tests
end

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::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)
  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.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.validate_sigs

formed.
This can be called in a wholesome test to make sure all the `sig`s are well
def self.validate_sigs
  exceptions = []
  run_all_sig_blocks
  ObjectSpace.each_object(Module) do |mod| # rubocop:disable PrisonGuard/NoDynamicConstAccess
    begin
      T::Private::Abstract::Validate.validate_subclass(mod)
      if T::AbstractUtils.abstract_module?(mod)
        T::Private::Abstract::Validate.validate_abstract_module(mod)
      end
    rescue => e
      exceptions << e
    end
  end
  if !exceptions.empty?
    raise "#{exceptions.count} exception thrown during validation:\n\n#{exceptions.map(&:message).sort.join("\n\n")}"
  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