rtype 0.6.8-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2b2e38ede798c765cd186f55ba37e7e81431521a
4
+ data.tar.gz: 90e4feb4d148c3ec38e554ee329686bd5f31d216
5
+ SHA512:
6
+ metadata.gz: e3d044c95597ba81652009aecf37917a6d8e79903866b23f76be56a0f1df367f1cf366d4a6bb5a900c27f66e5b71615ad6690a0f6df7d1d2f227f1b0340ddd58
7
+ data.tar.gz: ade3c453f3428dd7d6b7c9e7f24377bea7d6b8df2a7952fdd736775c7dcb67b4be0ff492eb23ad7cb6e936ea7dd920fa29a6d55433a2b48ff374decd1f056e9a
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec :name => 'rtype'
data/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Sputnik Gugja
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,541 @@
1
+ # Rtype: ruby with type
2
+ [![Gem Version](https://badge.fury.io/rb/rtype.svg)](https://badge.fury.io/rb/rtype)
3
+ [![Build Status](https://travis-ci.org/sputnikgugja/rtype.svg?branch=master)](https://travis-ci.org/sputnikgugja/rtype)
4
+ [![Coverage Status](https://coveralls.io/repos/github/sputnikgugja/rtype/badge.svg?branch=master)](https://coveralls.io/github/sputnikgugja/rtype?branch=master)
5
+
6
+ ```ruby
7
+ require 'rtype'
8
+
9
+ class Test
10
+ rtype [:to_i, Numeric] => Numeric
11
+ def sum(a, b)
12
+ a.to_i + b
13
+ end
14
+
15
+ rtype [{state: Boolean}] => Boolean
16
+ def self.invert(state:)
17
+ !state
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
25
+ end
26
+
27
+ Test.new.sum(123, "asd")
28
+ # (Rtype::ArgumentTypeError) for 2nd argument:
29
+ # Expected "asd" to be a Numeric
30
+
31
+ Test.invert(state: 0)
32
+ # (Rtype::ArgumentTypeError) for 'state' argument:
33
+ # Expected 0 to be a Boolean
34
+
35
+ Test.invert2(state: 0)
36
+ # (Rtype::ArgumentTypeError) for 'state' argument:
37
+ # Expected 0 to be a Boolean
38
+ ```
39
+
40
+ ## Requirements
41
+ - Ruby >= 2.1
42
+ - If you need to use old ruby, see [rtype-legacy](https://github.com/sputnikgugja/rtype-legacy) for ruby 1.9+
43
+ - MRI
44
+ - If C native extension is used. otherwise it is not required
45
+ - JRuby (JRuby 9000+)
46
+ - If Java extension is used. otherwise it is not required
47
+
48
+ ## Features
49
+ - Provides type checking for arguments and return
50
+ - Provides type checking for [Keyword Argument](#keyword-argument)
51
+ - [Type checking for hash elements](#hash)
52
+ - [Duck Typing](#duck-typing)
53
+ - [Typed Array](#typed-array), Typed Set, Typed Hash
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)
57
+ - Custom type behavior
58
+ - ...
59
+
60
+ ## Installation
61
+ Run `gem install rtype` or add `gem 'rtype'` to your `Gemfile`
62
+
63
+ And add to your `.rb` source file:
64
+ ```ruby
65
+ require 'rtype'
66
+ ```
67
+
68
+ ### Native extension
69
+ Rtype itself is pure-ruby gem. but you can make it more faster by using native extension.
70
+
71
+ #### Native extension for MRI
72
+ Run
73
+ ```ruby
74
+ gem install rtype-native
75
+ ```
76
+ or add to your `Gemfile`:
77
+ ```ruby
78
+ gem 'rtype-native'
79
+ ```
80
+ then, Rtype uses it. (**Do not** `require 'rtype-native'`)
81
+
82
+ #### Java extension for JRuby is automatic
83
+ **Do not** `require 'rtype-java'`
84
+
85
+ ## Usage
86
+
87
+ ### Supported Type Behaviors
88
+ - `Module` : Value must be of this module (`is_a?`)
89
+ - `Any` : Alias for `BasicObject` (means Any Object)
90
+ - `Boolean` : `true` or `false`
91
+ - `Symbol` : Value must respond to a method with this name
92
+ - `Regexp` : Value must match this regexp pattern
93
+ - `Range` : Value must be included in this range
94
+ - `Array` : Value can be any type in this array
95
+ - `Proc` : Value must return a truthy value for this proc
96
+ - `true` : Value must be truthy
97
+ - `false` : Value must be falsy
98
+ - `nil` : Value must be nil
99
+ - `Hash`
100
+ - Value must be a hash
101
+ - Each of elements must be valid
102
+ - Keys of the value must be equal to keys of this hash
103
+ - **String** key is **different** from **symbol** key
104
+ - vs. Keyword arguments (e.g.)
105
+ - `[{}]` is **not** hash argument. it is keyword argument, because its position is last
106
+ - `[{}, {}]` is hash argument (first) and keyword argument (second)
107
+ - `[{}, {}, {}]` is two hash argument (first, second) and keyword argument (last)
108
+ - `{}` is keyword argument. non-keyword arguments must be in array.
109
+ - Of course, nested hash works
110
+ - Example: [Hash](#hash)
111
+
112
+ - [Special Behaviors](#special-behaviors)
113
+ - `TypedArray, TypedSet, TypedHash`, `Num, Int, Flo`, `And`, `Xor`, `Not`, `Nilable`
114
+
115
+ ### Examples
116
+
117
+ #### Basic
118
+ ```ruby
119
+ require 'rtype'
120
+
121
+ class Example
122
+ rtype [Integer] => nil
123
+ def test(i)
124
+ end
125
+
126
+ rtype [Any] => nil
127
+ def any_type_arg(arg)
128
+ end
129
+
130
+ rtype [] => Integer
131
+ def return_type_test
132
+ "not integer"
133
+ end
134
+ end
135
+
136
+ e = Example.new
137
+ e.test("not integer")
138
+ # (Rtype::ArgumentTypeError) for 1st argument:
139
+ # Expected "not integer" to be a Integer
140
+
141
+ e.any_type_arg("Any argument!") # Works
142
+
143
+ e.return_type_test
144
+ # (Rtype::ReturnTypeError) for return:
145
+ # Expected "not integer" to be a Integer
146
+ ```
147
+
148
+ #### Keyword argument
149
+ ```ruby
150
+ require 'rtype'
151
+
152
+ class Example
153
+ rtype {name: String} => Any
154
+ def say_your_name(name:)
155
+ puts "My name is #{name}"
156
+ end
157
+
158
+ # Mixing positional arguments and keyword arguments
159
+ rtype [String, {age: Integer}] => Any
160
+ def name_and_age(name, age:)
161
+ puts "Name: #{name}, Age: #{age}"
162
+ end
163
+ end
164
+
165
+ Example.new.say_your_name(name: "Babo") # My name is Babo
166
+ Example.new.name_and_age("Bamboo", age: 100) # Name: Bamboo, Age: 100
167
+
168
+ Example.new.say_your_name(name: 12345)
169
+ # (Rtype::ArgumentTypeError) for 'name' argument:
170
+ # Expected 12345 to be a String
171
+ ```
172
+
173
+ #### Duck typing
174
+ ```ruby
175
+ require 'rtype'
176
+
177
+ class Duck
178
+ rtype [:to_i] => Any
179
+ def says(i)
180
+ puts "duck:" + " quack"*i.to_i
181
+ end
182
+ end
183
+
184
+ Duck.new.says("2") # duck: quack quack
185
+ ```
186
+
187
+ #### Array
188
+ ```ruby
189
+ rtype :ruby!, [[String, Integer]] => Any
190
+ def ruby!(arg)
191
+ puts "ruby!"
192
+ end
193
+
194
+ func("str") # ruby!
195
+ func(123) # ruby!
196
+
197
+ func(nil)
198
+ # (Rtype::ArgumentTypeError) for 1st argument:
199
+ # Expected nil to be a String
200
+ # OR Expected nil to be a Integer
201
+ ```
202
+
203
+ #### Hash
204
+ ```ruby
205
+ # last hash element is keyword arguments
206
+ rtype :func, [{msg: String}, {}] => Any
207
+ def func(hash)
208
+ puts hash[:msg]
209
+ end
210
+
211
+ func({})
212
+ # (Rtype::ArgumentTypeError) for 1st argument:
213
+ # Expected {} to be a hash with 1 elements:
214
+ # - msg : Expected nil to be a String
215
+
216
+ func({msg: 123})
217
+ # (Rtype::ArgumentTypeError) for 1st argument:
218
+ # Expected {:msg=>123} to be a hash with 1 elements:
219
+ # - msg : Expected 123 to be a String
220
+
221
+ func({msg: "hello", key: 'value'})
222
+ # (Rtype::ArgumentTypeError) for 1st argument:
223
+ # Expected {:msg=>"hello", :key=>"value"} to be a hash with 1 elements:
224
+ # - msg : Expected "hello" to be a String
225
+
226
+ func({"msg" => "hello hash"})
227
+ # (Rtype::ArgumentTypeError) for 1st argument:
228
+ # Expected {"msg"=>"hello hash"} to be a hash with 1 elements:
229
+ # - msg : Expected nil to be a String
230
+
231
+ func({msg: "hello hash"}) # hello hash
232
+ ```
233
+
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
238
+
239
+ You can use `rtype_accessor_self` for static accessor. (`rtype_reader_self`, `rtype_writer_self` also exist)
240
+
241
+ ```ruby
242
+ require 'rtype'
243
+
244
+ class Example
245
+ rtype_accessor :value, String
246
+
247
+ def initialize
248
+ @value = 456
249
+ end
250
+ end
251
+
252
+ Example.new.value = 123
253
+ # (Rtype::ArgumentTypeError) for 1st argument:
254
+ # Expected 123 to be a String
255
+
256
+ Example.new.value
257
+ # (Rtype::ReturnTypeError) for return:
258
+ # Expected 456 to be a String
259
+ ```
260
+
261
+ #### Typed Array
262
+ ```ruby
263
+ ### TEST 1 ###
264
+ class Test
265
+ rtype [Array.of(Integer)] => Any
266
+ def sum(args)
267
+ num = 0
268
+ args.each { |e| num += e }
269
+ end
270
+ end
271
+
272
+ sum([1, 2, 3]) # => 6
273
+
274
+ sum([1.0, 2, 3])
275
+ # (Rtype::ArgumentTypeError) for 1st argument:
276
+ # Expected [1.0, 2, 3] to be an array with type Integer"
277
+ ```
278
+
279
+ ```ruby
280
+ ### TEST 2 ###
281
+ class Test
282
+ rtype [ Array.of([Integer, Float]) ] => Any
283
+ def sum(args)
284
+ num = 0
285
+ args.each { |e| num += e }
286
+ end
287
+ end
288
+
289
+ sum([1, 2, 3]) # => 6
290
+ sum([1.0, 2, 3]) # => 6.0
291
+ ```
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
+
316
+ #### `rtype`
317
+ ```ruby
318
+ require 'rtype'
319
+
320
+ class Example
321
+ # Recommended. With annotation mode (no method name required)
322
+ rtype [Integer, String] => String
323
+ def hello_world(i, str)
324
+ puts "Hello? #{i} #{st
325
+ end
326
+
327
+ # Works (with specifying method name)
328
+ rtype :hello_world, [Integer, String] => String
329
+ def hello_world(i, str)
330
+ puts "Hello? #{i} #{st
331
+ end
332
+
333
+ # Works
334
+ def hello_world_two(i, str)
335
+ puts "Hello? #{i} #{str}"
336
+ end
337
+ rtype :hello_world_two, [Integer, String] => String
338
+
339
+ # Also works (String will be converted to Symbol)
340
+ rtype 'hello_world_three', [Integer, String] => String
341
+ def hello_world_three(i, str)
342
+ puts "Hello? #{i} #{str}"
343
+ end
344
+
345
+ # Doesn't work. annotation mode works for following (next) method
346
+ def hello_world_four(i, str)
347
+ puts "Hello? #{i} #{str}"
348
+ end
349
+ rtype [Integer, String] => String
350
+ end
351
+ ```
352
+
353
+ #### In the outside of module (root)
354
+ In the outside of module, annotation mode doesn't work. You must specify method name.
355
+
356
+ ```ruby
357
+ rtype :say, [String] => Any
358
+ def say(message)
359
+ puts message
360
+ end
361
+
362
+ Test.new.say "Hello" # Hello
363
+
364
+ rtype [String] => Any
365
+ # (ArgumentError) Annotation mode not working in the outside of module
366
+ ```
367
+
368
+ #### Class method
369
+ Annotation mode works for both instance method and class method
370
+
371
+ ```ruby
372
+ require 'rtype'
373
+
374
+ class Example
375
+ rtype [:to_i] => Any
376
+ def self.say_ya(i)
377
+ puts "say" + " ya"*i.to_i
378
+ end
379
+ end
380
+
381
+ Example::say_ya(3) #say ya ya ya
382
+ ```
383
+
384
+ if you specify method name, however, you must use `rtype_self` instead of `rtype`
385
+
386
+ ```ruby
387
+ require 'rtype'
388
+
389
+ class Example
390
+ rtype_self :say_ya, [:to_i] => Any
391
+ def self.say_ya(i)
392
+ puts "say" + " ya"*i.to_i
393
+ end
394
+ end
395
+
396
+ Example::say_ya(3) #say ya ya ya
397
+ ```
398
+
399
+ #### Type information
400
+ This is just 'information'
401
+
402
+ Any change of this doesn't affect type checking
403
+
404
+ ```ruby
405
+ require 'rtype'
406
+
407
+ class Example
408
+ rtype [:to_i] => Any
409
+ def test(i)
410
+ end
411
+ end
412
+
413
+ Example.new.method(:test).type_info
414
+ # => [:to_i] => Any
415
+ Example.new.method(:test).argument_type
416
+ # => [:to_i]
417
+ Example.new.method(:test).return_type
418
+ # => Any
419
+ ```
420
+
421
+ #### Special Behaviors
422
+ - `TypedArray` : Ensures value is an array with the type (type signature)
423
+ - `Array.of(type)` (recommended)
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)
431
+
432
+ - `Num, Int, Flo` : Numeric check
433
+ - `Num/Int/Flo >/>=/</<=/== x`
434
+ - e.g. `Num >= 2` means value must be a `Numeric` and >= 2
435
+ - e.g. `Int >= 2` means value must be a `Integer` and >= 2
436
+ - e.g. `Flo >= 2` means value must be a `Float` and >= 2
437
+
438
+ - `And` : Ensures value is valid for all given types
439
+ - `Rtype.and(*types)`, `Rtype::Behavior::And[*types]`
440
+ - or `Array#comb`, `Object#and(*others)`
441
+
442
+ - `Xor` : Ensures value is valid for only one of given types
443
+ - `Rtype.xor(*types)`, `Rtype::Behavior::Xor[*types]`
444
+ - or `Object#xor(*others)`
445
+
446
+ - `Not` : Ensures value is not valid for all given types
447
+ - `Rtype.not(*types)`, `Rtype::Behavior::Not[*types]`
448
+ - or `Object#not`
449
+
450
+ - `Nilable` : Value can be nil
451
+ - `Rtype.nilable(type)`, `Rtype::Behavior::Nilable[type]`
452
+ - or `Object#nilable`, `Object#or_nil`
453
+
454
+ - You can create custom behaviors by extending `Rtype::Behavior::Base`
455
+
456
+ ## Documentation
457
+ [RubyDoc.info](http://www.rubydoc.info/gems/rtype)
458
+
459
+ ## Benchmarks
460
+ Result of `rake benchmark` ([source](https://github.com/sputnikgugja/rtype/tree/master/benchmark/benchmark.rb))
461
+
462
+ ### MRI
463
+ ```
464
+ Rtype with C native extension
465
+ Ruby version: 2.1.7
466
+ Ruby engine: ruby
467
+ Ruby description: ruby 2.1.7p400 (2015-08-18 revision 51632) [x64-mingw32]
468
+ Rtype version: 0.3.0
469
+ Rubype version: 0.3.1
470
+ Sig version: 1.0.1
471
+ Contracts version: 0.13.0
472
+ Typecheck version: 0.1.2
473
+ Warming up --------------------------------------
474
+ pure 85.328k i/100ms
475
+ rtype 25.665k i/100ms
476
+ rubype 21.414k i/100ms
477
+ sig 8.921k i/100ms
478
+ contracts 4.638k i/100ms
479
+ typecheck 1.110k i/100ms
480
+ Calculating -------------------------------------
481
+ pure 3.282M (± 2.7%) i/s - 16.468M
482
+ rtype 339.065k (± 2.6%) i/s - 1.720M
483
+ rubype 266.893k (± 5.9%) i/s - 1.349M
484
+ sig 99.952k (± 2.1%) i/s - 499.576k
485
+ contracts 49.693k (± 1.5%) i/s - 250.452k
486
+ typecheck 11.356k (± 1.6%) i/s - 57.720k
487
+
488
+ Comparison:
489
+ pure: 3282431.9 i/s
490
+ rtype: 339064.9 i/s - 9.68x slower
491
+ rubype: 266892.9 i/s - 12.30x slower
492
+ sig: 99952.2 i/s - 32.84x slower
493
+ contracts: 49693.0 i/s - 66.05x slower
494
+ typecheck: 11355.9 i/s - 289.05x slower
495
+ ```
496
+
497
+ ### JRuby
498
+ Without Rubype that doesn't support JRuby
499
+
500
+ ```
501
+ Rtype with Java extension
502
+ Ruby version: 2.2.3
503
+ Ruby engine: jruby
504
+ 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]
505
+ Rtype version: 0.3.0
506
+ Sig version: 1.0.1
507
+ Contracts version: 0.13.0
508
+ Typecheck version: 0.1.2
509
+ Warming up --------------------------------------
510
+ pure 9.994k i/100ms
511
+ rtype 6.181k i/100ms
512
+ sig 4.041k i/100ms
513
+ contracts 951.000 i/100ms
514
+ typecheck 970.000 i/100ms
515
+ Calculating -------------------------------------
516
+ pure 7.128M (?±35.6%) i/s - 30.831M
517
+ rtype 121.556k (?± 6.2%) i/s - 605.738k
518
+ sig 72.187k (?± 6.4%) i/s - 359.649k
519
+ contracts 24.984k (?± 3.9%) i/s - 125.532k
520
+ typecheck 12.041k (?± 9.5%) i/s - 60.140k
521
+
522
+ Comparison:
523
+ pure: 7128373.0 i/s
524
+ rtype: 121555.8 i/s - 58.64x slower
525
+ sig: 72186.8 i/s - 98.75x slower
526
+ contracts: 24984.5 i/s - 285.31x slower
527
+ typecheck: 12041.0 i/s - 592.01x slower
528
+ ```
529
+
530
+ ## Rubype, Sig
531
+ Rtype is influenced by [Rubype](https://github.com/gogotanaka/Rubype) and [Sig](https://github.com/janlelis/sig).
532
+
533
+ If you don't like Rtype, You can use other library such as Contracts, Rubype, Rtc, Typecheck, Sig.
534
+
535
+ ## Author
536
+ Sputnik Gugja (sputnikgugja@gmail.com)
537
+
538
+ ## License
539
+ MIT license (@ Sputnik Gugja)
540
+
541
+ See `LICENSE` file.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require "rspec/core/rake_task"
2
+
3
+ # Default pattern is 'spec/**{,/*/**}/*_spec.rb'
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => [:spec]
7
+
8
+ # Benchmark
9
+ desc "Compare with pure ruby and other gems"
10
+ task :benchmark do
11
+ ruby "benchmark/benchmark.rb"
12
+ end