Module: Rtype
- Extended by:
- Rtype
- Included in:
- Rtype
- Defined in:
- lib/rtype.rb,
lib/rtype/version.rb,
lib/rtype/behavior.rb,
lib/rtype/rtype_proxy.rb,
lib/rtype/behavior/and.rb,
lib/rtype/behavior/not.rb,
lib/rtype/behavior/xor.rb,
lib/rtype/behavior/base.rb,
lib/rtype/type_signature.rb,
lib/rtype/behavior/nilable.rb,
lib/rtype/method_annotator.rb,
lib/rtype/return_type_error.rb,
lib/rtype/argument_type_error.rb,
lib/rtype/behavior/typed_array.rb,
lib/rtype/type_signature_error.rb
Defined Under Namespace
Modules: Behavior, MethodAnnotator Classes: ArgumentTypeError, ReturnTypeError, RtypeProxy, TypeSignature, TypeSignatureError
Constant Summary collapse
- VERSION =
"0.6.6".freeze
- JAVA_EXT_VERSION =
rtype java extension version. nil If the extension is not used
nil- NATIVE_EXT_VERSION =
rtype c extension version. nil If the extension is not used
nil- @@type_signatures =
This is just ‘information’ Any change of this doesn’t affect type checking
Hash.new
Class Method Summary collapse
Instance Method Summary collapse
- #arg_message(idx) ⇒ String
-
#arg_type_error_message(idx, expected, value) ⇒ String
A error message.
-
#assert_arguments_type(expected_args, args) ⇒ void
Validates arguments.
-
#assert_arguments_type_with_keywords(expected_args, args, expected_kwargs, kwargs) ⇒ void
Validates arguments and keyword arguments.
- #assert_return_type(expected, result) ⇒ Object
-
#assert_valid_argument_type_sig_element(sig) ⇒ Object
Checks the type behavior is valid.
-
#assert_valid_arguments_type_sig(sig) ⇒ Object
Checks the arguments type signature is valid.
- #assert_valid_return_type_sig(sig) ⇒ Object
-
#assert_valid_type_sig(sig) ⇒ Object
Checks the type signature is valid.
-
#define_typed_accessor(owner, accessor_name, type_behavior) ⇒ void
Calls
attr_accessorif the accessor method(getter/setter) is not defined. -
#define_typed_method(owner, method_name, type_sig_info) ⇒ void
Makes the method typed.
- #kwarg_message(key) ⇒ String
-
#kwarg_type_error_message(key, expected, value) ⇒ String
A error message.
- #nilable(*args) ⇒ Object
- #not(*args) ⇒ Object
-
#type_error_message(expected, value) ⇒ String
Returns a error message for the pair of type behavior and value.
-
#type_signatures ⇒ Hash
This is just ‘information’ Any change of this doesn’t affect type checking.
-
#valid?(expected, value) ⇒ Boolean
Checks the value is valid for the type behavior.
- #xor(*args) ⇒ Object
Class Method Details
.and(*args) ⇒ Object
21 22 23 |
# File 'lib/rtype/behavior/and.rb', line 21 def self.and(*args) Behavior::And[*args] end |
Instance Method Details
#arg_message(idx) ⇒ String
142 143 144 |
# File 'lib/rtype.rb', line 142 def (idx) "for #{ordinalize_number(idx+1)} argument:" end |
#arg_type_error_message(idx, expected, value) ⇒ String
Returns A error message.
127 128 129 |
# File 'lib/rtype.rb', line 127 def (idx, expected, value) "#{(idx)}\n" + (expected, value) end |
#assert_arguments_type(expected_args, args) ⇒ void
This method returns an undefined value.
Validates arguments
333 334 335 336 337 338 339 340 341 342 343 344 345 |
# File 'lib/rtype.rb', line 333 def assert_arguments_type(expected_args, args) e_len = expected_args.length # `length.times` is faster than `each_with_index` args.length.times do |i| break if i >= e_len expected = expected_args[i] value = args[i] unless valid?(expected, value) raise ArgumentTypeError, "#{(i)}\n" + (expected, value) end end nil end |
#assert_arguments_type_with_keywords(expected_args, args, expected_kwargs, kwargs) ⇒ void
This method returns an undefined value.
Validates arguments and keyword arguments
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
# File 'lib/rtype.rb', line 359 def assert_arguments_type_with_keywords(expected_args, args, expected_kwargs, kwargs) e_len = expected_args.length # `length.times` is faster than `each_with_index` args.length.times do |i| break if i >= e_len expected = expected_args[i] value = args[i] unless valid?(expected, value) raise ArgumentTypeError, "#{(i)}\n" + (expected, value) end end kwargs.each do |key, value| if expected_kwargs.key?(key) expected = expected_kwargs[key] unless valid?(expected, value) raise ArgumentTypeError, "#{(key)}\n" + (expected, value) end end end nil end |
#assert_return_type(expected, result) ⇒ Object
392 393 394 395 396 397 |
# File 'lib/rtype.rb', line 392 def assert_return_type(expected, result) unless valid?(expected, result) raise ReturnTypeError, "for return:\n" + (expected, result) end nil end |
#assert_valid_argument_type_sig_element(sig) ⇒ Object
Checks the type behavior is valid
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/rtype.rb', line 255 def assert_valid_argument_type_sig_element(sig) case sig when Rtype::Behavior::Base when Module when Symbol when Regexp when Range when Array sig.each do |e| assert_valid_argument_type_sig_element(e) end when Hash sig.each_value do |e| assert_valid_argument_type_sig_element(e) end when Proc when true when false when nil else raise TypeSignatureError, "Invalid type signature: Unknown type behavior #{sig}" end end |
#assert_valid_arguments_type_sig(sig) ⇒ Object
Checks the arguments type signature is valid
e.g. [Integer], ‘“value”` are valid. Integer is invalid
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/rtype.rb', line 228 def assert_valid_arguments_type_sig(sig) if sig.is_a?(Array) sig = sig.dup if sig.last.is_a?(Hash) kwargs = sig.pop else kwargs = {} end sig.each { |e| assert_valid_argument_type_sig_element(e) } if kwargs.keys.any? { |e| !e.is_a?(Symbol) } raise TypeSignatureError, "Invalid type signature: keyword arguments contain non-symbol key" end kwargs.each_value { |e| assert_valid_argument_type_sig_element(e) } elsif sig.is_a?(Hash) if sig.keys.any? { |e| !e.is_a?(Symbol) } raise TypeSignatureError, "Invalid type signature: keyword arguments contain non-symbol key" end sig.each_value { |e| assert_valid_argument_type_sig_element(e) } else raise TypeSignatureError, "Invalid type signature: arguments type signature is neither array nor hash" end end |
#assert_valid_return_type_sig(sig) ⇒ Object
280 281 282 |
# File 'lib/rtype.rb', line 280 def assert_valid_return_type_sig(sig) assert_valid_argument_type_sig_element(sig) end |
#assert_valid_type_sig(sig) ⇒ Object
Checks the type signature is valid
e.g. ‘[Integer] => Any` is valid. [Integer] or Any are invalid
209 210 211 212 213 214 215 216 217 218 |
# File 'lib/rtype.rb', line 209 def assert_valid_type_sig(sig) unless sig.is_a?(Hash) raise TypeSignatureError, "Invalid type signature: type signature is not hash" end if sig.empty? raise TypeSignatureError, "Invalid type signature: type signature is empty hash" end assert_valid_arguments_type_sig(sig.first[0]) assert_valid_return_type_sig(sig.first[1]) end |
#define_typed_accessor(owner, accessor_name, type_behavior) ⇒ void
This method returns an undefined value.
Calls attr_accessor if the accessor method(getter/setter) is not defined. and makes it typed.
this method uses define_typed_method for getter and setter.
90 91 92 93 94 95 96 97 |
# File 'lib/rtype.rb', line 90 def define_typed_accessor(owner, accessor_name, type_behavior) raise ArgumentError, "accessor_name is nil" if accessor_name.nil? getter = accessor_name.to_sym setter = :"#{accessor_name}=" valid?(type_behavior, nil) define_typed_method owner, getter, [] => type_behavior define_typed_method owner, setter, [type_behavior] => Any end |
#define_typed_method(owner, method_name, type_sig_info) ⇒ void
This method returns an undefined value.
Makes the method typed
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 |
# File 'lib/rtype.rb', line 46 def define_typed_method(owner, method_name, type_sig_info) method_name = method_name.to_sym raise ArgumentError, "method_name is nil" if method_name.nil? assert_valid_type_sig(type_sig_info) el = type_sig_info.first arg_sig = el[0] return_sig = el[1] if arg_sig.is_a?(Array) expected_args = arg_sig.dup if expected_args.last.is_a?(Hash) expected_kwargs = expected_args.pop else expected_kwargs = {} end elsif arg_sig.is_a?(Hash) expected_args = [] expected_kwargs = arg_sig end sig = TypeSignature.new sig.argument_type = arg_sig sig.return_type = return_sig unless @@type_signatures.key?(owner) @@type_signatures[owner] = {} end @@type_signatures[owner][method_name] = sig define_typed_method_to_proxy(owner, method_name, expected_args, expected_kwargs, return_sig) end |
#kwarg_message(key) ⇒ String
147 148 149 |
# File 'lib/rtype.rb', line 147 def (key) "for '#{key}' argument:" end |
#kwarg_type_error_message(key, expected, value) ⇒ String
Returns A error message.
137 138 139 |
# File 'lib/rtype.rb', line 137 def (key, expected, value) "#{(key)}\n" + (expected, value) end |
#nilable(*args) ⇒ Object
18 19 20 |
# File 'lib/rtype/behavior/nilable.rb', line 18 def nilable(*args) Behavior::Nilable[*args] end |
#not(*args) ⇒ Object
21 22 23 |
# File 'lib/rtype/behavior/not.rb', line 21 def not(*args) Behavior::Not[*args] end |
#type_error_message(expected, value) ⇒ String
This method doesn’t check the value is valid
Returns a error message for the pair of type behavior and value
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 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/rtype.rb', line 159 def (expected, value) case expected when Rtype::Behavior::Base expected.(value) when Module "Expected #{value.inspect} to be a #{expected}" when Symbol "Expected #{value.inspect} to respond to :#{expected}" when Regexp "Expected stringified #{value.inspect} to match regexp #{expected.inspect}" when Range "Expected #{value.inspect} to be included in range #{expected.inspect}" when Array arr = expected.map { |e| (e, value) } arr.join("\nOR ") when Hash if value.is_a?(Hash) arr = [] expected.each do |k, v| if v.is_a?(Array) || v.is_a?(Hash) arr << "- #{k} : {\n" + (v, value[k]) + "\n}" else arr << "- #{k} : " + (v, value[k]) end end "Expected #{value.inspect} to be a hash with #{expected.length} elements:\n" + arr.join("\n") else "Expected #{value.inspect} to be a hash" end when Proc "Expected #{value.inspect} to return a truthy value for proc #{expected}" when true "Expected #{value.inspect} to be a truthy value" when false "Expected #{value.inspect} to be a falsy value" when nil # for return "Expected #{value.inspect} to be nil" else raise TypeSignatureError, "Invalid type behavior #{expected}" end end |
#type_signatures ⇒ Hash
type_signatures[method_name]
This is just ‘information’ Any change of this doesn’t affect type checking
104 105 106 |
# File 'lib/rtype.rb', line 104 def type_signatures @@type_signatures end |
#valid?(expected, value) ⇒ Boolean
Checks the value is valid for the type behavior
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
# File 'lib/rtype.rb', line 292 def valid?(expected, value) case expected when Module value.is_a? expected when Symbol value.respond_to? expected when Regexp !!(expected =~ value.to_s) when Range expected.include?(value) when Hash return false unless value.is_a?(Hash) return false unless expected.keys == value.keys expected.all? { |k, v| valid?(v, value[k]) } when Array expected.any? { |e| valid?(e, value) } when Proc !!expected.call(value) when true !!value when false !value when Rtype::Behavior::Base expected.valid? value when nil value.nil? else raise TypeSignatureError, "Invalid type signature: Unknown type behavior #{expected}" end end |