rtype 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/README.md +46 -68
- data/benchmark/benchmark.rb +36 -1
- data/lib/rtype/behavior/nilable.rb +1 -1
- data/lib/rtype/version.rb +1 -1
- data/lib/rtype.rb +121 -82
- data/spec/rtype_spec.rb +104 -0
- data/spec/spec_helper.rb +4 -5
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c238c2b45a71c23c3d5c3a4f442d7c71f512b05b
|
4
|
+
data.tar.gz: a4068b256226cc7b8b16e1dbb31c1c086e892fb1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a71adbd7caa172f8aeda43b017f9e8a28ff57851c96e21a4461177b24fa0e242624db8193482e07bfda8999b687179507648693eac8fd9eedcd8bbbedee84f4a
|
7
|
+
data.tar.gz: 0d308aeadfa63866b391c219c2d3e162722221aed6c8e6480ebc72b7fb0f934f32d173a12cef40c23a6d909425efea898dbe56129f5877c1f1ff848cd402395f
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -31,9 +31,9 @@ Test::invert(state: 0)
|
|
31
31
|
|
32
32
|
## Requirements
|
33
33
|
- Ruby >= 2.1
|
34
|
+
- MRI or RBX if native extension is used. Rtype itself without it is pure-ruby gem, therefore you can use Rtype in JRuby, etc.
|
34
35
|
|
35
36
|
## Features
|
36
|
-
- Very simple
|
37
37
|
- Provide type checking for argument and return
|
38
38
|
- Support type checking for [keyword argument](#keyword-argument)
|
39
39
|
- [Type checking for array elements](#array)
|
@@ -48,6 +48,14 @@ And add to your `.rb` source file:
|
|
48
48
|
require 'rtype'
|
49
49
|
```
|
50
50
|
|
51
|
+
### Native extension
|
52
|
+
Rtype itself is pure-ruby gem. but you can make it more faster by native extension.
|
53
|
+
|
54
|
+
Just run `gem install rtype-native` or add `gem 'rtype-native'` to your `Gemfile`, then Rtype use it.
|
55
|
+
(Do not `require 'rtype-native'`)
|
56
|
+
|
57
|
+
It is only for MRI or RBX. JRuby extension not supported yet.
|
58
|
+
|
51
59
|
## Usage
|
52
60
|
|
53
61
|
### Supported Type Behaviors
|
@@ -360,100 +368,70 @@ Example.new.method(:test).return_type
|
|
360
368
|
## Benchmarks
|
361
369
|
Result of `rake benchmark` ([source](https://github.com/sputnikgugja/rtype/tree/master/benchmark/benchmark.rb))
|
362
370
|
|
363
|
-
The benchmark doesn't include `Rubype` gem because I can't install Rubype on my environment.
|
364
|
-
|
365
371
|
### MRI
|
366
|
-
Rtype is 1.56x faster than Sig and 2.85x faster than Contracts
|
367
|
-
|
368
372
|
```
|
369
373
|
Ruby version: 2.1.7
|
370
374
|
Ruby engine: ruby
|
371
375
|
Ruby description: ruby 2.1.7p400 (2015-08-18 revision 51632) [x64-mingw32]
|
372
|
-
Rtype version: 0.
|
376
|
+
Rtype version: 0.2.0
|
377
|
+
Rubype version: 0.3.1
|
373
378
|
Sig version: 1.0.1
|
374
379
|
Contracts version: 0.13.0
|
375
380
|
Typecheck version: 0.1.2
|
376
381
|
Warming up --------------------------------------
|
377
|
-
pure
|
378
|
-
rtype
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
+
pure 85.600k i/100ms
|
383
|
+
rtype 25.735k i/100ms
|
384
|
+
rubype 20.922k i/100ms
|
385
|
+
sig 8.960k i/100ms
|
386
|
+
contracts 4.659k i/100ms
|
387
|
+
typecheck 1.102k i/100ms
|
382
388
|
Calculating -------------------------------------
|
383
|
-
pure
|
384
|
-
rtype
|
385
|
-
|
386
|
-
|
387
|
-
|
389
|
+
pure 3.273M (± 2.4%) i/s - 16.435M
|
390
|
+
rtype 340.376k (± 1.9%) i/s - 1.724M
|
391
|
+
rubype 268.253k (± 4.2%) i/s - 1.339M
|
392
|
+
sig 100.050k (± 1.9%) i/s - 501.760k
|
393
|
+
contracts 50.027k (± 2.0%) i/s - 251.586k
|
394
|
+
typecheck 11.317k (± 1.4%) i/s - 57.304k
|
388
395
|
|
389
396
|
Comparison:
|
390
|
-
pure:
|
391
|
-
rtype:
|
392
|
-
|
393
|
-
|
394
|
-
|
397
|
+
pure: 3272978.0 i/s
|
398
|
+
rtype: 340375.8 i/s - 9.62x slower
|
399
|
+
rubype: 268252.5 i/s - 12.20x slower
|
400
|
+
sig: 100050.1 i/s - 32.71x slower
|
401
|
+
contracts: 50026.9 i/s - 65.42x slower
|
402
|
+
typecheck: 11317.1 i/s - 289.21x slower
|
395
403
|
```
|
396
404
|
|
397
405
|
### JRuby
|
398
|
-
|
406
|
+
Without Rubype that doesn't support JRuby
|
399
407
|
|
400
408
|
```
|
401
|
-
# Test 1
|
402
|
-
Ruby version: 2.2.3
|
403
|
-
Ruby engine: jruby
|
404
|
-
Ruby description: jruby 9.0.5.0 (2.2.3) 2016-01-26 7bee00d Java HotSpot(TM) 64-Bit Server VM 25.60-b23 on 1.8.0_60-b27 +jit [Windows 10-amd64]
|
405
|
-
Rtype version: 0.1.1
|
406
|
-
Sig version: 1.0.1
|
407
|
-
Contracts version: 0.13.0
|
408
|
-
Typecheck version: 0.1.2
|
409
|
-
Warming up --------------------------------------
|
410
|
-
pure 7.415k i/100ms
|
411
|
-
rtype 883.000 i/100ms
|
412
|
-
sig 922.000 i/100ms
|
413
|
-
contracts 408.000 i/100ms
|
414
|
-
typecheck 404.000 i/100ms
|
415
|
-
Calculating -------------------------------------
|
416
|
-
pure 4.242M (±46.3%) i/s - 16.795M
|
417
|
-
rtype 55.772k (±29.1%) i/s - 249.006k
|
418
|
-
sig 29.344k (±23.5%) i/s - 134.612k
|
419
|
-
contracts 12.192k (±29.4%) i/s - 51.816k
|
420
|
-
typecheck 7.503k (±23.5%) i/s - 35.148k
|
421
|
-
|
422
|
-
Comparison:
|
423
|
-
pure: 4241753.6 i/s
|
424
|
-
rtype: 55771.7 i/s - 76.06x slower
|
425
|
-
sig: 29344.3 i/s - 144.55x slower
|
426
|
-
contracts: 12192.0 i/s - 347.91x slower
|
427
|
-
typecheck: 7502.8 i/s - 565.36x slower
|
428
|
-
```
|
429
|
-
```
|
430
|
-
# Test 2
|
431
409
|
Ruby version: 2.2.3
|
432
410
|
Ruby engine: jruby
|
433
411
|
Ruby description: jruby 9.0.5.0 (2.2.3) 2016-01-26 7bee00d Java HotSpot(TM) 64-Bit Server VM 25.60-b23 on 1.8.0_60-b27 +jit [Windows 10-amd64]
|
434
|
-
Rtype version: 0.
|
412
|
+
Rtype version: 0.2.0
|
435
413
|
Sig version: 1.0.1
|
436
414
|
Contracts version: 0.13.0
|
437
415
|
Typecheck version: 0.1.2
|
438
416
|
Warming up --------------------------------------
|
439
|
-
pure
|
440
|
-
rtype
|
441
|
-
sig
|
442
|
-
contracts
|
443
|
-
typecheck
|
417
|
+
pure 29.127k i/100ms
|
418
|
+
rtype 4.566k i/100ms
|
419
|
+
sig 4.162k i/100ms
|
420
|
+
contracts 776.000 i/100ms
|
421
|
+
typecheck 981.000 i/100ms
|
444
422
|
Calculating -------------------------------------
|
445
|
-
pure
|
446
|
-
rtype
|
447
|
-
sig
|
448
|
-
contracts
|
449
|
-
typecheck
|
423
|
+
pure 6.705M (±12.0%) i/s - 32.826M
|
424
|
+
rtype 89.262k (± 3.3%) i/s - 447.468k
|
425
|
+
sig 74.070k (± 2.0%) i/s - 370.418k
|
426
|
+
contracts 25.399k (± 2.9%) i/s - 127.264k
|
427
|
+
typecheck 12.461k (± 9.0%) i/s - 61.803k
|
450
428
|
|
451
429
|
Comparison:
|
452
|
-
pure:
|
453
|
-
rtype:
|
454
|
-
sig:
|
455
|
-
contracts:
|
456
|
-
typecheck:
|
430
|
+
pure: 6705166.5 i/s
|
431
|
+
rtype: 89262.5 i/s - 75.12x slower
|
432
|
+
sig: 74070.1 i/s - 90.52x slower
|
433
|
+
contracts: 25398.9 i/s - 263.99x slower
|
434
|
+
typecheck: 12460.7 i/s - 538.10x slower
|
457
435
|
```
|
458
436
|
|
459
437
|
## Rubype, Sig
|
data/benchmark/benchmark.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'benchmark/ips'
|
2
2
|
|
3
|
-
|
3
|
+
is_mri = RUBY_ENGINE == 'ruby'
|
4
|
+
|
5
|
+
require "rtype"
|
6
|
+
require "rubype" if is_mri
|
4
7
|
require "sig"
|
5
8
|
require "contracts"
|
6
9
|
require "contracts/version"
|
@@ -11,6 +14,7 @@ puts "Ruby engine: #{RUBY_ENGINE}"
|
|
11
14
|
puts "Ruby description: #{RUBY_DESCRIPTION}"
|
12
15
|
|
13
16
|
puts "Rtype version: #{Rtype::VERSION}"
|
17
|
+
puts "Rubype version: #{Rubype::VERSION}" if is_mri
|
14
18
|
puts "Sig version: #{Sig::VERSION}"
|
15
19
|
puts "Contracts version: #{Contracts::VERSION}"
|
16
20
|
puts "Typecheck version: #{Typecheck::VERSION}"
|
@@ -46,6 +50,25 @@ class RtypeTest
|
|
46
50
|
end
|
47
51
|
rtype_obj = RtypeTest.new
|
48
52
|
|
53
|
+
if is_mri
|
54
|
+
class RubypeTest
|
55
|
+
def sum(x, y)
|
56
|
+
x + y
|
57
|
+
end
|
58
|
+
typesig :sum, [Numeric, Numeric] => Numeric
|
59
|
+
|
60
|
+
def mul(x, y)
|
61
|
+
x * y
|
62
|
+
end
|
63
|
+
typesig :mul, [:to_i, :to_i] => Numeric
|
64
|
+
|
65
|
+
def args(a, b, c, d)
|
66
|
+
end
|
67
|
+
typesig :args, [Integer, Numeric, String, :to_i] => Any
|
68
|
+
end
|
69
|
+
rubype_obj = RubypeTest.new
|
70
|
+
end
|
71
|
+
|
49
72
|
class SigTest
|
50
73
|
sig [Numeric, Numeric], Numeric,
|
51
74
|
def sum(x, y)
|
@@ -123,6 +146,18 @@ Benchmark.ips do |x|
|
|
123
146
|
end
|
124
147
|
end
|
125
148
|
|
149
|
+
if is_mri
|
150
|
+
x.report("rubype") do |times|
|
151
|
+
i = 0
|
152
|
+
while i < times
|
153
|
+
rubype_obj.sum(1, 2)
|
154
|
+
rubype_obj.mul(1, 2)
|
155
|
+
rubype_obj.args(1, 2, "c", 4)
|
156
|
+
i += 1
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
126
161
|
x.report("sig") do |times|
|
127
162
|
i = 0
|
128
163
|
while i < times
|
data/lib/rtype/version.rb
CHANGED
data/lib/rtype.rb
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
begin
|
2
|
+
require "rtype/rtype_native"
|
3
|
+
puts "Rtype with native extension"
|
4
|
+
rescue LoadError
|
5
|
+
puts "Rtype without native extension"
|
6
|
+
end
|
7
|
+
|
1
8
|
require_relative 'rtype/core_ext'
|
2
9
|
require_relative 'rtype/version'
|
3
10
|
require_relative 'rtype/type_signature_error'
|
@@ -45,18 +52,7 @@ module Rtype
|
|
45
52
|
sig.return_type = return_sig
|
46
53
|
@@type_signatures[owner][method_name] = sig
|
47
54
|
|
48
|
-
|
49
|
-
owner.send(:_rtype_proxy).send :define_method, method_name do |*args, **kwargs, &block|
|
50
|
-
if kwargs.empty?
|
51
|
-
::Rtype.assert_arguments_type(expected_args, args)
|
52
|
-
result = super(*args, &block)
|
53
|
-
else
|
54
|
-
::Rtype.assert_arguments_type_with_keywords(expected_args, args, expected_kwargs, kwargs)
|
55
|
-
result = super(*args, **kwargs, &block)
|
56
|
-
end
|
57
|
-
::Rtype.assert_return_type(return_sig, result)
|
58
|
-
result
|
59
|
-
end
|
55
|
+
define_typed_method_to_proxy(owner, method_name, expected_args, expected_kwargs, return_sig)
|
60
56
|
end
|
61
57
|
|
62
58
|
def define_typed_accessor(owner, accessor_name, type_behavior)
|
@@ -67,51 +63,10 @@ module Rtype
|
|
67
63
|
define_typed_method owner, setter, [type_behavior] => Any
|
68
64
|
end
|
69
65
|
|
70
|
-
# validate argument type
|
71
|
-
def valid?(expected, value)
|
72
|
-
case expected
|
73
|
-
when Module
|
74
|
-
value.is_a? expected
|
75
|
-
when Symbol
|
76
|
-
value.respond_to? expected
|
77
|
-
when Regexp
|
78
|
-
!!(expected =~ value.to_s)
|
79
|
-
when Range
|
80
|
-
expected.include?(value)
|
81
|
-
when Array
|
82
|
-
return false unless value.is_a?(Array)
|
83
|
-
return false unless expected.length == value.length
|
84
|
-
idx = -1
|
85
|
-
expected.all? { |e| idx += 1; valid?(e, value[idx]) }
|
86
|
-
when Proc
|
87
|
-
!!expected.call(value)
|
88
|
-
when true
|
89
|
-
!!value
|
90
|
-
when false
|
91
|
-
!value
|
92
|
-
when Rtype::Behavior::Base
|
93
|
-
expected.valid? value
|
94
|
-
else
|
95
|
-
raise TypeSignatureError, "Invalid type signature: Unknown type behavior #{expected}"
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
66
|
def type_signatures
|
100
67
|
@@type_signatures
|
101
68
|
end
|
102
69
|
|
103
|
-
def assert_arguments_type(expected_args, args)
|
104
|
-
# `length.times` is faster than `each_with_index`
|
105
|
-
args.length.times do |i|
|
106
|
-
expected = expected_args[i]
|
107
|
-
value = args[i]
|
108
|
-
unless expected.nil?
|
109
|
-
unless valid?(expected, value)
|
110
|
-
raise ArgumentTypeError, "for #{(i+1).ordinalize} argument:\n" + type_error_message(expected, value)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
70
|
=begin
|
116
71
|
def assert_keyword_arguments_type(expected_kwargs, kwargs)
|
117
72
|
kwargs.each do |key, value|
|
@@ -124,39 +79,24 @@ module Rtype
|
|
124
79
|
end
|
125
80
|
end
|
126
81
|
=end
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
expected = expected_args[i]
|
131
|
-
value = args[i]
|
132
|
-
unless expected.nil?
|
133
|
-
unless valid?(expected, value)
|
134
|
-
raise ArgumentTypeError, "for #{(i+1).ordinalize} argument:\n" + type_error_message(expected, value)
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
kwargs.each do |key, value|
|
139
|
-
expected = expected_kwargs[key]
|
140
|
-
unless expected.nil?
|
141
|
-
unless valid?(expected, value)
|
142
|
-
raise ArgumentTypeError, "for '#{key}' argument:\n" + type_error_message(expected, value)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
82
|
+
|
83
|
+
def arg_type_error_message(idx, expected, value)
|
84
|
+
"#{arg_message(idx)}\n" + type_error_message(expected, value)
|
146
85
|
end
|
147
86
|
|
148
|
-
def
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
87
|
+
def kwarg_type_error_message(key, expected, value)
|
88
|
+
"#{kwarg_message(key)}\n" + type_error_message(expected, value)
|
89
|
+
end
|
90
|
+
|
91
|
+
def arg_message(idx)
|
92
|
+
"for #{(idx+1).ordinalize} argument:"
|
93
|
+
end
|
94
|
+
|
95
|
+
def kwarg_message(key)
|
96
|
+
"for '#{key}' argument:"
|
158
97
|
end
|
159
98
|
|
99
|
+
|
160
100
|
def type_error_message(expected, value)
|
161
101
|
case expected
|
162
102
|
when Rtype::Behavior::Base
|
@@ -199,5 +139,104 @@ module Rtype
|
|
199
139
|
arg_sig = hash.first[0]
|
200
140
|
arg_sig.is_a?(Array) || arg_sig.is_a?(Hash)
|
201
141
|
end
|
142
|
+
|
143
|
+
def define_typed_method_to_proxy(owner, method_name, expected_args, expected_kwargs, return_sig)
|
144
|
+
# `send` is faster than `method(...).call`
|
145
|
+
owner.send(:_rtype_proxy).send :define_method, method_name do |*args, **kwargs, &block|
|
146
|
+
if kwargs.empty?
|
147
|
+
::Rtype.assert_arguments_type(expected_args, args)
|
148
|
+
result = super(*args, &block)
|
149
|
+
else
|
150
|
+
::Rtype.assert_arguments_type_with_keywords(expected_args, args, expected_kwargs, kwargs)
|
151
|
+
result = super(*args, **kwargs, &block)
|
152
|
+
end
|
153
|
+
::Rtype.assert_return_type(return_sig, result)
|
154
|
+
result
|
155
|
+
end
|
156
|
+
nil
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
unless self.respond_to?(:valid?)
|
161
|
+
# validate argument type
|
162
|
+
def self.valid?(expected, value)
|
163
|
+
case expected
|
164
|
+
when Module
|
165
|
+
value.is_a? expected
|
166
|
+
when Symbol
|
167
|
+
value.respond_to? expected
|
168
|
+
when Regexp
|
169
|
+
!!(expected =~ value.to_s)
|
170
|
+
when Range
|
171
|
+
expected.include?(value)
|
172
|
+
when Array
|
173
|
+
return false unless value.is_a?(Array)
|
174
|
+
return false unless expected.length == value.length
|
175
|
+
idx = -1
|
176
|
+
expected.all? { |e| idx += 1; valid?(e, value[idx]) }
|
177
|
+
when Proc
|
178
|
+
!!expected.call(value)
|
179
|
+
when true
|
180
|
+
!!value
|
181
|
+
when false
|
182
|
+
!value
|
183
|
+
when Rtype::Behavior::Base
|
184
|
+
expected.valid? value
|
185
|
+
else
|
186
|
+
raise TypeSignatureError, "Invalid type signature: Unknown type behavior #{expected}"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
unless self.respond_to?(:assert_arguments_type)
|
192
|
+
def self.assert_arguments_type(expected_args, args)
|
193
|
+
# `length.times` is faster than `each_with_index`
|
194
|
+
args.length.times do |i|
|
195
|
+
expected = expected_args[i]
|
196
|
+
value = args[i]
|
197
|
+
unless expected.nil?
|
198
|
+
unless valid?(expected, value)
|
199
|
+
raise ArgumentTypeError, "for #{(i+1).ordinalize} argument:\n" + type_error_message(expected, value)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
unless self.respond_to?(:assert_arguments_type_with_keywords)
|
207
|
+
def self.assert_arguments_type_with_keywords(expected_args, args, expected_kwargs, kwargs)
|
208
|
+
# `length.times` is faster than `each_with_index`
|
209
|
+
args.length.times do |i|
|
210
|
+
expected = expected_args[i]
|
211
|
+
value = args[i]
|
212
|
+
unless expected.nil?
|
213
|
+
unless valid?(expected, value)
|
214
|
+
raise ArgumentTypeError, "#{arg_message(idx)}\n" + type_error_message(expected, value)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
kwargs.each do |key, value|
|
219
|
+
expected = expected_kwargs[key]
|
220
|
+
unless expected.nil?
|
221
|
+
unless valid?(expected, value)
|
222
|
+
raise ArgumentTypeError, "#{kwarg_message(key)}\n" + type_error_message(expected, value)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
unless self.respond_to?(:assert_return_type)
|
230
|
+
def self.assert_return_type(expected, result)
|
231
|
+
if expected.nil?
|
232
|
+
unless result.nil?
|
233
|
+
raise ReturnTypeError, "for return:\n" + type_error_message(expected, result)
|
234
|
+
end
|
235
|
+
else
|
236
|
+
unless valid?(expected, result)
|
237
|
+
raise ReturnTypeError, "for return:\n" + type_error_message(expected, result)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
202
241
|
end
|
203
242
|
end
|
data/spec/rtype_spec.rb
CHANGED
@@ -3,10 +3,22 @@ require_relative 'spec_helper'
|
|
3
3
|
describe Rtype do
|
4
4
|
let(:klass) do
|
5
5
|
Class.new do
|
6
|
+
attr_accessor :value
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@value = 123
|
10
|
+
end
|
11
|
+
|
6
12
|
def return_arg(obj)
|
7
13
|
obj
|
8
14
|
end
|
9
15
|
|
16
|
+
def three_args(a, b, c)
|
17
|
+
end
|
18
|
+
|
19
|
+
def three_kwargs(a:, b:, c:)
|
20
|
+
end
|
21
|
+
|
10
22
|
def return_nil(obj)
|
11
23
|
nil
|
12
24
|
end
|
@@ -265,6 +277,40 @@ describe Rtype do
|
|
265
277
|
}.to raise_error Rtype::TypeSignatureError
|
266
278
|
end
|
267
279
|
end
|
280
|
+
|
281
|
+
describe 'Special type behaviors' do
|
282
|
+
it 'Rtype::Behavior::And' do
|
283
|
+
klass.send :rtype, :return_nil, [Rtype.and(:to_i, :chars)] => nil
|
284
|
+
instance.return_nil("Hello")
|
285
|
+
expect {instance.return_nil(123)}.to raise_error Rtype::ArgumentTypeError
|
286
|
+
end
|
287
|
+
|
288
|
+
it 'Rtype::Behavior::Or' do
|
289
|
+
klass.send :rtype, :return_nil, [Rtype.or(Integer, String)] => nil
|
290
|
+
instance.return_nil(123)
|
291
|
+
instance.return_nil("abc")
|
292
|
+
expect {instance.return_nil(nil)}.to raise_error Rtype::ArgumentTypeError
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'Rtype::Behavior::Nilable' do
|
296
|
+
klass.send :rtype, :return_nil, [Rtype.nilable(Integer)] => nil
|
297
|
+
instance.return_nil(nil)
|
298
|
+
instance.return_nil(123)
|
299
|
+
expect {instance.return_nil("abc")}.to raise_error Rtype::ArgumentTypeError
|
300
|
+
end
|
301
|
+
|
302
|
+
it 'Rtype::Behavior::Not' do
|
303
|
+
klass.send :rtype, :return_nil, [Rtype.not(String)] => nil
|
304
|
+
instance.return_nil(123)
|
305
|
+
expect {instance.return_nil("abc")}.to raise_error Rtype::ArgumentTypeError
|
306
|
+
end
|
307
|
+
|
308
|
+
it 'Rtype::Behavior::Xor' do
|
309
|
+
klass.send :rtype, :return_nil, [Rtype.xor(:to_i, String)] => nil
|
310
|
+
instance.return_nil(123)
|
311
|
+
expect {instance.return_nil("abc")}.to raise_error Rtype::ArgumentTypeError
|
312
|
+
end
|
313
|
+
end
|
268
314
|
end
|
269
315
|
|
270
316
|
describe 'Signature' do
|
@@ -433,5 +479,63 @@ describe Rtype do
|
|
433
479
|
expect {instance.private_func}.to raise_error NoMethodError
|
434
480
|
end
|
435
481
|
end
|
482
|
+
|
483
|
+
context 'with empty argument signature' do
|
484
|
+
it 'accept any arguments' do
|
485
|
+
klass.send :rtype, :three_args, [] => Any
|
486
|
+
instance.three_args("abc", 123, 456)
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
context 'when args length is more than arg signature length' do
|
491
|
+
it 'type checking ignore rest args' do
|
492
|
+
klass.send :rtype, :three_args, [String] => Any
|
493
|
+
instance.three_args("abc", 123, 456)
|
494
|
+
end
|
495
|
+
end
|
496
|
+
|
497
|
+
context 'when keyword args contain a key not configured to rtype' do
|
498
|
+
it 'type checking ignore the key' do
|
499
|
+
klass.send :rtype, :three_kwargs, {a: String} => Any
|
500
|
+
instance.three_kwargs(a: "abc", b: 123, c: 456)
|
501
|
+
end
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
describe "Call Rtype`s static method directly" do
|
506
|
+
it 'Rtype::define_typed_method' do
|
507
|
+
Rtype::define_typed_method klass, :return_arg, [String] => Any
|
508
|
+
expect {instance.return_arg(123)}.to raise_error Rtype::ArgumentTypeError
|
509
|
+
end
|
510
|
+
|
511
|
+
it 'Rtype::define_typed_accessor' do
|
512
|
+
Rtype::define_typed_accessor klass, :value, String
|
513
|
+
expect { instance.value = 123 }.to raise_error Rtype::ArgumentTypeError
|
514
|
+
expect { instance.value }.to raise_error Rtype::ReturnTypeError
|
515
|
+
end
|
516
|
+
|
517
|
+
it 'Rtype::valid?' do
|
518
|
+
expect {
|
519
|
+
Rtype::valid?("Invalid type behavior", "Test Value")
|
520
|
+
}.to raise_error Rtype::TypeSignatureError
|
521
|
+
end
|
522
|
+
|
523
|
+
it 'Rtype::assert_arguments_type' do
|
524
|
+
expect {
|
525
|
+
Rtype::assert_arguments_type([Integer, String], [123, 123])
|
526
|
+
}.to raise_error Rtype::ArgumentTypeError
|
527
|
+
end
|
528
|
+
|
529
|
+
it 'Rtype::assert_arguments_type_with_keywords' do
|
530
|
+
expect {
|
531
|
+
Rtype::assert_arguments_type_with_keywords([Integer, String], [123, "abc"], {arg: String}, {arg: 123})
|
532
|
+
}.to raise_error Rtype::ArgumentTypeError
|
533
|
+
end
|
534
|
+
|
535
|
+
it 'Rtype::assert_return_type' do
|
536
|
+
expect {
|
537
|
+
Rtype::assert_return_type nil, "No nil"
|
538
|
+
}.to raise_error Rtype::ReturnTypeError
|
539
|
+
end
|
436
540
|
end
|
437
541
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rtype
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sputnik Gugja
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -90,7 +90,7 @@ require_paths:
|
|
90
90
|
- lib
|
91
91
|
required_ruby_version: !ruby/object:Gem::Requirement
|
92
92
|
requirements:
|
93
|
-
- - "
|
93
|
+
- - "~>"
|
94
94
|
- !ruby/object:Gem::Version
|
95
95
|
version: '2.1'
|
96
96
|
required_rubygems_version: !ruby/object:Gem::Requirement
|