rtype 0.3.0 → 0.4.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 +78 -10
- data/lib/rtype/behavior/core_ext.rb +22 -0
- data/lib/rtype/behavior/nilable.rb +1 -1
- data/lib/rtype/behavior/not.rb +1 -1
- data/lib/rtype/behavior/or.rb +1 -1
- data/lib/rtype/behavior/xor.rb +1 -1
- data/lib/rtype/behavior.rb +2 -1
- data/lib/rtype/version.rb +1 -1
- data/lib/rtype.rb +53 -8
- data/spec/rtype_spec.rb +192 -26
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4bad8e7cdc12a3c4a598e806553fd89c184c212
|
4
|
+
data.tar.gz: 67576b9e8839a9f1988ee4f561cb0474824ecb84
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b82873431c88b2811b9ee34bdd84a3f23e683cbf4baaba9c57da29954b34869a3739db623496f0e07af92b8eab5750d10d523b3e93c3cf91080a5a36c5dd5fb
|
7
|
+
data.tar.gz: 29a5f2356be7ed7637841a0a240689cd11f7d19f73ce5b5447c8ec99bb497ee931e2c48706048efacffe4d15c7a73619b184b49e53bbb9c920dfd328905e4954
|
data/README.md
CHANGED
@@ -31,15 +31,16 @@ Test::invert(state: 0)
|
|
31
31
|
|
32
32
|
## Requirements
|
33
33
|
- Ruby >= 2.1
|
34
|
-
- MRI
|
34
|
+
- MRI
|
35
35
|
- If C native extension is used, otherwise it is not required
|
36
36
|
- JRuby
|
37
37
|
- If Java extension is used, otherwise it is not required
|
38
38
|
|
39
39
|
## Features
|
40
|
-
- Provide type checking for
|
40
|
+
- Provide type checking for arguments and return
|
41
41
|
- Support type checking for [keyword argument](#keyword-argument)
|
42
42
|
- [Type checking for array elements](#array)
|
43
|
+
- [Type checking for hash elements](#hash)
|
43
44
|
- [Duck typing](#duck-typing)
|
44
45
|
- Custom type behavior
|
45
46
|
|
@@ -54,7 +55,7 @@ require 'rtype'
|
|
54
55
|
### Native extension
|
55
56
|
Rtype itself is pure-ruby gem. but you can make it more faster by using native extension.
|
56
57
|
|
57
|
-
#### Native extension for MRI
|
58
|
+
#### Native extension for MRI
|
58
59
|
Just run
|
59
60
|
```ruby
|
60
61
|
gem install rtype-native
|
@@ -96,6 +97,18 @@ then, Rtype use it. (Do not `require 'rtype-java'`)
|
|
96
97
|
- Of course, nested array works
|
97
98
|
- Example: [Array](#array)
|
98
99
|
- This can be used as a tuple
|
100
|
+
- `Hash`
|
101
|
+
- Value must be an hash
|
102
|
+
- Each of value’s elements must be valid
|
103
|
+
- Value's key list must be equal to the hash's key list
|
104
|
+
- **String** key is **different** from **symbol** key
|
105
|
+
- The type signature could not be positioned at last index
|
106
|
+
- `[{}]` is **not** hash type argument. it is keyword argument because its position is last
|
107
|
+
- `[{}, {}]` is empty hash type argument (first) and one empty keyword argument (second)
|
108
|
+
- `[{}, {}, {}]` is two empty hash type argument (first, second) and empty keyword argument (last)
|
109
|
+
- `{}` is keyword argument. non-keyword arguments must be in array.
|
110
|
+
- Of course, nested hash works
|
111
|
+
- Example: [Hash](#hash)
|
99
112
|
- `Proc`
|
100
113
|
- Value must return a truthy value for this proc
|
101
114
|
- `true`
|
@@ -106,15 +119,36 @@ then, Rtype use it. (Do not `require 'rtype-java'`)
|
|
106
119
|
- Only available for **return type**. void return type in other languages
|
107
120
|
- Special Behaviors
|
108
121
|
- `Rtype::and(*types)` : Ensure value is valid for all the types
|
109
|
-
-
|
122
|
+
- `Rtype::and(*types)`
|
123
|
+
- `Rtype::Behavior::And[*types]`
|
124
|
+
- `include Rtype::Behavior; And[...]`
|
125
|
+
- `obj.and(*others)` (core extension)
|
126
|
+
|
110
127
|
- `Rtype::or(*types)` : Ensure value is valid for at least one of the types
|
111
|
-
-
|
128
|
+
- `Rtype::or(*types)`
|
129
|
+
- `Rtype::Behavior::Or[*types]`
|
130
|
+
- `include Rtype::Behavior; Or[...]`
|
131
|
+
- `obj.or(*others)` (core extension)
|
132
|
+
|
112
133
|
- `Rtype::xor(*types)` : Ensure value is valid for only one of the types
|
113
|
-
-
|
134
|
+
- `Rtype::xor(*types)`
|
135
|
+
- `Rtype::Behavior::Xor[*types]`
|
136
|
+
- `include Rtype::Behavior; Xor[...]`
|
137
|
+
- `obj.xor(*others)` (core extension)
|
138
|
+
|
114
139
|
- `Rtype::not(*types)` : Ensure value is not valid for all the types
|
115
|
-
-
|
140
|
+
- `Rtype::not(*types)`
|
141
|
+
- `Rtype::Behavior::Not[*types]`
|
142
|
+
- `include Rtype::Behavior; Not[...]`
|
143
|
+
- `obj.not` (core extension)
|
144
|
+
|
116
145
|
- `Rtype::nilable(type)` : Ensure value can be nil
|
117
|
-
-
|
146
|
+
- `Rtype::nilable(type)`
|
147
|
+
- `Rtype::Behavior::Nilable[type]`
|
148
|
+
- `include Rtype::Behavior; Nilable[...]`
|
149
|
+
- `obj.nilable` (core extension)
|
150
|
+
- `obj.or_nil` (core extension)
|
151
|
+
|
118
152
|
- You can create custom behavior by extending `Rtype::Behavior::Base`
|
119
153
|
|
120
154
|
### Examples
|
@@ -219,6 +253,38 @@ func [1]
|
|
219
253
|
func [1, 2] # Your location is (1, 2). I will look for you. I will find you
|
220
254
|
```
|
221
255
|
|
256
|
+
#### Hash
|
257
|
+
```ruby
|
258
|
+
# last hash element is keyword arguments
|
259
|
+
rtype :func, [{msg: String}, {}] => Any
|
260
|
+
def func(hash)
|
261
|
+
puts hash[:msg]
|
262
|
+
end
|
263
|
+
|
264
|
+
# last hash is keyword arguments
|
265
|
+
func({}, {})
|
266
|
+
# (Rtype::ArgumentTypeError) for 1st argument:
|
267
|
+
# Expected {} to be an hash with 1 elements:
|
268
|
+
# - msg : Expected nil to be a String
|
269
|
+
|
270
|
+
func({msg: 123}, {})
|
271
|
+
# (Rtype::ArgumentTypeError) for 1st argument:
|
272
|
+
# Expected {:msg=>123} to be an hash with 1 elements:
|
273
|
+
# - msg : Expected 123 to be a String
|
274
|
+
|
275
|
+
func({msg: "hello", key: 'value'}, {})
|
276
|
+
# (Rtype::ArgumentTypeError) for 1st argument:
|
277
|
+
# Expected {:msg=>"hello", :key=>"value"} to be an hash with 1 elements:
|
278
|
+
# - msg : Expected "hello" to be a String
|
279
|
+
|
280
|
+
func({"msg" => "hello hash"}, {})
|
281
|
+
# (Rtype::ArgumentTypeError) for 1st argument:
|
282
|
+
# Expected {"msg"=>"hello hash"} to be an hash with 1 elements:
|
283
|
+
# - msg : Expected nil to be a String
|
284
|
+
|
285
|
+
func({msg: "hello hash"}, {}) # hello hash
|
286
|
+
```
|
287
|
+
|
222
288
|
#### rtype with attr_accessor
|
223
289
|
`rtype_accessor`
|
224
290
|
|
@@ -250,7 +316,9 @@ Example.new.value
|
|
250
316
|
require 'rtype'
|
251
317
|
|
252
318
|
class Example
|
253
|
-
rtype :and_test, [
|
319
|
+
rtype :and_test, [String.and(:func)] => Any
|
320
|
+
# also works:
|
321
|
+
# rtype :and_test, [Rtype::and(String, :func)] => Any
|
254
322
|
def and_test(arg)
|
255
323
|
end
|
256
324
|
end
|
@@ -344,7 +412,7 @@ end
|
|
344
412
|
say "Hello" # Hello
|
345
413
|
```
|
346
414
|
|
347
|
-
#### Static method
|
415
|
+
#### Static(singleton) method
|
348
416
|
Use `rtype_self`
|
349
417
|
|
350
418
|
```ruby
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Object
|
2
|
+
def and(*others)
|
3
|
+
::Rtype::and(self, *others)
|
4
|
+
end
|
5
|
+
|
6
|
+
def nilable
|
7
|
+
::Rtype::nilable(self)
|
8
|
+
end
|
9
|
+
alias_method :or_nil, :nilable
|
10
|
+
|
11
|
+
def not
|
12
|
+
::Rtype::not(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def or(*others)
|
16
|
+
::Rtype::or(self, *others)
|
17
|
+
end
|
18
|
+
|
19
|
+
def xor(*others)
|
20
|
+
::Rtype::xor(self, *others)
|
21
|
+
end
|
22
|
+
end
|
data/lib/rtype/behavior/not.rb
CHANGED
data/lib/rtype/behavior/or.rb
CHANGED
data/lib/rtype/behavior/xor.rb
CHANGED
data/lib/rtype/behavior.rb
CHANGED
data/lib/rtype/version.rb
CHANGED
data/lib/rtype.rb
CHANGED
@@ -40,7 +40,7 @@ module Rtype
|
|
40
40
|
return_sig = el[1]
|
41
41
|
|
42
42
|
if arg_sig.is_a?(Array)
|
43
|
-
expected_args = arg_sig
|
43
|
+
expected_args = arg_sig.dup
|
44
44
|
if expected_args.last.is_a?(Hash)
|
45
45
|
expected_kwargs = expected_args.pop
|
46
46
|
else
|
@@ -51,12 +51,12 @@ module Rtype
|
|
51
51
|
expected_kwargs = arg_sig
|
52
52
|
end
|
53
53
|
|
54
|
-
expected_args.each { |e|
|
54
|
+
expected_args.each { |e| check_valid_argument_type_sig(e) }
|
55
55
|
if expected_kwargs.keys.any? { |e| !e.is_a?(Symbol) }
|
56
56
|
raise TypeSignatureError, "Invalid type signature: keyword arguments contain non-symbol key"
|
57
57
|
end
|
58
|
-
expected_kwargs.each_value { |e|
|
59
|
-
|
58
|
+
expected_kwargs.each_value { |e| check_valid_argument_type_sig(e) }
|
59
|
+
check_valid_return_type_sig(return_sig)
|
60
60
|
|
61
61
|
sig = TypeSignature.new
|
62
62
|
sig.argument_type = arg_sig
|
@@ -123,7 +123,7 @@ module Rtype
|
|
123
123
|
when Array
|
124
124
|
if value.is_a?(Array)
|
125
125
|
arr = expected.map.with_index do |e, idx|
|
126
|
-
if e.is_a?(Array)
|
126
|
+
if e.is_a?(Array) || e.is_a?(Hash)
|
127
127
|
"- [#{idx}] index : {\n" + type_error_message(e, value[idx]) + "\n}"
|
128
128
|
else
|
129
129
|
"- [#{idx}] index : " + type_error_message(e, value[idx])
|
@@ -133,6 +133,20 @@ module Rtype
|
|
133
133
|
else
|
134
134
|
"Expected #{value.inspect} to be an array"
|
135
135
|
end
|
136
|
+
when Hash
|
137
|
+
if value.is_a?(Hash)
|
138
|
+
arr = []
|
139
|
+
expected.each do |k, v|
|
140
|
+
if v.is_a?(Array) || v.is_a?(Hash)
|
141
|
+
arr << "- #{k} : {\n" + type_error_message(v, value[k]) + "\n}"
|
142
|
+
else
|
143
|
+
arr << "- #{k} : " + type_error_message(v, value[k])
|
144
|
+
end
|
145
|
+
end
|
146
|
+
"Expected #{value.inspect} to be an hash with #{expected.length} elements:\n" + arr.join("\n")
|
147
|
+
else
|
148
|
+
"Expected #{value.inspect} to be an hash"
|
149
|
+
end
|
136
150
|
when Proc
|
137
151
|
"Expected #{value.inspect} to return a truthy value for proc #{expected}"
|
138
152
|
when true
|
@@ -166,7 +180,34 @@ private
|
|
166
180
|
end
|
167
181
|
nil
|
168
182
|
end
|
169
|
-
|
183
|
+
|
184
|
+
def check_valid_argument_type_sig(sig)
|
185
|
+
case sig
|
186
|
+
when Rtype::Behavior::Base
|
187
|
+
when Module
|
188
|
+
when Symbol
|
189
|
+
when Regexp
|
190
|
+
when Range
|
191
|
+
when Array
|
192
|
+
sig.each do |e|
|
193
|
+
check_valid_argument_type_sig(e)
|
194
|
+
end
|
195
|
+
when Hash
|
196
|
+
sig.each_value do |e|
|
197
|
+
check_valid_argument_type_sig(e)
|
198
|
+
end
|
199
|
+
when Proc
|
200
|
+
when true
|
201
|
+
when false
|
202
|
+
else
|
203
|
+
raise TypeSignatureError, "Invalid type signature: Unknown type behavior #{sig}"
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def check_valid_return_type_sig(sig)
|
208
|
+
check_valid_argument_type_sig(sig) unless sig.nil?
|
209
|
+
end
|
210
|
+
|
170
211
|
public
|
171
212
|
unless respond_to?(:valid?)
|
172
213
|
# validate argument type
|
@@ -180,6 +221,10 @@ public
|
|
180
221
|
!!(expected =~ value.to_s)
|
181
222
|
when Range
|
182
223
|
expected.include?(value)
|
224
|
+
when Hash
|
225
|
+
return false unless value.is_a?(Hash)
|
226
|
+
return false unless expected.keys == value.keys
|
227
|
+
expected.all? { |k, v| valid?(v, value[k]) }
|
183
228
|
when Array
|
184
229
|
return false unless value.is_a?(Array)
|
185
230
|
return false unless expected.length == value.length
|
@@ -207,7 +252,7 @@ public
|
|
207
252
|
value = args[i]
|
208
253
|
unless expected.nil?
|
209
254
|
unless valid?(expected, value)
|
210
|
-
raise ArgumentTypeError, "
|
255
|
+
raise ArgumentTypeError, "#{arg_message(i)}\n" + type_error_message(expected, value)
|
211
256
|
end
|
212
257
|
end
|
213
258
|
end
|
@@ -222,7 +267,7 @@ public
|
|
222
267
|
value = args[i]
|
223
268
|
unless expected.nil?
|
224
269
|
unless valid?(expected, value)
|
225
|
-
raise ArgumentTypeError, "#{arg_message(
|
270
|
+
raise ArgumentTypeError, "#{arg_message(i)}\n" + type_error_message(expected, value)
|
226
271
|
end
|
227
272
|
end
|
228
273
|
end
|
data/spec/rtype_spec.rb
CHANGED
@@ -13,6 +13,9 @@ describe Rtype do
|
|
13
13
|
obj
|
14
14
|
end
|
15
15
|
|
16
|
+
def two_args(a, b)
|
17
|
+
end
|
18
|
+
|
16
19
|
def three_args(a, b, c)
|
17
20
|
end
|
18
21
|
|
@@ -207,10 +210,26 @@ describe Rtype do
|
|
207
210
|
it "is right" do
|
208
211
|
klass.send :rtype, :return_arg, [[:to_i, :to_i]] => Any
|
209
212
|
instance.return_arg([123, 456])
|
213
|
+
|
214
|
+
klass.send :rtype, :two_args, [[:to_i], [:to_i]] => Any
|
215
|
+
instance.two_args([123], [456])
|
210
216
|
end
|
211
217
|
it "is wrong args" do
|
212
218
|
klass.send :rtype, :return_arg, [[:to_i, :to_i]] => Any
|
213
|
-
expect {
|
219
|
+
expect {
|
220
|
+
instance.return_arg([123, [true]])
|
221
|
+
}.to raise_error Rtype::ArgumentTypeError
|
222
|
+
expect {
|
223
|
+
instance.return_arg([123, true])
|
224
|
+
}.to raise_error Rtype::ArgumentTypeError
|
225
|
+
|
226
|
+
klass.send :rtype, :two_args, [[:to_i], [:to_i]] => Any
|
227
|
+
expect {
|
228
|
+
instance.two_args([123, 123], [123])
|
229
|
+
}.to raise_error Rtype::ArgumentTypeError
|
230
|
+
expect {
|
231
|
+
instance.two_args([123], 123)
|
232
|
+
}.to raise_error Rtype::ArgumentTypeError
|
214
233
|
end
|
215
234
|
it "is wrong result" do
|
216
235
|
klass.send :rtype, :return_arg, [Any] => [:to_i, :to_i]
|
@@ -218,6 +237,23 @@ describe Rtype do
|
|
218
237
|
end
|
219
238
|
end
|
220
239
|
|
240
|
+
describe 'Hash' do
|
241
|
+
it "is right" do
|
242
|
+
klass.send :rtype, :return_arg, [{k: Integer}, {}] => Any
|
243
|
+
instance.return_arg({k: 123}, {})
|
244
|
+
end
|
245
|
+
it "is wrong args" do
|
246
|
+
klass.send :rtype, :return_arg, [{k: Integer}, {}] => Any
|
247
|
+
expect {
|
248
|
+
instance.return_arg({k: "str"}, {})
|
249
|
+
}.to raise_error Rtype::ArgumentTypeError
|
250
|
+
end
|
251
|
+
it "is wrong result" do
|
252
|
+
klass.send :rtype, :return_arg, [Any] => {k: Integer}
|
253
|
+
expect { instance.return_arg({k: "str"}) }.to raise_error Rtype::ReturnTypeError
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
221
257
|
describe 'Proc' do
|
222
258
|
it "is right" do
|
223
259
|
klass.send :rtype, :return_arg, [->(arg){!arg.nil?}] => Any
|
@@ -285,36 +321,117 @@ describe Rtype do
|
|
285
321
|
end
|
286
322
|
|
287
323
|
describe 'Special type behaviors' do
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
324
|
+
describe 'Rtype::Behavior::And' do
|
325
|
+
it 'module singleton method' do
|
326
|
+
klass.send :rtype, :return_nil, [Rtype::and(:to_i, :chars)] => nil
|
327
|
+
instance.return_nil("Hello")
|
328
|
+
expect {instance.return_nil(123)}.to raise_error Rtype::ArgumentTypeError
|
329
|
+
end
|
330
|
+
|
331
|
+
it 'class singleton [] method' do
|
332
|
+
klass.send :rtype, :return_nil, [ Rtype::Behavior::And[:to_i, :chars] ] => nil
|
333
|
+
instance.return_nil("Hello")
|
334
|
+
expect {instance.return_nil(123)}.to raise_error Rtype::ArgumentTypeError
|
335
|
+
end
|
336
|
+
|
337
|
+
it 'core extension method' do
|
338
|
+
klass.send :rtype, :return_nil, [ :to_i.and(:chars) ] => nil
|
339
|
+
instance.return_nil("Hello")
|
340
|
+
expect {instance.return_nil(123)}.to raise_error Rtype::ArgumentTypeError
|
341
|
+
end
|
292
342
|
end
|
293
343
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
344
|
+
describe 'Rtype::Behavior::Or' do
|
345
|
+
it 'module singleton method' do
|
346
|
+
klass.send :rtype, :return_nil, [Rtype::or(Integer, String)] => nil
|
347
|
+
instance.return_nil(123)
|
348
|
+
instance.return_nil("abc")
|
349
|
+
expect {instance.return_nil(nil)}.to raise_error Rtype::ArgumentTypeError
|
350
|
+
end
|
351
|
+
|
352
|
+
it 'class singleton [] method' do
|
353
|
+
klass.send :rtype, :return_nil, [ Rtype::Behavior::Or[Integer, String] ] => nil
|
354
|
+
instance.return_nil(123)
|
355
|
+
instance.return_nil("abc")
|
356
|
+
expect {instance.return_nil(nil)}.to raise_error Rtype::ArgumentTypeError
|
357
|
+
end
|
358
|
+
|
359
|
+
it 'core extension method' do
|
360
|
+
klass.send :rtype, :return_nil, [ Integer.or(String) ] => nil
|
361
|
+
instance.return_nil(123)
|
362
|
+
instance.return_nil("abc")
|
363
|
+
expect {instance.return_nil(nil)}.to raise_error Rtype::ArgumentTypeError
|
364
|
+
end
|
299
365
|
end
|
300
366
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
367
|
+
describe 'Rtype::Behavior::Nilable' do
|
368
|
+
it 'module singleton method' do
|
369
|
+
klass.send :rtype, :return_nil, [Rtype::nilable(Integer)] => nil
|
370
|
+
instance.return_nil(nil)
|
371
|
+
instance.return_nil(123)
|
372
|
+
expect {instance.return_nil("abc")}.to raise_error Rtype::ArgumentTypeError
|
373
|
+
end
|
374
|
+
|
375
|
+
it 'class singleton [] method' do
|
376
|
+
klass.send :rtype, :return_nil, [ Rtype::Behavior::Nilable[Integer] ] => nil
|
377
|
+
instance.return_nil(nil)
|
378
|
+
instance.return_nil(123)
|
379
|
+
expect {instance.return_nil("abc")}.to raise_error Rtype::ArgumentTypeError
|
380
|
+
end
|
381
|
+
|
382
|
+
it 'core extension method :nilable' do
|
383
|
+
klass.send :rtype, :return_nil, [Integer.nilable] => nil
|
384
|
+
instance.return_nil(nil)
|
385
|
+
instance.return_nil(123)
|
386
|
+
expect {instance.return_nil("abc")}.to raise_error Rtype::ArgumentTypeError
|
387
|
+
end
|
388
|
+
|
389
|
+
it 'core extension method :or_nil' do
|
390
|
+
klass.send :rtype, :return_nil, [Integer.or_nil] => nil
|
391
|
+
instance.return_nil(nil)
|
392
|
+
instance.return_nil(123)
|
393
|
+
expect {instance.return_nil("abc")}.to raise_error Rtype::ArgumentTypeError
|
394
|
+
end
|
306
395
|
end
|
307
396
|
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
397
|
+
describe 'Rtype::Behavior::Not' do
|
398
|
+
it 'module singleton method' do
|
399
|
+
klass.send :rtype, :return_nil, [Rtype::not(String)] => nil
|
400
|
+
instance.return_nil(123)
|
401
|
+
expect {instance.return_nil("abc")}.to raise_error Rtype::ArgumentTypeError
|
402
|
+
end
|
403
|
+
|
404
|
+
it 'class singleton [] method' do
|
405
|
+
klass.send :rtype, :return_nil, [ Rtype::Behavior::Not[String] ] => nil
|
406
|
+
instance.return_nil(123)
|
407
|
+
expect {instance.return_nil("abc")}.to raise_error Rtype::ArgumentTypeError
|
408
|
+
end
|
409
|
+
|
410
|
+
it 'core extension method' do
|
411
|
+
klass.send :rtype, :return_nil, [ String.not ] => nil
|
412
|
+
instance.return_nil(123)
|
413
|
+
expect {instance.return_nil("abc")}.to raise_error Rtype::ArgumentTypeError
|
414
|
+
end
|
312
415
|
end
|
313
416
|
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
417
|
+
describe 'Rtype::Behavior::Xor' do
|
418
|
+
it 'module singleton method' do
|
419
|
+
klass.send :rtype, :return_nil, [Rtype::xor(:to_i, String)] => nil
|
420
|
+
instance.return_nil(123)
|
421
|
+
expect {instance.return_nil("abc")}.to raise_error Rtype::ArgumentTypeError
|
422
|
+
end
|
423
|
+
|
424
|
+
it 'class singleton [] method' do
|
425
|
+
klass.send :rtype, :return_nil, [ Rtype::Behavior::Xor[:to_i, String] ] => nil
|
426
|
+
instance.return_nil(123)
|
427
|
+
expect {instance.return_nil("abc")}.to raise_error Rtype::ArgumentTypeError
|
428
|
+
end
|
429
|
+
|
430
|
+
it 'core extension method' do
|
431
|
+
klass.send :rtype, :return_nil, [ :to_i.xor(String) ] => nil
|
432
|
+
instance.return_nil(123)
|
433
|
+
expect {instance.return_nil("abc")}.to raise_error Rtype::ArgumentTypeError
|
434
|
+
end
|
318
435
|
end
|
319
436
|
end
|
320
437
|
end
|
@@ -334,6 +451,27 @@ describe Rtype do
|
|
334
451
|
expect {instance.sum(1, 2.0)}.to raise_error Rtype::ArgumentTypeError
|
335
452
|
end
|
336
453
|
|
454
|
+
it 'two array' do
|
455
|
+
klass.send :rtype, :sum, [[Integer], [Integer]] => Any
|
456
|
+
instance.sum([1], [2])
|
457
|
+
expect {instance.sum([1], 2)}.to raise_error Rtype::ArgumentTypeError
|
458
|
+
expect {instance.sum([1], ["str"])}.to raise_error Rtype::ArgumentTypeError
|
459
|
+
end
|
460
|
+
|
461
|
+
it 'two hash' do
|
462
|
+
klass.send :rtype, :two_args, [{k: Integer}, {k: Integer}, {}] => Any
|
463
|
+
instance.two_args({k: 123}, {k: 456}, {})
|
464
|
+
expect {
|
465
|
+
instance.two_args({k: 123}, {}, {})
|
466
|
+
}.to raise_error Rtype::ArgumentTypeError
|
467
|
+
expect {
|
468
|
+
instance.two_args({k: 123}, 456, {})
|
469
|
+
}.to raise_error Rtype::ArgumentTypeError
|
470
|
+
expect {
|
471
|
+
instance.two_args({k: 123}, {k: "str"}, {})
|
472
|
+
}.to raise_error Rtype::ArgumentTypeError
|
473
|
+
end
|
474
|
+
|
337
475
|
it 'one keyword argument' do
|
338
476
|
klass.send :rtype, :kwarg, {a: Float} => Any
|
339
477
|
expect {instance.kwarg(a: 1)}.to raise_error Rtype::ArgumentTypeError
|
@@ -370,6 +508,25 @@ describe Rtype do
|
|
370
508
|
expect {instance.kwarg(a: 1)}.to raise_error Rtype::ArgumentTypeError
|
371
509
|
expect {instance.kwarg(:a => 1)}.to raise_error Rtype::ArgumentTypeError
|
372
510
|
end
|
511
|
+
|
512
|
+
context 'when hash is not last element' do
|
513
|
+
it 'is hash-type argument, not keyword argument' do
|
514
|
+
klass.send :rtype, :return_arg, [{a: String}, {}] => Any
|
515
|
+
expect {
|
516
|
+
instance.return_arg({a: 123}, {})
|
517
|
+
}.to raise_error Rtype::ArgumentTypeError
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
it 'hash-type argument and keyword argument' do
|
522
|
+
klass.send :rtype, :arg_and_kwarg, [{a: String}, {b: String}] => Any
|
523
|
+
expect {
|
524
|
+
instance.arg_and_kwarg({a: 123}, b: "str")
|
525
|
+
}.to raise_error Rtype::ArgumentTypeError
|
526
|
+
expect {
|
527
|
+
instance.arg_and_kwarg({a: "str"}, b: 123)
|
528
|
+
}.to raise_error Rtype::ArgumentTypeError
|
529
|
+
end
|
373
530
|
end
|
374
531
|
|
375
532
|
describe 'check return' do
|
@@ -400,13 +557,13 @@ describe Rtype do
|
|
400
557
|
end
|
401
558
|
it 'invalid return signature' do
|
402
559
|
expect {
|
403
|
-
klass.send :rtype, :return_arg, [] =>
|
560
|
+
klass.send :rtype, :return_arg, [] => 123
|
404
561
|
}.to raise_error Rtype::TypeSignatureError
|
405
562
|
end
|
406
563
|
|
407
564
|
it 'invalid type behavior in arguments' do
|
408
565
|
expect {
|
409
|
-
klass.send :rtype, :sum_kwargs, [{a:
|
566
|
+
klass.send :rtype, :sum_kwargs, [{a: 123}, {b: Integer}] => Any
|
410
567
|
}.to raise_error Rtype::TypeSignatureError
|
411
568
|
expect {
|
412
569
|
klass.send :rtype, :return_arg, [123] => Any
|
@@ -418,7 +575,7 @@ describe Rtype do
|
|
418
575
|
klass.send :rtype, :kwarg, {a: 123} => Any
|
419
576
|
}.to raise_error Rtype::TypeSignatureError
|
420
577
|
expect {
|
421
|
-
klass.send :rtype, :kwarg, {a: {b:
|
578
|
+
klass.send :rtype, :kwarg, {a: {b: 123}} => Any
|
422
579
|
}.to raise_error Rtype::TypeSignatureError
|
423
580
|
expect {
|
424
581
|
klass.send :rtype, :kwarg, {Object.new => Integer} => Any
|
@@ -506,6 +663,15 @@ describe Rtype do
|
|
506
663
|
instance.three_kwargs(a: "abc", b: 123, c: 456)
|
507
664
|
end
|
508
665
|
end
|
666
|
+
|
667
|
+
context 'when hash type argument contain a key not configured to rtype' do
|
668
|
+
it 'raises error' do
|
669
|
+
klass.send :rtype, :return_arg, [{a: String}, {}] => Any
|
670
|
+
expect {
|
671
|
+
instance.return_arg({a: "str", b: "str"}, {})
|
672
|
+
}.to raise_error Rtype::ArgumentTypeError
|
673
|
+
end
|
674
|
+
end
|
509
675
|
end
|
510
676
|
|
511
677
|
describe "Call Rtype`s static method directly" do
|
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.4.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-
|
11
|
+
date: 2016-04-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -52,7 +52,7 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
-
description:
|
55
|
+
description: The fastest type checking gem
|
56
56
|
email:
|
57
57
|
- sputnikgugja@gmail.com
|
58
58
|
executables: []
|
@@ -69,6 +69,7 @@ files:
|
|
69
69
|
- lib/rtype/behavior.rb
|
70
70
|
- lib/rtype/behavior/and.rb
|
71
71
|
- lib/rtype/behavior/base.rb
|
72
|
+
- lib/rtype/behavior/core_ext.rb
|
72
73
|
- lib/rtype/behavior/nilable.rb
|
73
74
|
- lib/rtype/behavior/not.rb
|
74
75
|
- lib/rtype/behavior/or.rb
|