Module: T::Utils

Defined in:
lib/types/utils.rb,
lib/types/runtime_profiled.rb

Overview

typed: true

Defined Under Namespace

Modules: Nilable Classes: RuntimeProfiled

Class Method Summary collapse

Class Method Details

.arity(method) ⇒ Object

Returns the arity of a method, unwrapping the sig if needed



94
95
96
97
98
99
# File 'lib/types/utils.rb', line 94

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

.coerce(val) ⇒ Object

Used to convert from a type specification to a ‘T::Types::Base`.



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/types/utils.rb', line 6

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

.methods_excluding_object(mod) ⇒ Object

Returns the set of all methods (public, protected, private) defined on a module or its ancestors, excluding Object and its ancestors. Overrides of methods from Object (and its ancestors) are included.



38
39
40
41
42
43
44
45
46
# File 'lib/types/utils.rb', line 38

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

.register_forwarder(from_method, to_method, remove_first_param: false) ⇒ Object

Associates a signature with a forwarder method that matches the signature of the method it forwards to. This is necessary because forwarder methods are often declared with catch-all splat parameters, rather than the exact set of parameters ultimately used by the target method, so they cannot be validated as strictly.

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



55
56
57
58
59
# File 'lib/types/utils.rb', line 55

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

.run_all_sig_blocksObject

Unwraps all the sigs.



73
74
75
# File 'lib/types/utils.rb', line 73

def self.run_all_sig_blocks
  T::Private::Methods.run_all_sig_blocks
end

.signature_for_instance_method(mod, method_name) ⇒ Object

Returns the signature for the instance method on the supplied module, or nil if it’s not found or not typed.

Examples:

T::Utils.signature_for_instance_method(MyClass, :my_method)



64
65
66
# File 'lib/types/utils.rb', line 64

def self.signature_for_instance_method(mod, method_name)
  T::Private::Methods.signature_for_method(mod.instance_method(method_name))
end

.string_truncate_middle(str, start_len, end_len, ellipsis = '...') ⇒ String

Elide the middle of a string as needed and replace it with an ellipsis. Keep the given number of characters at the start and end of the string.

This method operates on string length, not byte length.

If the string is shorter than the requested truncation length, return it without adding an ellipsis. This method may return a longer string than the original if the characters removed are shorter than the ellipsis.

Parameters:

  • str (String)
  • start_len (Fixnum)

    The length of string before the ellipsis

  • end_len (Fixnum)

    The length of string after the ellipsis

  • ellipsis (String) (defaults to: '...')

    The string to add in place of the elided text

Returns:

  • (String)

Raises:

  • (ArgumentError)


119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/types/utils.rb', line 119

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

.unwrap_nilable(type) ⇒ Object

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). If so, returns the T::Types::Base of the something else. Otherwise, returns nil.



79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/types/utils.rb', line 79

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

.wrap_method_with_call_validation_if_needed(mod, method_sig, original_method) ⇒ Object



68
69
70
# File 'lib/types/utils.rb', line 68

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