rtype 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|