rtype 0.4.0 → 0.5.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/README.md +58 -28
- data/benchmark/benchmark.rb +3 -3
- data/lib/rtype/core_ext.rb +27 -4
- data/lib/rtype/method_annotator.rb +31 -0
- data/lib/rtype/rtype_proxy.rb +10 -0
- data/lib/rtype/version.rb +1 -1
- data/lib/rtype.rb +52 -29
- data/spec/rtype_spec.rb +121 -12
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e11e54455d379c4d6317ad318c97065c003f4de
|
4
|
+
data.tar.gz: 5111741978b57a0ed2741dcc936329bb8590a63b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16573abd845d6ce88f84014bbc7be4ad39a7b5a78dba4613729b00451983ba697d1b7ee2679f76c95bce06b4ae952254ccf1676c739289215f95e04c7418ca6b
|
7
|
+
data.tar.gz: d784a35084da9e02ff50cfd80a8c18867b8a0ca7133a2e4697d15f3e754db56f24ea55037afa398f6203962e93c27ba649036cd41736eefe700f00adc04797db
|
data/README.md
CHANGED
@@ -8,22 +8,22 @@ You can do the type checking in Ruby with this gem!
|
|
8
8
|
```ruby
|
9
9
|
require 'rtype'
|
10
10
|
|
11
|
-
rtype :sum, [:to_i, Numeric] => Numeric
|
12
|
-
def sum(a, b)
|
13
|
-
a.to_i + b
|
14
|
-
end
|
15
|
-
|
16
|
-
sum(123, "asd")
|
17
|
-
# (Rtype::ArgumentTypeError) for 2nd argument:
|
18
|
-
# Expected "asd" to be a Numeric
|
19
|
-
|
20
11
|
class Test
|
21
|
-
|
12
|
+
rtype [:to_i, Numeric] => Numeric
|
13
|
+
def sum(a, b)
|
14
|
+
a.to_i + b
|
15
|
+
end
|
16
|
+
|
17
|
+
rtype {state: Boolean} => Boolean
|
22
18
|
def self.invert(state:)
|
23
19
|
!state
|
24
20
|
end
|
25
21
|
end
|
26
22
|
|
23
|
+
Test.new.sum(123, "asd")
|
24
|
+
# (Rtype::ArgumentTypeError) for 2nd argument:
|
25
|
+
# Expected "asd" to be a Numeric
|
26
|
+
|
27
27
|
Test::invert(state: 0)
|
28
28
|
# (Rtype::ArgumentTypeError) for 'state' argument:
|
29
29
|
# Expected 0 to be a Boolean
|
@@ -102,7 +102,7 @@ then, Rtype use it. (Do not `require 'rtype-java'`)
|
|
102
102
|
- Each of value’s elements must be valid
|
103
103
|
- Value's key list must be equal to the hash's key list
|
104
104
|
- **String** key is **different** from **symbol** key
|
105
|
-
-
|
105
|
+
- vs Keyword arguments
|
106
106
|
- `[{}]` is **not** hash type argument. it is keyword argument because its position is last
|
107
107
|
- `[{}, {}]` is empty hash type argument (first) and one empty keyword argument (second)
|
108
108
|
- `[{}, {}, {}]` is two empty hash type argument (first, second) and empty keyword argument (last)
|
@@ -158,15 +158,15 @@ then, Rtype use it. (Do not `require 'rtype-java'`)
|
|
158
158
|
require 'rtype'
|
159
159
|
|
160
160
|
class Example
|
161
|
-
rtype
|
161
|
+
rtype [Integer] => nil
|
162
162
|
def test(i)
|
163
163
|
end
|
164
164
|
|
165
|
-
rtype
|
165
|
+
rtype [Any] => nil
|
166
166
|
def any_type_arg(arg)
|
167
167
|
end
|
168
168
|
|
169
|
-
rtype
|
169
|
+
rtype [] => Integer
|
170
170
|
def return_type_test
|
171
171
|
"not integer"
|
172
172
|
end
|
@@ -189,13 +189,13 @@ e.return_type_test
|
|
189
189
|
require 'rtype'
|
190
190
|
|
191
191
|
class Example
|
192
|
-
rtype
|
192
|
+
rtype {name: String} => Any
|
193
193
|
def say_your_name(name:)
|
194
194
|
puts "My name is #{name}"
|
195
195
|
end
|
196
196
|
|
197
197
|
# Mixing positional arguments and keyword arguments
|
198
|
-
rtype
|
198
|
+
rtype [String, {age: Integer}] => Any
|
199
199
|
def name_and_age(name, age:)
|
200
200
|
puts "Name: #{name}, Age: #{age}"
|
201
201
|
end
|
@@ -214,7 +214,7 @@ Example.new.say_your_name(name: 12345)
|
|
214
214
|
require 'rtype'
|
215
215
|
|
216
216
|
class Duck
|
217
|
-
rtype
|
217
|
+
rtype [:to_i] => Any
|
218
218
|
def says(i)
|
219
219
|
puts "duck:" + " quack"*i.to_i
|
220
220
|
end
|
@@ -286,7 +286,7 @@ func({msg: "hello hash"}, {}) # hello hash
|
|
286
286
|
```
|
287
287
|
|
288
288
|
#### rtype with attr_accessor
|
289
|
-
`rtype_accessor`
|
289
|
+
`rtype_accessor` : call attr_accessor and make it typed method
|
290
290
|
|
291
291
|
You can use `rtype_accessor_self` for static accessor.
|
292
292
|
|
@@ -295,7 +295,7 @@ require 'rtype'
|
|
295
295
|
|
296
296
|
class Example
|
297
297
|
rtype_accessor :value, String
|
298
|
-
|
298
|
+
|
299
299
|
def initialize
|
300
300
|
@value = 456
|
301
301
|
end
|
@@ -316,9 +316,9 @@ Example.new.value
|
|
316
316
|
require 'rtype'
|
317
317
|
|
318
318
|
class Example
|
319
|
-
rtype
|
319
|
+
rtype [String.and(:func)] => Any
|
320
320
|
# also works:
|
321
|
-
# rtype
|
321
|
+
# rtype [Rtype::and(String, :func)] => Any
|
322
322
|
def and_test(arg)
|
323
323
|
end
|
324
324
|
end
|
@@ -354,7 +354,7 @@ module Game
|
|
354
354
|
class Player < Entity
|
355
355
|
include Rtype::Behavior
|
356
356
|
|
357
|
-
rtype
|
357
|
+
rtype [And[*ENEMY]] => Any
|
358
358
|
def attacks(enemy)
|
359
359
|
"Player attacks '#{enemy.name}' (level #{enemy.level})!"
|
360
360
|
end
|
@@ -375,12 +375,18 @@ Game::Player.new.attacks Game::Slime.new
|
|
375
375
|
# Player attacks 'Powerful Slime' (level 123)!
|
376
376
|
```
|
377
377
|
|
378
|
-
#### Position of `rtype` && (
|
378
|
+
#### Position of `rtype` && (Specify method name || annotation mode) && (Symbol || String)
|
379
379
|
```ruby
|
380
380
|
require 'rtype'
|
381
381
|
|
382
382
|
class Example
|
383
|
-
#
|
383
|
+
# Recommended. Annotation mode (no method name required)
|
384
|
+
rtype [Integer, String] => String
|
385
|
+
def hello_world(i, str)
|
386
|
+
puts "Hello? #{i} #{st
|
387
|
+
end
|
388
|
+
|
389
|
+
# Works (specifying method name)
|
384
390
|
rtype :hello_world, [Integer, String] => String
|
385
391
|
def hello_world(i, str)
|
386
392
|
puts "Hello? #{i} #{st
|
@@ -397,11 +403,17 @@ class Example
|
|
397
403
|
def hello_world_three(i, str)
|
398
404
|
puts "Hello? #{i} #{str}"
|
399
405
|
end
|
406
|
+
|
407
|
+
# Don't works. `rtype` works for next method
|
408
|
+
def hello_world_four(i, str)
|
409
|
+
puts "Hello? #{i} #{str}"
|
410
|
+
end
|
411
|
+
rtype [Integer, String] => String
|
400
412
|
end
|
401
413
|
```
|
402
414
|
|
403
415
|
#### Outside of module (root)
|
404
|
-
|
416
|
+
Outside of module, annotation mode don't works. You must specify method name.
|
405
417
|
|
406
418
|
```ruby
|
407
419
|
rtype :say, [String] => Any
|
@@ -409,11 +421,29 @@ def say(message)
|
|
409
421
|
puts message
|
410
422
|
end
|
411
423
|
|
412
|
-
say "Hello" # Hello
|
424
|
+
Test.new.say "Hello" # Hello
|
425
|
+
|
426
|
+
rtype [String] => Any
|
427
|
+
# (ArgumentError) Annotation mode not working out of module
|
413
428
|
```
|
414
429
|
|
415
430
|
#### Static(singleton) method
|
416
|
-
|
431
|
+
rtype annotation mode works both instance and class method
|
432
|
+
|
433
|
+
```ruby
|
434
|
+
require 'rtype'
|
435
|
+
|
436
|
+
class Example
|
437
|
+
rtype [:to_i] => Any
|
438
|
+
def self.say_ya(i)
|
439
|
+
puts "say" + " ya"*i.to_i
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
Example::say_ya(3) #say ya ya ya
|
444
|
+
```
|
445
|
+
|
446
|
+
however, if you specify method name, you must use `rtype_self` instead of `rtype`
|
417
447
|
|
418
448
|
```ruby
|
419
449
|
require 'rtype'
|
@@ -437,7 +467,7 @@ Any change of this doesn't affect type checking
|
|
437
467
|
require 'rtype'
|
438
468
|
|
439
469
|
class Example
|
440
|
-
rtype
|
470
|
+
rtype [:to_i] => Any
|
441
471
|
def test(i)
|
442
472
|
end
|
443
473
|
end
|
data/benchmark/benchmark.rb
CHANGED
@@ -34,17 +34,17 @@ end
|
|
34
34
|
pure_obj = PureTest.new
|
35
35
|
|
36
36
|
class RtypeTest
|
37
|
-
rtype
|
37
|
+
rtype [Numeric, Numeric] => Numeric
|
38
38
|
def sum(x, y)
|
39
39
|
x + y
|
40
40
|
end
|
41
41
|
|
42
|
-
rtype
|
42
|
+
rtype [:to_i, :to_i] => Numeric
|
43
43
|
def mul(x, y)
|
44
44
|
x * y
|
45
45
|
end
|
46
46
|
|
47
|
-
rtype
|
47
|
+
rtype [Integer, Numeric, String, :to_i] => Any
|
48
48
|
def args(a, b, c, d)
|
49
49
|
end
|
50
50
|
end
|
data/lib/rtype/core_ext.rb
CHANGED
@@ -3,21 +3,35 @@ class TrueClass; include Boolean; end
|
|
3
3
|
class FalseClass; include Boolean; end
|
4
4
|
Any = BasicObject
|
5
5
|
|
6
|
+
class Object
|
7
|
+
include ::Rtype::MethodAnnotator
|
8
|
+
end
|
9
|
+
|
6
10
|
module Kernel
|
7
11
|
private
|
8
12
|
def _rtype_proxy
|
9
13
|
unless @_rtype_proxy
|
10
|
-
@_rtype_proxy =
|
14
|
+
@_rtype_proxy = ::Rtype::RtypeProxy.new
|
11
15
|
prepend @_rtype_proxy
|
12
16
|
end
|
13
17
|
@_rtype_proxy
|
14
18
|
end
|
15
19
|
|
16
|
-
def rtype(method_name, type_sig_info)
|
20
|
+
def rtype(method_name=nil, type_sig_info)
|
17
21
|
if is_a?(Module)
|
18
|
-
|
22
|
+
if method_name.nil?
|
23
|
+
::Rtype::assert_valid_type_sig(type_sig_info)
|
24
|
+
_rtype_proxy.annotation_mode = true
|
25
|
+
_rtype_proxy.annotation_type_sig = type_sig_info
|
26
|
+
else
|
27
|
+
::Rtype::define_typed_method(self, method_name, type_sig_info)
|
28
|
+
end
|
19
29
|
else
|
20
|
-
|
30
|
+
if method_name.nil?
|
31
|
+
raise ArgumentError, "Annotation mode not working out of module"
|
32
|
+
else
|
33
|
+
rtype_self(method_name, type_sig_info)
|
34
|
+
end
|
21
35
|
end
|
22
36
|
end
|
23
37
|
|
@@ -26,6 +40,11 @@ private
|
|
26
40
|
end
|
27
41
|
|
28
42
|
def rtype_accessor(accessor_name, type_behavior)
|
43
|
+
accessor_name = accessor_name.to_sym
|
44
|
+
if !respond_to?(accessor_name) || !respond_to?(:"#{accessor_name}=")
|
45
|
+
attr_accessor accessor_name
|
46
|
+
end
|
47
|
+
|
29
48
|
if is_a?(Module)
|
30
49
|
::Rtype::define_typed_accessor(self, accessor_name, type_behavior)
|
31
50
|
else
|
@@ -34,6 +53,10 @@ private
|
|
34
53
|
end
|
35
54
|
|
36
55
|
def rtype_accessor_self(accessor_name, type_behavior)
|
56
|
+
accessor_name = accessor_name.to_sym
|
57
|
+
if !respond_to?(accessor_name) || !respond_to?(:"#{accessor_name}=")
|
58
|
+
singleton_class.send(:attr_accessor, accessor_name)
|
59
|
+
end
|
37
60
|
::Rtype::define_typed_accessor(singleton_class, accessor_name, type_behavior)
|
38
61
|
end
|
39
62
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Rtype
|
2
|
+
module MethodAnnotator
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def method_added(name)
|
9
|
+
if @_rtype_proxy
|
10
|
+
proxy = _rtype_proxy
|
11
|
+
if proxy.annotation_mode
|
12
|
+
::Rtype::define_typed_method(self, name, proxy.annotation_type_sig)
|
13
|
+
proxy.annotation_mode = false
|
14
|
+
proxy.annotation_type_sig = nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def singleton_method_added(name)
|
20
|
+
if @_rtype_proxy
|
21
|
+
proxy = _rtype_proxy
|
22
|
+
if proxy.annotation_mode
|
23
|
+
::Rtype::define_typed_method(singleton_class, name, proxy.annotation_type_sig)
|
24
|
+
proxy.annotation_mode = false
|
25
|
+
proxy.annotation_type_sig = nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/rtype/version.rb
CHANGED
data/lib/rtype.rb
CHANGED
@@ -15,6 +15,8 @@ else
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
require_relative 'rtype/rtype_proxy'
|
19
|
+
require_relative 'rtype/method_annotator'
|
18
20
|
require_relative 'rtype/core_ext'
|
19
21
|
require_relative 'rtype/version'
|
20
22
|
require_relative 'rtype/type_signature_error'
|
@@ -31,9 +33,9 @@ module Rtype
|
|
31
33
|
@@type_signatures = Hash.new({})
|
32
34
|
|
33
35
|
def define_typed_method(owner, method_name, type_sig_info)
|
34
|
-
raise TypeSignatureError, "Invalid type signature" unless valid_type_sig_info_form?(type_sig_info)
|
35
36
|
method_name = method_name.to_sym
|
36
37
|
raise ArgumentError, "method_name is nil" if method_name.nil?
|
38
|
+
assert_valid_type_sig(type_sig_info)
|
37
39
|
|
38
40
|
el = type_sig_info.first
|
39
41
|
arg_sig = el[0]
|
@@ -51,13 +53,6 @@ module Rtype
|
|
51
53
|
expected_kwargs = arg_sig
|
52
54
|
end
|
53
55
|
|
54
|
-
expected_args.each { |e| check_valid_argument_type_sig(e) }
|
55
|
-
if expected_kwargs.keys.any? { |e| !e.is_a?(Symbol) }
|
56
|
-
raise TypeSignatureError, "Invalid type signature: keyword arguments contain non-symbol key"
|
57
|
-
end
|
58
|
-
expected_kwargs.each_value { |e| check_valid_argument_type_sig(e) }
|
59
|
-
check_valid_return_type_sig(return_sig)
|
60
|
-
|
61
56
|
sig = TypeSignature.new
|
62
57
|
sig.argument_type = arg_sig
|
63
58
|
sig.return_type = return_sig
|
@@ -158,30 +153,41 @@ module Rtype
|
|
158
153
|
end
|
159
154
|
end
|
160
155
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
156
|
+
def assert_valid_type_sig(sig)
|
157
|
+
unless sig.is_a?(Hash)
|
158
|
+
raise TypeSignatureError, "Invalid type signature: type signature is not hash"
|
159
|
+
end
|
160
|
+
if sig.empty?
|
161
|
+
raise TypeSignatureError, "Invalid type signature: type signature is empty hash"
|
162
|
+
end
|
163
|
+
assert_valid_arguments_type_sig(sig.first[0])
|
164
|
+
assert_valid_return_type_sig(sig.first[1])
|
166
165
|
end
|
167
166
|
|
168
|
-
def
|
169
|
-
|
170
|
-
|
171
|
-
if
|
172
|
-
|
173
|
-
result = super(*args, &block)
|
167
|
+
def assert_valid_arguments_type_sig(sig)
|
168
|
+
if sig.is_a?(Array)
|
169
|
+
sig = sig.dup
|
170
|
+
if sig.last.is_a?(Hash)
|
171
|
+
kwargs = sig.pop
|
174
172
|
else
|
175
|
-
|
176
|
-
result = super(*args, **kwargs, &block)
|
173
|
+
kwargs = {}
|
177
174
|
end
|
178
|
-
|
179
|
-
|
175
|
+
sig.each { |e| assert_valid_argument_type_sig_element(e) }
|
176
|
+
if kwargs.keys.any? { |e| !e.is_a?(Symbol) }
|
177
|
+
raise TypeSignatureError, "Invalid type signature: keyword arguments contain non-symbol key"
|
178
|
+
end
|
179
|
+
kwargs.each_value { |e| assert_valid_argument_type_sig_element(e) }
|
180
|
+
elsif sig.is_a?(Hash)
|
181
|
+
if sig.keys.any? { |e| !e.is_a?(Symbol) }
|
182
|
+
raise TypeSignatureError, "Invalid type signature: keyword arguments contain non-symbol key"
|
183
|
+
end
|
184
|
+
sig.each_value { |e| assert_valid_argument_type_sig_element(e) }
|
185
|
+
else
|
186
|
+
raise TypeSignatureError, "Invalid type signature: arguments type signature is neither array nor hash"
|
180
187
|
end
|
181
|
-
nil
|
182
188
|
end
|
183
189
|
|
184
|
-
def
|
190
|
+
def assert_valid_argument_type_sig_element(sig)
|
185
191
|
case sig
|
186
192
|
when Rtype::Behavior::Base
|
187
193
|
when Module
|
@@ -190,11 +196,11 @@ private
|
|
190
196
|
when Range
|
191
197
|
when Array
|
192
198
|
sig.each do |e|
|
193
|
-
|
199
|
+
assert_valid_argument_type_sig_element(e)
|
194
200
|
end
|
195
201
|
when Hash
|
196
202
|
sig.each_value do |e|
|
197
|
-
|
203
|
+
assert_valid_argument_type_sig_element(e)
|
198
204
|
end
|
199
205
|
when Proc
|
200
206
|
when true
|
@@ -204,8 +210,25 @@ private
|
|
204
210
|
end
|
205
211
|
end
|
206
212
|
|
207
|
-
def
|
208
|
-
|
213
|
+
def assert_valid_return_type_sig(sig)
|
214
|
+
assert_valid_argument_type_sig_element(sig) unless sig.nil?
|
215
|
+
end
|
216
|
+
|
217
|
+
private
|
218
|
+
def define_typed_method_to_proxy(owner, method_name, expected_args, expected_kwargs, return_sig)
|
219
|
+
# `send` is faster than `method(...).call`
|
220
|
+
owner.send(:_rtype_proxy).send :define_method, method_name do |*args, **kwargs, &block|
|
221
|
+
if kwargs.empty?
|
222
|
+
::Rtype::assert_arguments_type(expected_args, args)
|
223
|
+
result = super(*args, &block)
|
224
|
+
else
|
225
|
+
::Rtype::assert_arguments_type_with_keywords(expected_args, args, expected_kwargs, kwargs)
|
226
|
+
result = super(*args, **kwargs, &block)
|
227
|
+
end
|
228
|
+
::Rtype::assert_return_type(return_sig, result)
|
229
|
+
result
|
230
|
+
end
|
231
|
+
nil
|
209
232
|
end
|
210
233
|
|
211
234
|
public
|
data/spec/rtype_spec.rb
CHANGED
@@ -62,6 +62,38 @@ describe Rtype do
|
|
62
62
|
end
|
63
63
|
|
64
64
|
describe 'Kernel#rtype' do
|
65
|
+
context "with annotation mode" do
|
66
|
+
it "works with instance method" do
|
67
|
+
class AnnotationTest
|
68
|
+
rtype [String] => Any
|
69
|
+
def test(str)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
expect {
|
73
|
+
AnnotationTest.new.test(123)
|
74
|
+
}.to raise_error Rtype::ArgumentTypeError
|
75
|
+
end
|
76
|
+
it "works with class method" do
|
77
|
+
class AnnotationTest
|
78
|
+
rtype [String] => Any
|
79
|
+
def self.class_method_test(str)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
expect {
|
83
|
+
AnnotationTest::class_method_test(123)
|
84
|
+
}.to raise_error Rtype::ArgumentTypeError
|
85
|
+
end
|
86
|
+
context "outside of module" do
|
87
|
+
it "doesn't works" do
|
88
|
+
expect {
|
89
|
+
rtype [String] => Any
|
90
|
+
def annotation_test(str)
|
91
|
+
end
|
92
|
+
}.to raise_error ArgumentError
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
65
97
|
it "outside of module" do
|
66
98
|
rtype :test_args, [String] => Any
|
67
99
|
def test_args(str)
|
@@ -119,7 +151,6 @@ describe Rtype do
|
|
119
151
|
it 'Kernel#rtype_accessor' do
|
120
152
|
class TestClass
|
121
153
|
rtype_accessor :value, String
|
122
|
-
attr_accessor :value
|
123
154
|
|
124
155
|
def initialize
|
125
156
|
@value = 123
|
@@ -134,12 +165,6 @@ describe Rtype do
|
|
134
165
|
@@val = 123
|
135
166
|
|
136
167
|
rtype_accessor_self :value, String
|
137
|
-
def self.value=(val)
|
138
|
-
@@val = val
|
139
|
-
end
|
140
|
-
def self.value
|
141
|
-
@@val
|
142
|
-
end
|
143
168
|
end
|
144
169
|
expect {TestClass::value = 123}.to raise_error Rtype::ArgumentTypeError
|
145
170
|
expect {TestClass::value}.to raise_error Rtype::ReturnTypeError
|
@@ -198,11 +223,15 @@ describe Rtype do
|
|
198
223
|
end
|
199
224
|
it "is wrong args" do
|
200
225
|
klass.send :rtype, :return_arg, [1..10] => Any
|
201
|
-
expect {
|
226
|
+
expect {
|
227
|
+
instance.return_arg(1001)
|
228
|
+
}.to raise_error Rtype::ArgumentTypeError
|
202
229
|
end
|
203
230
|
it "is wrong result" do
|
204
231
|
klass.send :rtype, :return_nil, [Any] => 1..10
|
205
|
-
expect {
|
232
|
+
expect {
|
233
|
+
instance.return_nil(5)
|
234
|
+
}.to raise_error Rtype::ReturnTypeError
|
206
235
|
end
|
207
236
|
end
|
208
237
|
|
@@ -549,13 +578,13 @@ describe Rtype do
|
|
549
578
|
end
|
550
579
|
|
551
580
|
describe 'wrong case' do
|
552
|
-
describe 'invalid signature
|
553
|
-
it 'invalid
|
581
|
+
describe 'invalid type signature' do
|
582
|
+
it 'invalid arguments type signature' do
|
554
583
|
expect {
|
555
584
|
klass.send :rtype, :return_arg, Any => nil
|
556
585
|
}.to raise_error Rtype::TypeSignatureError
|
557
586
|
end
|
558
|
-
it 'invalid return signature' do
|
587
|
+
it 'invalid return type signature' do
|
559
588
|
expect {
|
560
589
|
klass.send :rtype, :return_arg, [] => 123
|
561
590
|
}.to raise_error Rtype::TypeSignatureError
|
@@ -590,6 +619,18 @@ describe Rtype do
|
|
590
619
|
klass.send :rtype, :return_arg, [] => "abc"
|
591
620
|
}.to raise_error Rtype::TypeSignatureError
|
592
621
|
end
|
622
|
+
|
623
|
+
context "with annotation mode" do
|
624
|
+
it 'works' do
|
625
|
+
expect {
|
626
|
+
class AnnotationTest
|
627
|
+
rtype [String, 123] => Any
|
628
|
+
def invalid_test(arg)
|
629
|
+
end
|
630
|
+
end
|
631
|
+
}.to raise_error Rtype::TypeSignatureError
|
632
|
+
end
|
633
|
+
end
|
593
634
|
end
|
594
635
|
end
|
595
636
|
end
|
@@ -672,6 +713,40 @@ describe Rtype do
|
|
672
713
|
}.to raise_error Rtype::ArgumentTypeError
|
673
714
|
end
|
674
715
|
end
|
716
|
+
|
717
|
+
it "One rtype annotation affect only one method" do
|
718
|
+
class AnnotationTest
|
719
|
+
rtype [String] => Any
|
720
|
+
def one(str)
|
721
|
+
end
|
722
|
+
|
723
|
+
def two(str)
|
724
|
+
end
|
725
|
+
end
|
726
|
+
expect {
|
727
|
+
AnnotationTest.new.one(123)
|
728
|
+
}.to raise_error Rtype::ArgumentTypeError
|
729
|
+
AnnotationTest.new.two(123)
|
730
|
+
end
|
731
|
+
|
732
|
+
it "One rtype annotation affect only one method, regardless of instance method or class method" do
|
733
|
+
class AnnotationTest2
|
734
|
+
rtype [String] => Any
|
735
|
+
def self.static_one(str)
|
736
|
+
end
|
737
|
+
|
738
|
+
def inst_one(str)
|
739
|
+
end
|
740
|
+
|
741
|
+
def self.static_two(str)
|
742
|
+
end
|
743
|
+
end
|
744
|
+
expect {
|
745
|
+
AnnotationTest2::static_one(123)
|
746
|
+
}.to raise_error Rtype::ArgumentTypeError
|
747
|
+
AnnotationTest2.new.inst_one(123)
|
748
|
+
AnnotationTest2::static_two(123)
|
749
|
+
end
|
675
750
|
end
|
676
751
|
|
677
752
|
describe "Call Rtype`s static method directly" do
|
@@ -687,6 +762,12 @@ describe Rtype do
|
|
687
762
|
end
|
688
763
|
|
689
764
|
it 'Rtype::valid?' do
|
765
|
+
expect(
|
766
|
+
Rtype::valid?(String, "str")
|
767
|
+
).to be true
|
768
|
+
expect(
|
769
|
+
Rtype::valid?(Integer, "str")
|
770
|
+
).to be false
|
690
771
|
expect {
|
691
772
|
Rtype::valid?("Invalid type behavior", "Test Value")
|
692
773
|
}.to raise_error Rtype::TypeSignatureError
|
@@ -709,5 +790,33 @@ describe Rtype do
|
|
709
790
|
Rtype::assert_return_type nil, "No nil"
|
710
791
|
}.to raise_error Rtype::ReturnTypeError
|
711
792
|
end
|
793
|
+
|
794
|
+
it 'Rtype::assert_valid_type_sig' do
|
795
|
+
Rtype::assert_valid_type_sig([Integer, String] => Any)
|
796
|
+
expect {
|
797
|
+
Rtype::assert_valid_type_sig([Integer, String])
|
798
|
+
}.to raise_error Rtype::TypeSignatureError
|
799
|
+
end
|
800
|
+
|
801
|
+
it 'Rtype::assert_valid_arguments_type_sig' do
|
802
|
+
Rtype::assert_valid_arguments_type_sig([Integer, String])
|
803
|
+
expect {
|
804
|
+
Rtype::assert_valid_arguments_type_sig("[Integer, String]")
|
805
|
+
}.to raise_error Rtype::TypeSignatureError
|
806
|
+
end
|
807
|
+
|
808
|
+
it 'Rtype::assert_valid_argument_type_sig_element' do
|
809
|
+
Rtype::assert_valid_argument_type_sig_element(Integer)
|
810
|
+
expect {
|
811
|
+
Rtype::assert_valid_argument_type_sig_element("Integer")
|
812
|
+
}.to raise_error Rtype::TypeSignatureError
|
813
|
+
end
|
814
|
+
|
815
|
+
it 'Rtype::assert_valid_return_type_sig' do
|
816
|
+
Rtype::assert_valid_return_type_sig(Integer)
|
817
|
+
expect {
|
818
|
+
Rtype::assert_valid_return_type_sig("Integer")
|
819
|
+
}.to raise_error Rtype::TypeSignatureError
|
820
|
+
end
|
712
821
|
end
|
713
822
|
end
|
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.5.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-04-
|
11
|
+
date: 2016-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -75,7 +75,9 @@ files:
|
|
75
75
|
- lib/rtype/behavior/or.rb
|
76
76
|
- lib/rtype/behavior/xor.rb
|
77
77
|
- lib/rtype/core_ext.rb
|
78
|
+
- lib/rtype/method_annotator.rb
|
78
79
|
- lib/rtype/return_type_error.rb
|
80
|
+
- lib/rtype/rtype_proxy.rb
|
79
81
|
- lib/rtype/type_signature.rb
|
80
82
|
- lib/rtype/type_signature_error.rb
|
81
83
|
- lib/rtype/version.rb
|