rtype-native 0.6.6 → 0.6.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c9296a99a60b8f7ea3ec34c5464aad09d27c6ccd
4
- data.tar.gz: ec627f0a0fc11a3fbf9182d194954bb6d98a3dde
3
+ metadata.gz: 1532be5637819ff82d30dbd34a3ce0314af8cb04
4
+ data.tar.gz: b2ed2031f2ba992c59005fbd9008ac3de99ea89e
5
5
  SHA512:
6
- metadata.gz: 111203e0c9cc7ce0b0ee3c25eea6ee7e74d4c7bb604af1de6466788aaa5ec72668e2f3691232bcd1769dd1376bd0a7218923a45dcdf5bdda99f6679a7f64bfb0
7
- data.tar.gz: d4b8c28841bd430666a1fe08114fdc3c505bdb7ebfa03b50db7ac20048462a03085bebe99443c7e9f9662b7155ef11890d54581a605ffea5841883dbea43f674
6
+ metadata.gz: 007445e116ded093152f2bba33fc8d56259a16fbaa9e7cbe0848110053152b2040d8ff682f532aa81e0945a41d64e2692924fdaff40f0ee86581c0022bef9efb
7
+ data.tar.gz: fe39ccf6a59187b32c869a4fd09dc05d2fc0ba68a6a452e008297d0f3cb3c8eddd777fea51b0f81cb9e1910f0ff341155e3f43a89fcb0dc270f05914d12b0461
data/README.md CHANGED
@@ -12,17 +12,27 @@ class Test
12
12
  a.to_i + b
13
13
  end
14
14
 
15
- rtype {state: Boolean} => Boolean
15
+ rtype [{state: Boolean}] => Boolean
16
16
  def self.invert(state:)
17
17
  !state
18
18
  end
19
+
20
+ # Hashes of hashes params require () to prevent invalid syntax
21
+ rtype({state: Boolean} => Boolean)
22
+ def self.invert2(state:)
23
+ !state
24
+ end
19
25
  end
20
26
 
21
27
  Test.new.sum(123, "asd")
22
28
  # (Rtype::ArgumentTypeError) for 2nd argument:
23
29
  # Expected "asd" to be a Numeric
24
30
 
25
- Test::invert(state: 0)
31
+ Test.invert(state: 0)
32
+ # (Rtype::ArgumentTypeError) for 'state' argument:
33
+ # Expected 0 to be a Boolean
34
+
35
+ Test.invert2(state: 0)
26
36
  # (Rtype::ArgumentTypeError) for 'state' argument:
27
37
  # Expected 0 to be a Boolean
28
38
  ```
@@ -40,8 +50,10 @@ Test::invert(state: 0)
40
50
  - Provides type checking for [Keyword Argument](#keyword-argument)
41
51
  - [Type checking for hash elements](#hash)
42
52
  - [Duck Typing](#duck-typing)
43
- - [Typed Array](#typed-array)
53
+ - [Typed Array](#typed-array), Typed Set, Typed Hash
44
54
  - [Numeric check](#special-behaviors). e.g. `Int >= 0`
55
+ - [Type checking for getter and setter](#attr_accessor-with-rtype)
56
+ - [float_accessor](#float_accessor), [bool_accessor](#bool_accessor)
45
57
  - Custom type behavior
46
58
  - ...
47
59
 
@@ -67,16 +79,8 @@ gem 'rtype-native'
67
79
  ```
68
80
  then, Rtype uses it. (**Do not** `require 'rtype-native'`)
69
81
 
70
- #### Java extension for JRuby
71
- Run
72
- ```ruby
73
- gem install rtype-java
74
- ```
75
- or add to your `Gemfile`:
76
- ```ruby
77
- gem 'rtype-java'
78
- ```
79
- then, Rtype uses it. (**Do not** `require 'rtype-java'`)
82
+ #### Java extension for JRuby is automatic
83
+ **Do not** `require 'rtype-java'`
80
84
 
81
85
  ## Usage
82
86
 
@@ -106,7 +110,7 @@ then, Rtype uses it. (**Do not** `require 'rtype-java'`)
106
110
  - Example: [Hash](#hash)
107
111
 
108
112
  - [Special Behaviors](#special-behaviors)
109
- - `TypedArray`, `Num, Int, Flo`, `And`, `Xor`, `Not`, `Nilable`
113
+ - `TypedArray, TypedSet, TypedHash`, `Num, Int, Flo`, `And`, `Xor`, `Not`, `Nilable`
110
114
 
111
115
  ### Examples
112
116
 
@@ -204,34 +208,35 @@ def func(hash)
204
208
  puts hash[:msg]
205
209
  end
206
210
 
207
- # last hash is not hash argument but keyword arguments
208
- func({}, {})
211
+ func({})
209
212
  # (Rtype::ArgumentTypeError) for 1st argument:
210
213
  # Expected {} to be a hash with 1 elements:
211
214
  # - msg : Expected nil to be a String
212
215
 
213
- func({msg: 123}, {})
216
+ func({msg: 123})
214
217
  # (Rtype::ArgumentTypeError) for 1st argument:
215
218
  # Expected {:msg=>123} to be a hash with 1 elements:
216
219
  # - msg : Expected 123 to be a String
217
220
 
218
- func({msg: "hello", key: 'value'}, {})
221
+ func({msg: "hello", key: 'value'})
219
222
  # (Rtype::ArgumentTypeError) for 1st argument:
220
223
  # Expected {:msg=>"hello", :key=>"value"} to be a hash with 1 elements:
221
224
  # - msg : Expected "hello" to be a String
222
225
 
223
- func({"msg" => "hello hash"}, {})
226
+ func({"msg" => "hello hash"})
224
227
  # (Rtype::ArgumentTypeError) for 1st argument:
225
228
  # Expected {"msg"=>"hello hash"} to be a hash with 1 elements:
226
229
  # - msg : Expected nil to be a String
227
230
 
228
- func({msg: "hello hash"}, {}) # hello hash
231
+ func({msg: "hello hash"}) # hello hash
229
232
  ```
230
233
 
231
- #### rtype with attr_accessor
232
- `rtype_accessor` : calls `attr_accessor` if the accessor method(getter/setter) is not defined. and makes it typed
234
+ #### attr_accessor with rtype
235
+ - `rtype_accessor(*names, type)` : calls `attr_accessor` if the accessor methods(getter/setter) are not defined. and makes it typed
236
+ - `rtype_reader(*names, type)` : calls `attr_reader` if the getters are not defined. and makes it typed
237
+ - `rtype_writer(*names, type)` : calls `attr_writer` if the setters are not defined. and makes it typed
233
238
 
234
- You can use `rtype_accessor_self` for static accessor.
239
+ You can use `rtype_accessor_self` for static accessor. (`rtype_reader_self`, `rtype_writer_self` also exist)
235
240
 
236
241
  ```ruby
237
242
  require 'rtype'
@@ -285,6 +290,29 @@ sum([1, 2, 3]) # => 6
285
290
  sum([1.0, 2, 3]) # => 6.0
286
291
  ```
287
292
 
293
+ #### float_accessor
294
+ ```ruby
295
+ class Point
296
+ float_accessor :x, :y
297
+ end
298
+
299
+ v = Point.new
300
+ v.x = 1
301
+ v.x # => 1.0 (always Float)
302
+ ```
303
+
304
+ #### bool_accessor
305
+ ```ruby
306
+ class Human
307
+ bool_accessor :hungry
308
+ end
309
+
310
+ a = Human.new
311
+ a.hungry = true
312
+ a.hungry? # => true
313
+ a.hungry # NoMethodError
314
+ ```
315
+
288
316
  #### `rtype`
289
317
  ```ruby
290
318
  require 'rtype'
@@ -392,9 +420,14 @@ Example.new.method(:test).return_type
392
420
 
393
421
  #### Special Behaviors
394
422
  - `TypedArray` : Ensures value is an array with the type (type signature)
395
- - `Array::of(type)` (recommended)
396
- - or `Rtype::Behavior::TypedArray[type]`
423
+ - `Array.of(type)` (recommended)
397
424
  - Example: [TypedArray](#typed-array)
425
+
426
+ - `TypedSet` : Ensures value is a set with the type (type signature)
427
+ - `Set.of(type)` (recommended)
428
+
429
+ - `TypedHash` : Ensures value is a hash with the type (type signature)
430
+ - `Hash.of(key_type, value_type)` (recommended)
398
431
 
399
432
  - `Num, Int, Flo` : Numeric check
400
433
  - `Num/Int/Flo >/>=/</<=/== x`
@@ -403,19 +436,19 @@ Example.new.method(:test).return_type
403
436
  - e.g. `Flo >= 2` means value must be a `Float` and >= 2
404
437
 
405
438
  - `And` : Ensures value is valid for all given types
406
- - `Rtype::and(*types)`, `Rtype::Behavior::And[*types]`
439
+ - `Rtype.and(*types)`, `Rtype::Behavior::And[*types]`
407
440
  - or `Array#comb`, `Object#and(*others)`
408
441
 
409
442
  - `Xor` : Ensures value is valid for only one of given types
410
- - `Rtype::xor(*types)`, `Rtype::Behavior::Xor[*types]`
443
+ - `Rtype.xor(*types)`, `Rtype::Behavior::Xor[*types]`
411
444
  - or `Object#xor(*others)`
412
445
 
413
446
  - `Not` : Ensures value is not valid for all given types
414
- - `Rtype::not(*types)`, `Rtype::Behavior::Not[*types]`
447
+ - `Rtype.not(*types)`, `Rtype::Behavior::Not[*types]`
415
448
  - or `Object#not`
416
449
 
417
450
  - `Nilable` : Value can be nil
418
- - `Rtype::nilable(type)`, `Rtype::Behavior::Nilable[type]`
451
+ - `Rtype.nilable(type)`, `Rtype::Behavior::Nilable[type]`
419
452
  - or `Object#nilable`, `Object#or_nil`
420
453
 
421
454
  - You can create custom behaviors by extending `Rtype::Behavior::Base`
data/Rakefile CHANGED
@@ -8,5 +8,5 @@ task :default => [:spec]
8
8
  # Benchmark
9
9
  desc "Compare with pure ruby and other gems"
10
10
  task :benchmark do
11
- ruby "benchmark/benchmark.rb"
11
+ ruby "benchmark/benchmark.rb"
12
12
  end
@@ -2,5 +2,5 @@
2
2
  #define RTYPE_H
3
3
  #include "ruby.h"
4
4
  #include <string.h>
5
- #define RTYPE_NATIVE_EXT_VERSION "0.6.6"
5
+ #define RTYPE_NATIVE_EXT_VERSION "0.6.8"
6
6
  #endif
@@ -46,6 +46,10 @@ describe Rtype do
46
46
 
47
47
  def args_and_kwargs(a, b, c:, d:)
48
48
  end
49
+
50
+ public
51
+ def public_func
52
+ end
49
53
 
50
54
  protected
51
55
  def protected_func
@@ -149,7 +153,7 @@ describe Rtype do
149
153
  end
150
154
 
151
155
  it 'Kernel#rtype_accessor' do
152
- class TestClass
156
+ class AccessorTestClass
153
157
  rtype_accessor :value, :value2, String
154
158
 
155
159
  def initialize
@@ -157,23 +161,109 @@ describe Rtype do
157
161
  @value2 = 123
158
162
  end
159
163
  end
160
- expect {TestClass.new.value = 123}.to raise_error Rtype::ArgumentTypeError
161
- expect {TestClass.new.value}.to raise_error Rtype::ReturnTypeError
162
- expect {TestClass.new.value2 = 123}.to raise_error Rtype::ArgumentTypeError
163
- expect {TestClass.new.value2}.to raise_error Rtype::ReturnTypeError
164
+ expect {AccessorTestClass.new.value = 123}.to raise_error Rtype::ArgumentTypeError
165
+ expect {AccessorTestClass.new.value}.to raise_error Rtype::ReturnTypeError
166
+ expect {AccessorTestClass.new.value2 = 123}.to raise_error Rtype::ArgumentTypeError
167
+ expect {AccessorTestClass.new.value2}.to raise_error Rtype::ReturnTypeError
164
168
  end
165
169
 
166
170
  it 'Kernel#rtype_accessor_self' do
167
- class TestClass
171
+ class AccessorTestClass
168
172
  @@value = 123
169
173
  @@value2 = 123
170
-
171
174
  rtype_accessor_self :value, :value2, String
172
175
  end
173
- expect {TestClass::value = 123}.to raise_error Rtype::ArgumentTypeError
174
- expect {TestClass::value}.to raise_error Rtype::ReturnTypeError
175
- expect {TestClass::value2 = 123}.to raise_error Rtype::ArgumentTypeError
176
- expect {TestClass::value2}.to raise_error Rtype::ReturnTypeError
176
+ expect {AccessorTestClass::value = 123}.to raise_error Rtype::ArgumentTypeError
177
+ expect {AccessorTestClass::value}.to raise_error Rtype::ReturnTypeError
178
+ expect {AccessorTestClass::value2 = 123}.to raise_error Rtype::ArgumentTypeError
179
+ expect {AccessorTestClass::value2}.to raise_error Rtype::ReturnTypeError
180
+ end
181
+
182
+ it 'Kernel#rtype_reader' do
183
+ class ReaderTestClass
184
+ rtype_reader :value, :value2, String
185
+
186
+ def initialize
187
+ @value = 123
188
+ @value2 = 123
189
+ end
190
+ end
191
+ expect {ReaderTestClass.new.value}.to raise_error Rtype::ReturnTypeError
192
+ expect {ReaderTestClass.new.value2}.to raise_error Rtype::ReturnTypeError
193
+ end
194
+
195
+ it 'Kernel#rtype_reader_self' do
196
+ class ReaderTestClass
197
+ @@value = 123
198
+ @@value2 = 123
199
+ rtype_reader_self :value, :value2, String
200
+ end
201
+ expect {ReaderTestClass::value}.to raise_error Rtype::ReturnTypeError
202
+ expect {ReaderTestClass::value2}.to raise_error Rtype::ReturnTypeError
203
+ end
204
+
205
+ it 'Kernel#rtype_writer' do
206
+ class WriterTestClass
207
+ rtype_writer :value, :value2, String
208
+
209
+ def initialize
210
+ @value = 123
211
+ @value2 = 123
212
+ end
213
+ end
214
+ expect {WriterTestClass.new.value = 123}.to raise_error Rtype::ArgumentTypeError
215
+ expect {WriterTestClass.new.value2 = 123}.to raise_error Rtype::ArgumentTypeError
216
+ end
217
+
218
+ it 'Kernel#rtype_writer_self' do
219
+ class WriterTestClass
220
+ @@value = 123
221
+ @@value2 = 123
222
+ rtype_writer_self :value, :value2, String
223
+ end
224
+ expect {WriterTestClass::value = 123}.to raise_error Rtype::ArgumentTypeError
225
+ expect {WriterTestClass::value2 = 123}.to raise_error Rtype::ArgumentTypeError
226
+ end
227
+
228
+ it 'Kernel#float_accessor' do
229
+ class FloatAccessorTestClass
230
+ float_accessor :float, :int
231
+
232
+ def initialize
233
+ @float = 10.0
234
+ @int = 10
235
+ end
236
+ end
237
+
238
+ float_accessor_test = FloatAccessorTestClass.new
239
+
240
+ float_accessor_test.float
241
+ expect {float_accessor_test.int}.to raise_error Rtype::ReturnTypeError
242
+ float_accessor_test.float = 5.0
243
+ float_accessor_test.float = 5
244
+ expect(float_accessor_test.float).to eql(5.0) # be(expected) => passes if actual.eql?(expected)
245
+ expect(float_accessor_test.float).not_to eql(5)
246
+ end
247
+
248
+ it 'Kernel#bool_accessor' do
249
+ class BoolAccessorTestClass
250
+ bool_accessor :state, :invalid_var
251
+
252
+ def initialize
253
+ @state = false
254
+ @invalid_var = 123
255
+ end
256
+ end
257
+
258
+ bool_accessor_test = BoolAccessorTestClass.new
259
+
260
+ bool_accessor_test.state?
261
+ expect {bool_accessor_test.state}.to raise_error NoMethodError
262
+ expect(bool_accessor_test.state?).to eql(false)
263
+ bool_accessor_test.state = true
264
+ expect(bool_accessor_test.state?).to eql(true)
265
+ expect {bool_accessor_test.state = 123}.to raise_error Rtype::ArgumentTypeError
266
+ expect {bool_accessor_test.invalid_var?}.to raise_error Rtype::ReturnTypeError
177
267
  end
178
268
 
179
269
  describe 'Test type behaviors' do
@@ -475,6 +565,65 @@ describe Rtype do
475
565
  end
476
566
  end
477
567
 
568
+ describe 'Rtype::Behavior::TypedSet' do
569
+ it 'class singleton [] method' do
570
+ klass.send :rtype, :return_nil, [ Rtype::Behavior::TypedSet[Integer] ] => nil
571
+ instance.return_nil( Set.new([123]) )
572
+ expect {instance.return_nil(123)}.to raise_error Rtype::ArgumentTypeError
573
+ expect { instance.return_nil(Set.new([1.0])) }.to raise_error Rtype::ArgumentTypeError
574
+ end
575
+
576
+ it 'core extension method (Set::of)' do
577
+ klass.send :rtype, :return_nil, [ Set.of(Integer) ] => nil
578
+ instance.return_nil( Set.new([123]) )
579
+ expect {instance.return_nil(123)}.to raise_error Rtype::ArgumentTypeError
580
+ expect { instance.return_nil(Set.new([1.0])) }.to raise_error Rtype::ArgumentTypeError
581
+ end
582
+
583
+ it 'complicated type sig' do
584
+ klass.send :rtype, :return_nil, [ Set.of(:to_i.and(:chars)) ] => nil
585
+ instance.return_nil( Set.new(["hello"]) )
586
+ expect {instance.return_nil("hello")}.to raise_error Rtype::ArgumentTypeError
587
+ expect { instance.return_nil(Set.new([123])) }.to raise_error Rtype::ArgumentTypeError
588
+ end
589
+
590
+ it 'allows empty set' do
591
+ klass.send :rtype, :return_nil, [ Set.of(Integer) ] => nil
592
+ instance.return_nil(Set.new)
593
+ end
594
+ end
595
+
596
+ describe 'Rtype::Behavior::TypedHash' do
597
+ it 'class singleton [] method' do
598
+ klass.send :rtype, :return_nil, [ Rtype::Behavior::TypedHash[Symbol, Integer] ] => nil
599
+ instance.return_nil( {key: 123} )
600
+ expect {instance.return_nil(:key)}.to raise_error Rtype::ArgumentTypeError
601
+ expect {instance.return_nil(123)}.to raise_error Rtype::ArgumentTypeError
602
+ expect {instance.return_nil( {"key" => 123} )}.to raise_error Rtype::ArgumentTypeError
603
+ end
604
+
605
+ it 'core extension method (Hash::of)' do
606
+ klass.send :rtype, :return_nil, [ Hash.of(Symbol, Integer) ] => nil
607
+ instance.return_nil( {key: 123} )
608
+ expect {instance.return_nil(:key)}.to raise_error Rtype::ArgumentTypeError
609
+ expect {instance.return_nil(123)}.to raise_error Rtype::ArgumentTypeError
610
+ expect {instance.return_nil( {"key" => 123} )}.to raise_error Rtype::ArgumentTypeError
611
+ end
612
+
613
+ it 'complicated type sig' do
614
+ klass.send :rtype, :return_nil, [ Hash.of(:to_i.and(:chars), :to_i.and(:chars)) ] => nil
615
+ instance.return_nil( {"key" => "val"} )
616
+ expect {instance.return_nil("hello")}.to raise_error Rtype::ArgumentTypeError
617
+ expect {instance.return_nil( {key: "val"} )}.to raise_error Rtype::ArgumentTypeError
618
+ expect {instance.return_nil( {"key" => :val} )}.to raise_error Rtype::ArgumentTypeError
619
+ end
620
+
621
+ it 'allows empty hash' do
622
+ klass.send :rtype, :return_nil, [ Hash.of(Symbol, Integer) ] => nil
623
+ instance.return_nil({})
624
+ end
625
+ end
626
+
478
627
  describe 'Numeric check' do
479
628
  it 'Num (Numeric)' do
480
629
  klass.send :rtype, :return_nil, [Num >= 0] => Any
@@ -751,6 +900,10 @@ describe Rtype do
751
900
  klass.send :rtype, :private_func, [] => Any
752
901
  expect {instance.private_func}.to raise_error NoMethodError
753
902
  end
903
+ it 'public' do
904
+ klass.send :rtype, :public_func, [] => Any
905
+ instance.public_func
906
+ end
754
907
  end
755
908
 
756
909
  context 'with empty argument signature' do
@@ -816,6 +969,32 @@ describe Rtype do
816
969
  AnnotationTest2.new.inst_one(123)
817
970
  AnnotationTest2::static_two(123)
818
971
  end
972
+
973
+ context 'when rtype signature duplicated' do
974
+ it 'the latest have priority' do
975
+ class PriorityTest1
976
+ rtype :test_priority, [String] => Any
977
+ def test_priority(arg)
978
+ end
979
+ rtype :test_priority, [Integer] => Any
980
+ end
981
+
982
+ PriorityTest1.new.test_priority(1)
983
+ expect { PriorityTest1.new.test_priority("str") }.to raise_error Rtype::ArgumentTypeError
984
+ end
985
+
986
+ it 'annotation mode have priority in contemporaneous signatures' do
987
+ class PriorityTest2
988
+ rtype :test_priority, [String] => Any
989
+ rtype [Integer] => Any
990
+ def test_priority(arg)
991
+ end
992
+ end
993
+
994
+ PriorityTest2.new.test_priority(1)
995
+ expect { PriorityTest2.new.test_priority("str") }.to raise_error Rtype::ArgumentTypeError
996
+ end
997
+ end
819
998
  end
820
999
 
821
1000
  describe "Call Rtype`s static method directly" do
@@ -3,6 +3,7 @@ Coveralls.wear!
3
3
 
4
4
  require 'rtype'
5
5
  require 'rspec'
6
+ require 'set'
6
7
 
7
8
  if !Rtype::NATIVE_EXT_VERSION.nil?
8
9
  puts "Rtype with native extension"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rtype-native
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.6
4
+ version: 0.6.8
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-08-01 00:00:00.000000000 Z
11
+ date: 2016-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rtype
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.6.6
19
+ version: 0.6.8
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.6.6
26
+ version: 0.6.8
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement