Class: T::Private::Methods::Signature
- Inherits:
-
Object
- Object
- T::Private::Methods::Signature
- Defined in:
- lib/types/private/methods/signature.rb
Overview
typed: true
Constant Summary collapse
- EMPTY_HASH =
{}.freeze
Instance Attribute Summary collapse
-
#arg_types ⇒ Object
readonly
Returns the value of attribute arg_types.
-
#bind ⇒ Object
readonly
Returns the value of attribute bind.
-
#block_name ⇒ Object
readonly
Returns the value of attribute block_name.
-
#block_type ⇒ Object
readonly
Returns the value of attribute block_type.
-
#check_level ⇒ Object
readonly
Returns the value of attribute check_level.
-
#ever_failed ⇒ Object
readonly
Returns the value of attribute ever_failed.
-
#generated ⇒ Object
readonly
Returns the value of attribute generated.
-
#has_keyrest ⇒ Object
readonly
Returns the value of attribute has_keyrest.
-
#has_rest ⇒ Object
readonly
Returns the value of attribute has_rest.
-
#keyrest_name ⇒ Object
readonly
Returns the value of attribute keyrest_name.
-
#keyrest_type ⇒ Object
readonly
Returns the value of attribute keyrest_type.
-
#kwarg_types ⇒ Object
readonly
Returns the value of attribute kwarg_types.
-
#method ⇒ Object
readonly
Returns the value of attribute method.
-
#method_name ⇒ Object
readonly
Returns the value of attribute method_name.
-
#mode ⇒ Object
readonly
Returns the value of attribute mode.
-
#on_failure ⇒ Object
readonly
Returns the value of attribute on_failure.
-
#override_allow_incompatible ⇒ Object
readonly
Returns the value of attribute override_allow_incompatible.
-
#parameters ⇒ Object
readonly
Returns the value of attribute parameters.
-
#req_arg_count ⇒ Object
readonly
Returns the value of attribute req_arg_count.
-
#req_kwarg_names ⇒ Object
readonly
Returns the value of attribute req_kwarg_names.
-
#rest_name ⇒ Object
readonly
Returns the value of attribute rest_name.
-
#rest_type ⇒ Object
readonly
Returns the value of attribute rest_type.
-
#return_type ⇒ Object
readonly
Returns the value of attribute return_type.
Class Method Summary collapse
Instance Method Summary collapse
- #arg_count ⇒ Object
- #dsl_method ⇒ Object
-
#each_args_value_type(args) ⇒ Hash
A mapping like [val, type], …, for only those args actually present.
-
#initialize(method:, method_name:, raw_arg_types:, raw_return_type:, bind:, mode:, check_level:, parameters: method.parameters, on_failure:, generated: false, override_allow_incompatible: false) ⇒ Signature
constructor
A new instance of Signature.
- #kwarg_names ⇒ Object
- #mark_failed ⇒ Object
- #method_desc ⇒ Object
- #owner ⇒ Object
Constructor Details
#initialize(method:, method_name:, raw_arg_types:, raw_return_type:, bind:, mode:, check_level:, parameters: method.parameters, on_failure:, generated: false, override_allow_incompatible: false) ⇒ Signature
Returns a new instance of Signature.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/types/private/methods/signature.rb', line 35 def initialize(method:, method_name:, raw_arg_types:, raw_return_type:, bind:, mode:, check_level:, parameters: method.parameters, on_failure:, generated: false, override_allow_incompatible: false) @method = method @method_name = method_name @arg_types = [] @kwarg_types = {} @block_type = nil @block_name = nil @rest_type = nil @rest_name = nil @keyrest_type = nil @keyrest_name = nil @return_type = T::Utils.coerce(raw_return_type) @bind = bind ? T::Utils.coerce(bind) : bind @mode = mode @check_level = check_level @req_arg_count = 0 @req_kwarg_names = [] @has_rest = false @has_keyrest = false @parameters = parameters @on_failure = on_failure @override_allow_incompatible = override_allow_incompatible @generated = generated @ever_failed = false param_names = parameters.map {|_, name| name} declared_param_names = raw_arg_types.keys missing_names = param_names - declared_param_names extra_names = declared_param_names - param_names if !missing_names.empty? raise "The declaration for `#{method.name}` is missing parameter(s): #{missing_names.join(', ')}" end if !extra_names.empty? raise "The declaration for `#{method.name}` has extra parameter(s): #{extra_names.join(', ')}" end parameters.zip(raw_arg_types) do |(param_kind, param_name), (type_name, raw_type)| if type_name != param_name hint = "" # Ruby reorders params so that required keyword arguments # always precede optional keyword arguments. We can't tell # whether the culprit is the Ruby reordering or user error, so # we error but include a note if param_kind == :keyreq && parameters.any? {|k, _| k == :key} hint = "\n\nNote: Any required keyword arguments must precede any optional keyword " \ "arguments. If your method declaration matches your `def`, try reordering any " \ "optional keyword parameters to the end of the method list." end raise "Parameter `#{type_name}` is declared out of order (declared as arg number " \ "#{declared_param_names.index(type_name) + 1}, defined in the method as arg number " \ "#{param_names.index(type_name) + 1}).#{hint}\nMethod: #{method_desc}" end type = T::Utils.coerce(raw_type) case param_kind when :req if @arg_types.length > @req_arg_count # Note that this is actually is supported by Ruby, but it would add complexity to # support it here, and I'm happy to discourage its use anyway. raise "Required params after optional params are not supported in method declarations. Method: #{method_desc}" end @arg_types << [param_name, type] @req_arg_count += 1 when :opt @arg_types << [param_name, type] when :key, :keyreq @kwarg_types[param_name] = type if param_kind == :keyreq @req_kwarg_names << param_name end when :block @block_name = param_name @block_type = type when :rest @has_rest = true @rest_name = param_name @rest_type = type when :keyrest @has_keyrest = true @keyrest_name = param_name @keyrest_type = type else raise "Unexpected param_kind: `#{param_kind}`. Method: #{method_desc}" end end end |
Instance Attribute Details
#arg_types ⇒ Object (readonly)
Returns the value of attribute arg_types.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def arg_types @arg_types end |
#bind ⇒ Object (readonly)
Returns the value of attribute bind.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def bind @bind end |
#block_name ⇒ Object (readonly)
Returns the value of attribute block_name.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def block_name @block_name end |
#block_type ⇒ Object (readonly)
Returns the value of attribute block_type.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def block_type @block_type end |
#check_level ⇒ Object (readonly)
Returns the value of attribute check_level.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def check_level @check_level end |
#ever_failed ⇒ Object (readonly)
Returns the value of attribute ever_failed.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def ever_failed @ever_failed end |
#generated ⇒ Object (readonly)
Returns the value of attribute generated.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def generated @generated end |
#has_keyrest ⇒ Object (readonly)
Returns the value of attribute has_keyrest.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def has_keyrest @has_keyrest end |
#has_rest ⇒ Object (readonly)
Returns the value of attribute has_rest.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def has_rest @has_rest end |
#keyrest_name ⇒ Object (readonly)
Returns the value of attribute keyrest_name.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def keyrest_name @keyrest_name end |
#keyrest_type ⇒ Object (readonly)
Returns the value of attribute keyrest_type.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def keyrest_type @keyrest_type end |
#kwarg_types ⇒ Object (readonly)
Returns the value of attribute kwarg_types.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def kwarg_types @kwarg_types end |
#method ⇒ Object (readonly)
Returns the value of attribute method.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def method @method end |
#method_name ⇒ Object (readonly)
Returns the value of attribute method_name.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def method_name @method_name end |
#mode ⇒ Object (readonly)
Returns the value of attribute mode.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def mode @mode end |
#on_failure ⇒ Object (readonly)
Returns the value of attribute on_failure.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def on_failure @on_failure end |
#override_allow_incompatible ⇒ Object (readonly)
Returns the value of attribute override_allow_incompatible.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def override_allow_incompatible @override_allow_incompatible end |
#parameters ⇒ Object (readonly)
Returns the value of attribute parameters.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def parameters @parameters end |
#req_arg_count ⇒ Object (readonly)
Returns the value of attribute req_arg_count.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def req_arg_count @req_arg_count end |
#req_kwarg_names ⇒ Object (readonly)
Returns the value of attribute req_kwarg_names.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def req_kwarg_names @req_kwarg_names end |
#rest_name ⇒ Object (readonly)
Returns the value of attribute rest_name.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def rest_name @rest_name end |
#rest_type ⇒ Object (readonly)
Returns the value of attribute rest_type.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def rest_type @rest_type end |
#return_type ⇒ Object (readonly)
Returns the value of attribute return_type.
5 6 7 |
# File 'lib/types/private/methods/signature.rb', line 5 def return_type @return_type end |
Class Method Details
.new_untyped(method:, mode: T::Private::Methods::Modes.untyped, parameters: method.parameters) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/types/private/methods/signature.rb', line 10 def self.new_untyped(method:, mode: T::Private::Methods::Modes.untyped, parameters: method.parameters) # Using `Untyped` ensures we'll get an error if we ever try validation on these. not_typed = T::Private::Types::NotTyped.new raw_return_type = not_typed raw_arg_types = parameters.map do |_param_kind, param_name| [param_name, not_typed] end.to_h self.new( method: method, method_name: method.name, raw_arg_types: raw_arg_types, raw_return_type: raw_return_type, bind: nil, mode: mode, check_level: :never, parameters: parameters, on_failure: nil, ) end |
Instance Method Details
#arg_count ⇒ Object
124 125 126 |
# File 'lib/types/private/methods/signature.rb', line 124 def arg_count @arg_types.length end |
#dsl_method ⇒ Object
136 137 138 |
# File 'lib/types/private/methods/signature.rb', line 136 def dsl_method "#{@mode}_method" end |
#each_args_value_type(args) ⇒ Hash
Returns a mapping like [val, type], …, for only those args actually present.
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/types/private/methods/signature.rb', line 141 def each_args_value_type(args) # Manually split out args and kwargs based on ruby's behavior. Do not try to implement this by # getting ruby to determine the kwargs for you (e.g., by defining this method to take *args and # **kwargs). That won't work, because ruby's behavior for determining kwargs is dependent on the # the other parameters in the method definition, and our method definition here doesn't (and # can't) match the definition of the method we're validating. In addition, Ruby has a bug that # causes forwarding **kwargs to do the wrong thing: see https://bugs.ruby-lang.org/issues/10708 # and https://bugs.ruby-lang.org/issues/11860. if (args.length > @req_arg_count) && (!@kwarg_types.empty? || @has_keyrest) && args[-1].is_a?(Hash) kwargs = args[-1] args = args[0...-1] else kwargs = EMPTY_HASH end arg_types = @arg_types if @has_rest arg_types += [[@rest_name, @rest_type]] * (args.length - @arg_types.length) elsif (args.length < @req_arg_count) || (args.length > @arg_types.length) expected_str = @req_arg_count.to_s if @arg_types.length != @req_arg_count expected_str += "..#{@arg_types.length}" end raise ArgumentError.new("wrong number of arguments (given #{args.length}, expected #{expected_str})") end begin it = 0 while it < args.length yield arg_types[it][0], args[it], arg_types[it][1] it += 1 end end kwargs.each do |name, val| type = @kwarg_types[name] if !type && @has_keyrest type = @keyrest_type end yield name, val, type if type end end |
#kwarg_names ⇒ Object
128 129 130 |
# File 'lib/types/private/methods/signature.rb', line 128 def kwarg_names @kwarg_types.keys end |
#mark_failed ⇒ Object
31 32 33 |
# File 'lib/types/private/methods/signature.rb', line 31 def mark_failed @ever_failed = true end |
#method_desc ⇒ Object
186 187 188 189 190 191 192 193 |
# File 'lib/types/private/methods/signature.rb', line 186 def method_desc if @method.source_location loc = @method.source_location.join(':') else loc = "<unknown location>" end "#{@method} at #{loc}" end |
#owner ⇒ Object
132 133 134 |
# File 'lib/types/private/methods/signature.rb', line 132 def owner @method.owner end |