typecheck 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +1 -1
- data/Rakefile +2 -2
- data/lib/typecheck.rb +12 -7
- data/spec/integration/typecheck_spec.rb +54 -17
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f76e0be630cb566def0e4b2b83b427afc0e856d5
|
4
|
+
data.tar.gz: 26f08e776636a425f7834e2338ad68a3f169cdae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d29e6f557d66947c70949de7a006200484767f0614d58bc216174c335f88e6a0b847293efdebf2a46a23d75b08d1d3220680a7bf6797af341aadcf44542bf59
|
7
|
+
data.tar.gz: 435e26ef5a06df032b63dfa4bd1a1a3531b5f0e914b1711f51d1e31892ba622665dbf16351127374627f2861e38bd3ca12d1db23c0168a1952dc0b69585dd058
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pkg
|
data/Gemfile.lock
CHANGED
data/Rakefile
CHANGED
@@ -10,7 +10,7 @@ task :default => :mutant
|
|
10
10
|
|
11
11
|
task :mutant do
|
12
12
|
pattern = ENV.fetch('PATTERN', 'Typecheck*')
|
13
|
-
result = Mutant::CLI.run(%w[-Ilib -rtypecheck --use rspec --score
|
13
|
+
result = Mutant::CLI.run(%w[-Ilib -rtypecheck --use rspec --score 99] + [pattern])
|
14
14
|
fail unless result == Mutant::CLI::EXIT_SUCCESS
|
15
15
|
end
|
16
16
|
|
@@ -24,7 +24,7 @@ gem.define
|
|
24
24
|
|
25
25
|
desc "Push gem to rubygems.org"
|
26
26
|
task :push => :gem do
|
27
|
-
|
27
|
+
sh "git tag v#{Typecheck::VERSION}"
|
28
28
|
sh "git push --tags"
|
29
29
|
sh "gem push pkg/typecheck-#{Typecheck::VERSION}.gem"
|
30
30
|
end
|
data/lib/typecheck.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Typecheck
|
2
|
-
VERSION = '0.1.
|
2
|
+
VERSION = '0.1.1'
|
3
3
|
|
4
4
|
def typecheck(signature, method)
|
5
5
|
alias_method "#{method}_unchecked", method
|
@@ -57,9 +57,9 @@ module Typecheck
|
|
57
57
|
pred_and subtype.split(';').map(&:strip).map { |type|
|
58
58
|
case type
|
59
59
|
when /#(.*)/
|
60
|
-
method("#{check_or_raise}_respond_to").to_proc.curry.(
|
60
|
+
method("#{check_or_raise}_respond_to").to_proc.curry.(type[1..-1])
|
61
61
|
when /\[(.*)\]/
|
62
|
-
method("#{check_or_raise}_array").to_proc.curry.(eval(
|
62
|
+
method("#{check_or_raise}_array").to_proc.curry.(eval(type[1..-2]))
|
63
63
|
else
|
64
64
|
method("#{check_or_raise}_class").to_proc.curry.(eval(type))
|
65
65
|
end
|
@@ -67,11 +67,12 @@ module Typecheck
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def check_respond_to(method, value)
|
70
|
-
value.respond_to?
|
70
|
+
value.respond_to?(method)
|
71
71
|
end
|
72
72
|
|
73
73
|
def raise_respond_to(method, value)
|
74
|
-
raise "Expected #{value.inspect}, to respond_to #{method}" unless check_respond_to(method, value)
|
74
|
+
raise TypeError, "Expected #{value.inspect}, to respond_to #{method}" unless check_respond_to(method, value)
|
75
|
+
true
|
75
76
|
end
|
76
77
|
|
77
78
|
def check_array(type, array)
|
@@ -79,7 +80,8 @@ module Typecheck
|
|
79
80
|
end
|
80
81
|
|
81
82
|
def raise_array(type, array)
|
82
|
-
raise "Bad type: #{array
|
83
|
+
raise TypeError, "Bad type: expected #{array} to only contain #{type}" unless check_array(type, array)
|
84
|
+
true
|
83
85
|
end
|
84
86
|
|
85
87
|
def check_class(klz, value)
|
@@ -87,7 +89,10 @@ module Typecheck
|
|
87
89
|
end
|
88
90
|
|
89
91
|
def raise_class(klz, value)
|
90
|
-
raise "Bad type: #{value.inspect}, expected #{klz}" unless check_class(klz, value)
|
92
|
+
raise TypeError, "Bad type: #{value.inspect}, expected #{klz}" unless check_class(klz, value)
|
93
|
+
true
|
91
94
|
end
|
92
95
|
end
|
96
|
+
|
97
|
+
TypeError = Class.new(StandardError)
|
93
98
|
end
|
@@ -7,9 +7,9 @@ describe Typecheck do
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
shared_examples 'invalid' do |method, args|
|
10
|
+
shared_examples 'invalid' do |method, args, message = '', error = Typecheck::TypeError|
|
11
11
|
it 'should typecheck' do
|
12
|
-
expect{subject.send(method, *args)}.to
|
12
|
+
expect{subject.send(method, *args)}.to raise_error(error, message)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -40,12 +40,22 @@ describe Typecheck do
|
|
40
40
|
def multi(range)
|
41
41
|
('x' * range.end).chars.drop(range.begin).join.intern
|
42
42
|
end
|
43
|
-
typecheck '#begin
|
43
|
+
typecheck '#begin; #end -> Symbol', :multi
|
44
|
+
|
45
|
+
def multi2(comp_enum)
|
46
|
+
:foo
|
47
|
+
end
|
48
|
+
typecheck 'Comparable;Enumerable -> Symbol', :multi2
|
49
|
+
|
50
|
+
def multi3(comp_enum)
|
51
|
+
:foo
|
52
|
+
end
|
53
|
+
typecheck '[Fixnum];[String] -> Symbol', :multi3
|
44
54
|
|
45
55
|
def choice(x)
|
46
56
|
:foo
|
47
57
|
end
|
48
|
-
typecheck '#to_str|Fixnum ->
|
58
|
+
typecheck '#to_str | Fixnum -> Symbol', :choice
|
49
59
|
|
50
60
|
def arrays(nums, strings)
|
51
61
|
(nums + strings.map(&:length)).inject(:+)
|
@@ -55,39 +65,66 @@ describe Typecheck do
|
|
55
65
|
def optional(num, str = nil, sym = nil)
|
56
66
|
num
|
57
67
|
end
|
58
|
-
typecheck 'Fixnum,String,Symbol -> Numeric', :optional
|
68
|
+
typecheck 'Fixnum, String, Symbol -> Numeric', :optional
|
59
69
|
end
|
60
70
|
end
|
61
71
|
|
62
72
|
subject { checked_class.new }
|
73
|
+
comparable = Class.new { include Comparable }.new
|
63
74
|
|
64
75
|
include_examples 'valid', :double_me, [7], 14
|
65
|
-
include_examples 'invalid', :double_me, ['foo']
|
66
|
-
include_examples 'invalid', :double_me, []
|
76
|
+
include_examples 'invalid', :double_me, ['foo'], 'Bad type: "foo", expected Numeric'
|
77
|
+
include_examples 'invalid', :double_me, [], 'wrong number of arguments (0 for 1)', ArgumentError
|
67
78
|
|
68
|
-
include_examples 'invalid', :bad_out, [42]
|
79
|
+
include_examples 'invalid', :bad_out, [42], 'Bad type: :sym, expected Numeric'
|
69
80
|
|
70
81
|
include_examples 'valid', :strsym_num, ['foo', :bar], 3
|
71
|
-
include_examples 'invalid', :strsym_num, [:foo, 'bar']
|
82
|
+
include_examples 'invalid', :strsym_num, [:foo, 'bar'], 'Bad type: :foo, expected String'
|
72
83
|
|
73
84
|
include_examples 'valid', :duck, ['foo'], :FOO
|
74
|
-
include_examples 'invalid', :duck, [7]
|
85
|
+
include_examples 'invalid', :duck, [7], /to respond_to to_str/
|
75
86
|
|
76
87
|
include_examples 'valid', :multi, [3..5], :xx
|
77
|
-
include_examples 'invalid', :multi, [Class.new { def begin ; end }.new]
|
78
|
-
include_examples 'invalid', :multi, [7]
|
88
|
+
include_examples 'invalid', :multi, [Class.new { def begin ; end }.new], /to respond_to end/
|
89
|
+
include_examples 'invalid', :multi, [7], /to respond_to begin/
|
90
|
+
include_examples 'invalid', :multi, ["foo"], /Expected "foo", to respond_to begin/
|
91
|
+
|
92
|
+
include_examples 'invalid', :multi2, [3..6], /Bad type.* expected Comparable/
|
93
|
+
include_examples 'invalid', :multi2, [comparable], /Bad type.* expected Enumerable/
|
94
|
+
|
95
|
+
include_examples 'invalid', :multi3, [[3.5]], 'Bad type: expected [3.5] to only contain Fixnum'
|
96
|
+
include_examples 'invalid', :multi3, [[3]], /to only contain String/
|
79
97
|
|
80
98
|
include_examples 'valid', :choice, ['foo'], :foo
|
81
99
|
include_examples 'valid', :choice, [9], :foo
|
82
|
-
include_examples 'invalid', :choice, [5..9]
|
83
|
-
include_examples 'invalid', :choice, [5.9]
|
100
|
+
include_examples 'invalid', :choice, [5..9], /Expected 5..9, to respond_to to_str/
|
101
|
+
include_examples 'invalid', :choice, [5.9], /Expected 5.9, to respond_to to_str/
|
84
102
|
|
85
103
|
include_examples 'valid', :arrays, [[1,2], ['x', 'y']], 5
|
86
|
-
include_examples 'invalid', :arrays, [[:foo], ['x']]
|
104
|
+
include_examples 'invalid', :arrays, [[:foo], ['x']], /\[:foo\] to only contain Fixnum/
|
87
105
|
|
88
106
|
include_examples 'valid', :optional, [1, 'x', :foo], 1
|
89
107
|
include_examples 'valid', :optional, [1, 'x'], 1
|
90
108
|
include_examples 'valid', :optional, [1], 1
|
91
|
-
include_examples 'invalid', :optional, [1, 'x', 'y'], 1
|
92
|
-
include_examples 'invalid', :optional, []
|
109
|
+
include_examples 'invalid', :optional, [1, 'x', 'y'], 1, 'Bad type: "y", expected Symbol'
|
110
|
+
include_examples 'invalid', :optional, [], /wrong number of arguments/, ArgumentError
|
111
|
+
|
112
|
+
it 'should make the original method available' do
|
113
|
+
expect(subject.double_me_unchecked('foo')).to eq 'foofoo'
|
114
|
+
end
|
115
|
+
|
116
|
+
describe Typecheck::SignatureCompiler do
|
117
|
+
describe '#parse_type' do
|
118
|
+
let(:compiler) { Typecheck::SignatureCompiler.new }
|
119
|
+
|
120
|
+
it 'should work with ; for "or"' do
|
121
|
+
x = Class.new { def begin ; end }.new
|
122
|
+
|
123
|
+
expect( compiler.parse_type('#begin;#end', :check).(x) ).to be false
|
124
|
+
expect{ compiler.raise_respond_to('end', x) }.to raise_error
|
125
|
+
expect{ compiler.parse_type('#begin;#end', :raise).(x) }.to raise_error
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
93
130
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: typecheck
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arne Brasseur
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
11
|
+
date: 2014-04-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -61,6 +61,7 @@ extra_rdoc_files:
|
|
61
61
|
- README.md
|
62
62
|
- LICENSE
|
63
63
|
files:
|
64
|
+
- .gitignore
|
64
65
|
- Gemfile
|
65
66
|
- Gemfile.lock
|
66
67
|
- LICENSE
|