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
-
.arity(method) ⇒ Object
Returns the arity of a method, unwrapping the sig if needed.
-
.coerce(val) ⇒ Object
Used to convert from a type specification to a ‘T::Types::Base`.
-
.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.
-
.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.
-
.run_all_sig_blocks ⇒ Object
Unwraps all the sigs.
-
.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.
-
.string_truncate_middle(str, start_len, end_len, ellipsis = '...') ⇒ String
Elide the middle of a string as needed and replace it with an ellipsis.
-
.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).
-
.validate_sigs ⇒ Object
This can be called in a wholesome test to make sure all the ‘sig`s are well formed.
- .wrap_method_with_call_validation_if_needed(mod, method_sig, original_method) ⇒ Object
Class Method Details
.arity(method) ⇒ Object
Returns the arity of a method, unwrapping the sig if needed
114 115 116 117 118 119 |
# File 'lib/types/utils.rb', line 114 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_blocks ⇒ Object
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.
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.
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/types/utils.rb', line 139 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.
99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/types/utils.rb', line 99 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 |
.validate_sigs ⇒ Object
This can be called in a wholesome test to make sure all the ‘sig`s are well formed.
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/types/utils.rb', line 79 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 |
.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 |