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)
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)
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, 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)
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
def self.run_all_sig_blocks T::Private::Methods.run_all_sig_blocks end
def self.signature_for_instance_method(mod, method_name)
- 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='...')
-
(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)
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
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