rdl 2.0.0.rc1 → 2.0.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +19 -4
- data/lib/rdl.rb +4 -2
- data/lib/rdl/config.rb +42 -11
- data/lib/rdl/typecheck.rb +7 -2
- data/lib/rdl/wrap.rb +112 -75
- data/rdl.gemspec +2 -2
- data/test/test_typecheck.rb +70 -30
- data/types/ruby-2.x/module.rb +83 -0
- 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: b977016fb74ea728b29a3eaa767aec63ee0d6a7b
|
4
|
+
data.tar.gz: 45b460bc49df3fca8248811e582617229142c35d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2922f3d18c4c5398a520202d8930806545e05db55a449110a9837fef4c06293dc44ef98a3c3ca70a74c639d69114ae2d93f711ad0099dd11ae9ba730ab05b7b8
|
7
|
+
data.tar.gz: c36055f80360a2b6cdf4d732d7d7419e5783512b9d947f08ab933358d9ed0fef34c62fdb8b1d8ed2ec34d24f2cdcf9dd12c5cf03472b550714dce384ffa56cf6
|
data/README.md
CHANGED
@@ -77,7 +77,7 @@ The beta version of RDL also has an experimental mode in which method bodies can
|
|
77
77
|
file.rb:
|
78
78
|
require 'rdl'
|
79
79
|
|
80
|
-
type '(Fixnum) -> Fixnum',
|
80
|
+
type '(Fixnum) -> Fixnum', typecheck: :now
|
81
81
|
def id(x)
|
82
82
|
"forty-two"
|
83
83
|
end
|
@@ -91,7 +91,7 @@ $ ruby file.rb
|
|
91
91
|
.../file.rb:5: ^~~~~~~~~~~
|
92
92
|
```
|
93
93
|
|
94
|
-
Passing `
|
94
|
+
Passing `typecheck: :now` to `type` checks the method body immediately or as soon as it is defined. Passing `typecheck: :call` to `type` statically type checks the method body whenever it is called. Passing `typecheck: sym` for some other symbol statically type checks the method body when `rdl_do_typecheck sym` is called.
|
95
95
|
|
96
96
|
RDL contracts and types are stored in memory at run time, so it's also possible for programs to query them. RDL includes lots of contracts and types for the core and standard libraries. Since those methods are generally trustworthy, RDL doesn't actually enforce the contracts (since that would add overhead), but they are available to search and query. RDL includes a small script `rdl_query` to look up type information from the command line. Note you might need to put the argument in quotes depending on your shell.
|
97
97
|
|
@@ -540,9 +540,11 @@ RDL also includes a special *bottom* type `%bot` that is a subtype of any type,
|
|
540
540
|
|
541
541
|
# Static Type Checking
|
542
542
|
|
543
|
-
RDL has experimental support (note: this is in beta release) for static type checking. As mentioned in the introduction, calling `type` with `
|
543
|
+
RDL has experimental support (note: this is in beta release) for static type checking. As mentioned in the introduction, calling `type` with `typecheck: :now` statically type checks the body of the annotated method body against the given signature. If the method has already been defined, RDL will try to check the method immediately. Otherwise, RDL will statically type check the method as soon as it is loaded.
|
544
544
|
|
545
|
-
Often method bodies cannot be type checked as soon as they are loaded because they refer to classes, methods, and variables that have not been created yet. To support these cases,
|
545
|
+
Often method bodies cannot be type checked as soon as they are loaded because they refer to classes, methods, and variables that have not been created yet. To support these cases, some other symbol can be supplied as `typecheck: sym`. Then when `rdl_do_typecheck sym` is called, all methods typechecked at `sym` will be statically checked.
|
546
|
+
|
547
|
+
Addditionally, `type` can be called with `typecheck: :call`, which will delay checking the method's type until the method is called. Currently these checks are not cached, so expect a big performance hit for using this feature.
|
546
548
|
|
547
549
|
To perform type checking, RDL needs source code, which it gets by parsing the file containing the to-be-typechecked method. Hence, static type checking does not work in `irb` since RDL has no way of getting the source. RDL currently uses the [parser Gem](https://github.com/whitequark/parser) to parse Ruby source code. (And RDL uses the parser gem's amazing diagnostic output facility to print type error messages.)
|
548
550
|
|
@@ -590,6 +592,17 @@ end
|
|
590
592
|
|
591
593
|
The `var_type` method may also be called as `var_type klass, :name, typ` to assign a type to an instance or class variable of class `klass`.
|
592
594
|
|
595
|
+
As a short-hand, RDL defines methods `attr_accessor_type`, `attr_reader_type`, and `attr_writer_type` to behave like their corresponding non-`_type` analogs but attribute types follow the attribute names. For example, `attr_accessor_type :f, 'Fixnum', :g, 'String'` is equivalent to:
|
596
|
+
|
597
|
+
```ruby
|
598
|
+
var_type :@f, 'Fixnum'
|
599
|
+
var_type :@g, 'String'
|
600
|
+
type :f, '() -> Fixnum'
|
601
|
+
type :f=, '(Fixnum) -> Fixnum'
|
602
|
+
type :g, '() -> String'
|
603
|
+
type :g=, '(String) -> String'
|
604
|
+
```
|
605
|
+
|
593
606
|
## Tuples, Finite Hashes, and Subtyping
|
594
607
|
|
595
608
|
When RDL encounters a literal array in the program, it assigns it a tuple type, which allows, among other things, precise handling of multiple assignment. For example:
|
@@ -791,3 +804,5 @@ Copyright (c) 2014-2016, University of Maryland, College Park. All rights reserv
|
|
791
804
|
* Queries, include more regexp operators aside from . and ...
|
792
805
|
|
793
806
|
* Queries, allow regexp in class and method names; suggested by Andreas Adamcik, Vienna
|
807
|
+
|
808
|
+
* Tag for private methods
|
data/lib/rdl.rb
CHANGED
@@ -39,8 +39,10 @@ $__rdl_aliases = Hash.new
|
|
39
39
|
# method is a symbol
|
40
40
|
$__rdl_to_wrap = Set.new
|
41
41
|
|
42
|
-
#
|
43
|
-
|
42
|
+
# Map from symbols to set of [class, method] pairs to type check when those symbols are rdl_do_typecheck'd
|
43
|
+
# (or the methods are defined, for the symbol :now)
|
44
|
+
$__rdl_to_typecheck = Hash.new
|
45
|
+
$__rdl_to_typecheck[:now] = Set.new
|
44
46
|
|
45
47
|
# List of contracts that should be applied to the next method definition
|
46
48
|
$__rdl_deferred = []
|
data/lib/rdl/config.rb
CHANGED
@@ -5,10 +5,12 @@ class RDL::Config
|
|
5
5
|
|
6
6
|
attr_accessor :nowrap
|
7
7
|
attr_accessor :gather_stats
|
8
|
-
|
8
|
+
attr_accessor :report
|
9
|
+
|
9
10
|
def initialize
|
10
11
|
@nowrap = Set.new
|
11
|
-
@gather_stats =
|
12
|
+
@gather_stats = false
|
13
|
+
@report = false
|
12
14
|
end
|
13
15
|
|
14
16
|
def add_nowrap(*klasses)
|
@@ -18,7 +20,7 @@ class RDL::Config
|
|
18
20
|
def remove_nowrap(*klasses)
|
19
21
|
klasses.each { |klass| @nowrap.delete klass }
|
20
22
|
end
|
21
|
-
|
23
|
+
|
22
24
|
# To use, copy these 3 lines to the test file of a gem
|
23
25
|
=begin
|
24
26
|
require_relative '../rdl3/rdl/lib/rdl.rb'
|
@@ -28,7 +30,7 @@ RDL::Config.instance.profile_stats
|
|
28
30
|
def profile_stats(outname="/#{__FILE__[0...-3]}",outdir="")
|
29
31
|
require 'profile'
|
30
32
|
Profiler__.stop_profile # Leave setup out of stats
|
31
|
-
|
33
|
+
|
32
34
|
at_exit do
|
33
35
|
Profiler__.stop_profile
|
34
36
|
$__rdl_contract_switch.off {
|
@@ -40,7 +42,7 @@ RDL::Config.instance.profile_stats
|
|
40
42
|
# [-1] -> Contract exists for method, but method not profiled
|
41
43
|
# [-1, ...] -> Method profiled, but no contract exists
|
42
44
|
totals = {}
|
43
|
-
|
45
|
+
|
44
46
|
puts "Retrieving Profiler Data"
|
45
47
|
Profiler__.class_variable_get(:@@maps).values.each do |threadmap|
|
46
48
|
threadmap.each do |key, data|
|
@@ -50,7 +52,7 @@ RDL::Config.instance.profile_stats
|
|
50
52
|
total_data[3] += data[2]
|
51
53
|
end
|
52
54
|
end
|
53
|
-
|
55
|
+
|
54
56
|
puts "Scanning Object Space"
|
55
57
|
kls = []
|
56
58
|
ObjectSpace.each_object { |obj|
|
@@ -65,7 +67,7 @@ RDL::Config.instance.profile_stats
|
|
65
67
|
totals["#{obj.class}::#{mthd.to_s}".gsub('::','#')] ||= [nil] unless mthd.to_s =~ /new/
|
66
68
|
}
|
67
69
|
}
|
68
|
-
|
70
|
+
|
69
71
|
p "Scanning RDL Contract Log"
|
70
72
|
$__rdl_wrapped_calls.each{ |mname,ct|
|
71
73
|
if (totals[mname]) then
|
@@ -76,13 +78,13 @@ RDL::Config.instance.profile_stats
|
|
76
78
|
end
|
77
79
|
end
|
78
80
|
}
|
79
|
-
|
81
|
+
|
80
82
|
puts "Analyzing Statistics"
|
81
83
|
filtered = {}
|
82
84
|
totals.each{ |k,v|
|
83
85
|
if (not (k=~/(rdl)|(RDL)/)) and (v[0].nil? or v[0]==-1) then filtered[k]=v end
|
84
86
|
}
|
85
|
-
|
87
|
+
|
86
88
|
puts "Writing Output"
|
87
89
|
require 'json'
|
88
90
|
fpath = "#{outdir}/#{outname}_rdlstat.json".gsub('//','')
|
@@ -115,7 +117,36 @@ RDL::Config.instance.profile_stats
|
|
115
117
|
puts "DONE."
|
116
118
|
}
|
117
119
|
end
|
118
|
-
|
120
|
+
|
119
121
|
Profiler__.start_profile # Restart profiler after setup
|
120
122
|
end
|
121
|
-
end
|
123
|
+
end
|
124
|
+
|
125
|
+
at_exit do
|
126
|
+
if RDL::Config.instance.report
|
127
|
+
typechecked = []
|
128
|
+
missing = []
|
129
|
+
$__rdl_info.info.each_pair { |klass, meths|
|
130
|
+
meths.each { |meth, kinds|
|
131
|
+
if kinds[:typecheck]
|
132
|
+
if kinds[:typechecked]
|
133
|
+
typechecked << [klass, meth]
|
134
|
+
else
|
135
|
+
missing << [klass, meth]
|
136
|
+
end
|
137
|
+
elsif kinds[:typechecked]
|
138
|
+
raise RuntimeError, "#{RDL::Util.pp_klass_method(klass, meth)} typechecked but not annotated to do so?!"
|
139
|
+
end
|
140
|
+
}
|
141
|
+
}
|
142
|
+
unless typechecked.empty?
|
143
|
+
puts "TYPECHECKED METHODS:"
|
144
|
+
typechecked.each { |klass, meth| puts RDL::Util.pp_klass_method(klass, meth) }
|
145
|
+
end
|
146
|
+
unless missing.empty?
|
147
|
+
puts unless typechecked.empty?
|
148
|
+
puts "METHODS ANNOTATED TO BE TYPECHECKED BUT NOT TYPECHECKED:"
|
149
|
+
missing.each { |klass, meth| puts RDL::Util.pp_klass_method(klass, meth) }
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
data/lib/rdl/typecheck.rb
CHANGED
@@ -152,6 +152,7 @@ module RDL::Typecheck
|
|
152
152
|
def self.typecheck(klass, meth)
|
153
153
|
file, line = $__rdl_info.get(klass, meth, :source_location)
|
154
154
|
raise RuntimeError, "static type checking in irb not supported" if file == "(irb)"
|
155
|
+
raise RuntimeError, "No file for #{RDL::Util.pp_klass_method(klass, meth)}" if file.nil?
|
155
156
|
digest = Digest::MD5.file file
|
156
157
|
cache_hit = (($__rdl_ruby_parser_cache.has_key? file) &&
|
157
158
|
($__rdl_ruby_parser_cache[file][0] == digest))
|
@@ -185,13 +186,16 @@ module RDL::Typecheck
|
|
185
186
|
end
|
186
187
|
inst = {self: self_type}
|
187
188
|
type = type.instantiate inst
|
188
|
-
|
189
|
+
unless type.args.length == args.children.length
|
190
|
+
error :arg_count_mismatch, ['method', type.args.length, 'method', args.children.length], (if args.children.empty? then ast else args end)
|
191
|
+
end
|
189
192
|
a = args.children.map { |arg| arg.children[0] }.zip(type.args).to_h
|
190
193
|
a[:self] = self_type
|
191
194
|
scope = {tret: type.ret, tblock: type.block }
|
192
195
|
_, body_type = if body.nil? then [nil, $__rdl_nil_type] else tc(scope, Env.new(a), body) end
|
193
196
|
error :bad_return_type, [body_type.to_s, type.ret.to_s], body unless body.nil? || body_type <= type.ret
|
194
197
|
}
|
198
|
+
$__rdl_info.set(klass, meth, :typechecked, true)
|
195
199
|
end
|
196
200
|
|
197
201
|
# The actual type checking logic.
|
@@ -1012,7 +1016,8 @@ RUBY
|
|
1012
1016
|
end
|
1013
1017
|
tancestor = $__rdl_info.get(ancestor_name, name, :type)
|
1014
1018
|
return tancestor if tancestor
|
1015
|
-
if (if RDL::Util.has_singleton_marker(ancestor_name) then ancestor.singleton_methods.member?(name) else ancestor.instance_methods.member?(name) end)
|
1019
|
+
if (if RDL::Util.has_singleton_marker(ancestor_name) then ancestor.singleton_methods(false).member?(name) else ancestor.instance_methods(false).member?(name) end)
|
1020
|
+
klass = RDL::Util.remove_singleton_marker klass if RDL::Util.has_singleton_marker klass
|
1016
1021
|
error :missing_ancestor_type, [ancestor_name, klass, name], e
|
1017
1022
|
end
|
1018
1023
|
}
|
data/lib/rdl/wrap.rb
CHANGED
@@ -8,7 +8,7 @@ class RDL::Wrap
|
|
8
8
|
meth = meth.to_sym
|
9
9
|
while $__rdl_aliases[klass] && $__rdl_aliases[klass][meth]
|
10
10
|
if $__rdl_info.has_any?(klass, meth, [:pre, :post, :type])
|
11
|
-
raise RuntimeError, "Alias #{klass
|
11
|
+
raise RuntimeError, "Alias #{RDL::Util.pp_klass_method(klass, meth)} has contracts. Contracts are only allowed on methods, not aliases."
|
12
12
|
end
|
13
13
|
meth = $__rdl_aliases[klass][meth]
|
14
14
|
end
|
@@ -30,9 +30,8 @@ class RDL::Wrap
|
|
30
30
|
klass_str = klass_str.to_s
|
31
31
|
klass = RDL::Util.to_class klass_str
|
32
32
|
return if wrapped? klass, meth
|
33
|
-
$__rdl_info.set(klass_str, meth, :source_location, klass.instance_method(meth).source_location) # get locs for nowrap meths!
|
34
33
|
return if RDL::Config.instance.nowrap.member? klass
|
35
|
-
raise ArgumentError, "Attempt to wrap #{klass
|
34
|
+
raise ArgumentError, "Attempt to wrap #{RDL::Util.pp_klass_method(klass, meth)}" if klass.to_s =~ /^RDL::/
|
36
35
|
meth_old = wrapped_name(klass, meth) # meth_old is a symbol
|
37
36
|
# return if (klass.method_defined? meth_old) # now checked above by wrapped? call
|
38
37
|
is_singleton_method = RDL::Util.has_singleton_marker(klass_str)
|
@@ -55,7 +54,7 @@ class RDL::Wrap
|
|
55
54
|
#{if not(is_singleton_method) then "inst[:self] = RDL::Type::NominalType.new(self.class)" end}
|
56
55
|
# puts "Intercepted #{full_method_name}(\#{args.join(", ")}) { \#{blk} }, inst = \#{inst.inspect}"
|
57
56
|
meth = RDL::Wrap.resolve_alias(klass, #{meth.inspect})
|
58
|
-
RDL::Typecheck.typecheck(klass, meth) if $__rdl_info.get(klass, meth, :typecheck)
|
57
|
+
RDL::Typecheck.typecheck(klass, meth) if $__rdl_info.get(klass, meth, :typecheck) == :call
|
59
58
|
pres = $__rdl_info.get(klass, meth, :pre)
|
60
59
|
RDL::Contract::AndContract.check_array(pres, self, *args, &blk) if pres
|
61
60
|
types = $__rdl_info.get(klass, meth, :type)
|
@@ -176,6 +175,53 @@ RUBY
|
|
176
175
|
return $__rdl_parser.scan_str type
|
177
176
|
end
|
178
177
|
end
|
178
|
+
|
179
|
+
# called by Object#method_added (sing=false) and Object#singleton_method_added (sing=true)
|
180
|
+
def self.do_method_added(the_self, sing, klass, meth)
|
181
|
+
# Apply any deferred contracts and reset list
|
182
|
+
if sing
|
183
|
+
loc = the_self.singleton_method(meth).source_location
|
184
|
+
else
|
185
|
+
loc = the_self.instance_method(meth).source_location
|
186
|
+
end
|
187
|
+
|
188
|
+
if $__rdl_deferred.size > 0
|
189
|
+
$__rdl_info.set(klass, meth, :source_location, loc)
|
190
|
+
a = $__rdl_deferred
|
191
|
+
$__rdl_deferred = [] # Reset before doing more work to avoid infinite recursion
|
192
|
+
a.each { |prev_klass, kind, contract, h|
|
193
|
+
if RDL::Util.has_singleton_marker(klass)
|
194
|
+
tmp_klass = RDL::Util.remove_singleton_marker(klass)
|
195
|
+
else
|
196
|
+
tmp_klass = klass
|
197
|
+
end
|
198
|
+
raise RuntimeError, "Deferred contract from class #{prev_klass} being applied in class #{tmp_klass}" if prev_klass != tmp_klass
|
199
|
+
$__rdl_info.add(klass, meth, kind, contract)
|
200
|
+
RDL::Wrap.wrap(klass, meth) if h[:wrap]
|
201
|
+
unless $__rdl_info.set(klass, meth, :typecheck, h[:typecheck])
|
202
|
+
raise RuntimeError, "Inconsistent typecheck flag on #{RDL::Util.pp_klass_method(klass, meth)}"
|
203
|
+
end
|
204
|
+
RDL::Typecheck.typecheck(klass, meth) if h[:typecheck] == :now
|
205
|
+
if (h[:typecheck] && h[:typecheck] != :call)
|
206
|
+
$__rdl_to_typecheck[h[:typecheck]] = Set.new unless $__rdl_to_typecheck[h[:typecheck]]
|
207
|
+
$__rdl_to_typecheck[h[:typecheck]].add([klass, meth])
|
208
|
+
end
|
209
|
+
}
|
210
|
+
end
|
211
|
+
|
212
|
+
# Wrap method if there was a prior contract for it.
|
213
|
+
if $__rdl_to_wrap.member? [klass, meth]
|
214
|
+
$__rdl_to_wrap.delete [klass, meth]
|
215
|
+
RDL::Wrap.wrap(klass, meth)
|
216
|
+
$__rdl_info.set(klass, meth, :source_location, loc)
|
217
|
+
end
|
218
|
+
|
219
|
+
# Type check method if requested; must typecheck before wrap
|
220
|
+
if $__rdl_to_typecheck[:now].member? [klass, meth]
|
221
|
+
$__rdl_to_typecheck[:now].delete [klass, meth]
|
222
|
+
RDL::Typecheck.typecheck(klass, meth)
|
223
|
+
end
|
224
|
+
end
|
179
225
|
end
|
180
226
|
|
181
227
|
class Object
|
@@ -229,17 +275,20 @@ class Object
|
|
229
275
|
}
|
230
276
|
end
|
231
277
|
|
232
|
-
# [+klass+] may be Class, Symbol, or String
|
233
|
-
# [+method+] may be Symbol or String
|
234
|
-
# [+type+] may be Type or String
|
235
|
-
# [+wrap+] indicates whether the type should be enforced (true) or just recorded (false)
|
236
|
-
# [+typecheck+] indicates
|
278
|
+
# [+ klass +] may be Class, Symbol, or String
|
279
|
+
# [+ method +] may be Symbol or String
|
280
|
+
# [+ type +] may be Type or String
|
281
|
+
# [+ wrap +] indicates whether the type should be enforced (true) or just recorded (false)
|
282
|
+
# [+ typecheck +] indicates a method that should be statically type checked, as follows
|
283
|
+
# if :call, indicates method should be typechecked when called
|
284
|
+
# if :now, indicates method should be typechecked immediately
|
285
|
+
# if other-symbol, indicates method should be typechecked when rdl_do_typecheck(other-symbol) is called
|
237
286
|
#
|
238
287
|
# Set a method's type. Possible invocations:
|
239
288
|
# type(klass, meth, type)
|
240
289
|
# type(meth, type)
|
241
290
|
# type(type)
|
242
|
-
def type(*args, wrap: true, typecheck: false,
|
291
|
+
def type(*args, wrap: true, typecheck: false, &blk)
|
243
292
|
$__rdl_contract_switch.off {
|
244
293
|
klass, meth, type = begin
|
245
294
|
RDL::Wrap.process_type_args(self, *args, &blk)
|
@@ -260,71 +309,78 @@ class Object
|
|
260
309
|
# end
|
261
310
|
$__rdl_info.add(klass, meth, :type, type)
|
262
311
|
unless $__rdl_info.set(klass, meth, :typecheck, typecheck)
|
263
|
-
raise RuntimeError, "Inconsistent typecheck flag on #{klass
|
312
|
+
raise RuntimeError, "Inconsistent typecheck flag on #{RDL::Util.pp_klass_method(klass, meth)}"
|
264
313
|
end
|
265
314
|
if wrap
|
266
315
|
if RDL::Util.method_defined?(klass, meth) || meth == :initialize
|
267
|
-
|
316
|
+
$__rdl_info.set(klass, meth, :source_location, RDL::Util.to_class(klass).instance_method(meth).source_location)
|
317
|
+
RDL::Typecheck.typecheck(klass, meth) if typecheck == :now
|
268
318
|
RDL::Wrap.wrap(klass, meth)
|
269
319
|
else
|
270
320
|
$__rdl_to_wrap << [klass, meth]
|
271
|
-
|
321
|
+
if (typecheck && typecheck != :call)
|
322
|
+
$__rdl_to_typecheck[typecheck] = Set.new unless $__rdl_to_typecheck[typecheck]
|
323
|
+
$__rdl_to_typecheck[typecheck].add([klass, meth])
|
324
|
+
end
|
272
325
|
end
|
273
326
|
end
|
274
327
|
else
|
275
328
|
$__rdl_deferred << [klass, :type, type, {wrap: wrap,
|
276
|
-
typecheck: typecheck
|
277
|
-
typecheck_now: typecheck_now}]
|
329
|
+
typecheck: typecheck}]
|
278
330
|
end
|
279
331
|
}
|
280
332
|
end
|
281
333
|
|
334
|
+
# [+ klass +] is the class containing the variable; self if omitted; ignored for local and global variables
|
335
|
+
# [+ var +] is a symbol or string containing the name of the variable
|
336
|
+
# [+ typ +] is a string containing the type
|
282
337
|
def var_type(klass=self, var, typ)
|
283
338
|
raise RuntimeError, "Variable cannot begin with capital" if var.to_s =~ /^[A-Z]/
|
284
339
|
return if var.to_s =~ /^[a-z]/ # local variables handled specially, inside type checker
|
285
|
-
raise
|
340
|
+
raise RuntimeError, "Global variables can't be typed in a class" unless klass = self
|
286
341
|
klass = RDL::Util::GLOBAL_NAME if var.to_s =~ /^\$/
|
287
342
|
unless $__rdl_info.set(klass, var, :type, $__rdl_parser.scan_str("#T #{typ}"))
|
288
343
|
raise RuntimeError, "Type already declared for #{var}"
|
289
344
|
end
|
290
345
|
end
|
291
346
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
347
|
+
# In the following three methods
|
348
|
+
# [+ args +] is a sequence of symbol, typ. attr_reader is called for each symbol,
|
349
|
+
# and var_type is called to assign the immediately following type to the
|
350
|
+
# attribute named after that symbol.
|
351
|
+
def attr_accessor_type(*args)
|
352
|
+
args.each_slice(2) { |name, typ|
|
353
|
+
attr_accessor name
|
354
|
+
var_type ("@" + name.to_s), typ
|
355
|
+
type name, "() -> #{typ}"
|
356
|
+
type name.to_s + "=", "(#{typ}) -> #{typ}"
|
357
|
+
}
|
358
|
+
end
|
296
359
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
RDL::Wrap.wrap(klass, meth) if h[:wrap]
|
305
|
-
RDL::Typecheck.typecheck(klass, meth) if h[:typecheck_now]
|
306
|
-
unless $__rdl_info.set(klass, meth, :typecheck, h[:typecheck])
|
307
|
-
raise RuntimeError, "Inconsistent typecheck flag on #{klass}##{meth}"
|
308
|
-
end
|
360
|
+
def attr_reader_type(*args)
|
361
|
+
args.each_slice(2) { |name, typ|
|
362
|
+
attr_reader name
|
363
|
+
var_type ("@" + name.to_s), typ
|
364
|
+
type name, "() -> #{typ}"
|
365
|
+
}
|
366
|
+
end
|
309
367
|
|
310
|
-
|
311
|
-
# if (kind == :type) && (meth.to_s[-1] == "?") && (contract.ret != $__rdl_type_bool)
|
312
|
-
# warn "#{RDL::Util.pp_klass_method(klass, meth)}: methods that end in ? should have return type %bool"
|
313
|
-
# end
|
314
|
-
}
|
315
|
-
end
|
368
|
+
alias_method :attr_type, :attr_reader_type
|
316
369
|
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
370
|
+
def attr_writer_type(*args)
|
371
|
+
args.each_slice(2) { |name, typ|
|
372
|
+
attr_writer name
|
373
|
+
var_type ("@" + name.to_s), typ
|
374
|
+
type name.to_s + "=", "(#{typ}) -> #{typ}"
|
375
|
+
}
|
376
|
+
end
|
322
377
|
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
378
|
+
|
379
|
+
def self.method_added(meth)
|
380
|
+
$__rdl_contract_switch.off {
|
381
|
+
klass = self.to_s
|
382
|
+
klass = "Object" if (klass.is_a? Object) && (klass.to_s == "main")
|
383
|
+
RDL::Wrap.do_method_added(self, false, klass, meth)
|
328
384
|
}
|
329
385
|
end
|
330
386
|
|
@@ -333,33 +389,7 @@ class Object
|
|
333
389
|
klass = self.to_s
|
334
390
|
klass = "Object" if (klass.is_a? Object) && (klass.to_s == "main")
|
335
391
|
sklass = RDL::Util.add_singleton_marker(klass)
|
336
|
-
|
337
|
-
# Apply any deferred contracts and reset list
|
338
|
-
if $__rdl_deferred.size > 0
|
339
|
-
a = $__rdl_deferred
|
340
|
-
$__rdl_deferred = [] # Reset before doing more work to avoid infinite recursion
|
341
|
-
a.each { |prev_klass, kind, contract, h|
|
342
|
-
raise RuntimeError, "Deferred contract from class #{prev_klass} being applied in class #{klass}" if prev_klass != klass
|
343
|
-
$__rdl_info.add(sklass, meth, kind, contract)
|
344
|
-
RDL::Wrap.wrap(sklass, meth) if h[:wrap]
|
345
|
-
RDL::Typecheck.typecheck(sklass, meth) if h[:typecheck_now]
|
346
|
-
unless $__rdl_info.set(klass, meth, :typecheck, h[:typecheck])
|
347
|
-
raise RuntimeError, "Inconsistent typecheck flag on #{klass}##{meth}"
|
348
|
-
end
|
349
|
-
}
|
350
|
-
end
|
351
|
-
|
352
|
-
# Wrap method if there was a prior contract for it.
|
353
|
-
if $__rdl_to_wrap.member? [sklass, meth]
|
354
|
-
$__rdl_to_wrap.delete [sklass, meth]
|
355
|
-
RDL::Wrap.wrap(sklass, meth)
|
356
|
-
end
|
357
|
-
|
358
|
-
# Type check method if requested
|
359
|
-
if $__rdl_to_typecheck_now.member? [sklass, meth]
|
360
|
-
$__rdl_to_typecheck_now.delete [sklass, meth]
|
361
|
-
RDL::Typecheck.typecheck(sklass, meth)
|
362
|
-
end
|
392
|
+
RDL::Wrap.do_method_added(self, true, sklass, meth)
|
363
393
|
}
|
364
394
|
end
|
365
395
|
|
@@ -498,5 +528,12 @@ class Object
|
|
498
528
|
}
|
499
529
|
end
|
500
530
|
|
531
|
+
# Type check all methods that had annotation `typecheck: sym' at type call
|
532
|
+
def rdl_do_typecheck(sym)
|
533
|
+
$__rdl_to_typecheck[sym].each { |klass, meth|
|
534
|
+
RDL::Typecheck.typecheck(klass, meth)
|
535
|
+
}
|
536
|
+
$__rdl_to_typecheck[sym] = Array.new
|
537
|
+
end
|
501
538
|
|
502
539
|
end
|
data/rdl.gemspec
CHANGED
@@ -4,8 +4,8 @@
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = 'rdl'
|
7
|
-
s.version = '2.0.0.
|
8
|
-
s.date = '2016-07-
|
7
|
+
s.version = '2.0.0.rc2'
|
8
|
+
s.date = '2016-07-19'
|
9
9
|
s.summary = 'Ruby type and contract system'
|
10
10
|
s.description = <<-EOF
|
11
11
|
RDL is a gem that adds types and contracts to Ruby. RDL includes extensive
|
data/test/test_typecheck.rb
CHANGED
@@ -41,54 +41,68 @@ class TestTypecheck < Minitest::Test
|
|
41
41
|
|
42
42
|
def test_def
|
43
43
|
self.class.class_eval {
|
44
|
-
type "(Fixnum) -> Fixnum",
|
44
|
+
type "(Fixnum) -> Fixnum", typecheck: :now
|
45
45
|
def def_ff(x) x; end
|
46
46
|
}
|
47
47
|
|
48
48
|
assert_raises(RDL::Typecheck::StaticTypeError) {
|
49
49
|
self.class.class_eval {
|
50
|
-
type "(Fixnum) -> Fixnum",
|
50
|
+
type "(Fixnum) -> Fixnum", typecheck: :now
|
51
51
|
def def_fs(x) "42"; end
|
52
52
|
}
|
53
53
|
}
|
54
54
|
|
55
55
|
self.class.class_eval {
|
56
|
-
type "(Fixnum) -> Fixnum",
|
56
|
+
type "(Fixnum) -> Fixnum", typecheck: :now
|
57
57
|
def def_ff2(x) x; end
|
58
58
|
}
|
59
59
|
assert_equal 42, def_ff2(42)
|
60
60
|
|
61
61
|
self.class.class_eval {
|
62
|
-
type "(Fixnum) -> Fixnum", typecheck:
|
62
|
+
type "(Fixnum) -> Fixnum", typecheck: :call
|
63
63
|
def def_fs2(x) "42"; end
|
64
64
|
}
|
65
65
|
assert_raises(RDL::Typecheck::StaticTypeError) { def_fs2(42) }
|
66
66
|
|
67
67
|
assert_raises(RDL::Typecheck::StaticTypeError) {
|
68
68
|
self.class.class_eval {
|
69
|
-
type "(Fixnum) -> Fixnum",
|
69
|
+
type "(Fixnum) -> Fixnum", typecheck: :now
|
70
70
|
def def_ff3(x, y) 42; end
|
71
71
|
}
|
72
72
|
}
|
73
|
+
|
74
|
+
self.class.class_eval {
|
75
|
+
type "(Fixnum) -> Fixnum", typecheck: :later
|
76
|
+
def def_ff4(x, y) 42; end
|
77
|
+
}
|
78
|
+
|
79
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { rdl_do_typecheck :later }
|
73
80
|
end
|
74
81
|
|
75
82
|
def test_defs
|
76
83
|
self.class.class_eval {
|
77
|
-
type "(Fixnum) -> Class",
|
84
|
+
type "(Fixnum) -> Class", typecheck: :now
|
78
85
|
def self.defs_ff(x) self; end
|
79
86
|
}
|
80
87
|
|
81
88
|
self.class.class_eval {
|
82
|
-
type "() -> Class",
|
89
|
+
type "() -> Class", typecheck: :now
|
83
90
|
def self.defs_nn() defs_ff(42); end
|
84
91
|
}
|
85
92
|
|
86
93
|
assert_raises(RDL::Typecheck::StaticTypeError) {
|
87
94
|
self.class.class_eval {
|
88
|
-
type "() -> Class",
|
95
|
+
type "() -> Class", typecheck: :now
|
89
96
|
def self.defs_other() fdsakjfhds(42); end
|
90
97
|
}
|
91
98
|
}
|
99
|
+
|
100
|
+
self.class.class_eval {
|
101
|
+
type "(Fixnum) -> Fixnum", typecheck: :later
|
102
|
+
def self.defs_ff2(x, y) 42; end
|
103
|
+
}
|
104
|
+
|
105
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { rdl_do_typecheck :later }
|
92
106
|
end
|
93
107
|
|
94
108
|
def test_lits
|
@@ -107,7 +121,7 @@ class TestTypecheck < Minitest::Test
|
|
107
121
|
|
108
122
|
def test_empty
|
109
123
|
self.class.class_eval {
|
110
|
-
type "() -> nil",
|
124
|
+
type "() -> nil", typecheck: :now
|
111
125
|
def empty() end
|
112
126
|
}
|
113
127
|
end
|
@@ -115,10 +129,10 @@ class TestTypecheck < Minitest::Test
|
|
115
129
|
def test_dstr_xstr
|
116
130
|
# Hard to read if these are inside of strings, so leave like this
|
117
131
|
self.class.class_eval {
|
118
|
-
type "() -> String",
|
132
|
+
type "() -> String", typecheck: :now
|
119
133
|
def dstr() "Foo #{42} Bar #{43}"; end
|
120
134
|
|
121
|
-
type "() -> String",
|
135
|
+
type "() -> String", typecheck: :now
|
122
136
|
def xstr() `ls #{42}`; end
|
123
137
|
}
|
124
138
|
end
|
@@ -130,7 +144,7 @@ class TestTypecheck < Minitest::Test
|
|
130
144
|
def test_dsym
|
131
145
|
# Hard to read if these are inside of strings, so leave like this
|
132
146
|
self.class.class_eval {
|
133
|
-
type "() -> Symbol",
|
147
|
+
type "() -> Symbol", typecheck: :now
|
134
148
|
def dsym() :"foo#{42}"; end
|
135
149
|
}
|
136
150
|
end
|
@@ -140,7 +154,7 @@ class TestTypecheck < Minitest::Test
|
|
140
154
|
|
141
155
|
self.class.class_eval {
|
142
156
|
# Hard to read if these are inside of strings, so leave like this
|
143
|
-
type "() -> Regexp",
|
157
|
+
type "() -> Regexp", typecheck: :now
|
144
158
|
def regexp2() /foo#{42}bar#{"baz"}/i; end
|
145
159
|
}
|
146
160
|
end
|
@@ -166,18 +180,18 @@ class TestTypecheck < Minitest::Test
|
|
166
180
|
def test_self
|
167
181
|
# These need to be inside an actual class
|
168
182
|
self.class.class_eval {
|
169
|
-
type "() -> self",
|
183
|
+
type "() -> self", typecheck: :now
|
170
184
|
def self1() self; end
|
171
185
|
}
|
172
186
|
|
173
187
|
self.class.class_eval {
|
174
|
-
type "() -> self",
|
188
|
+
type "() -> self", typecheck: :now
|
175
189
|
def self2() TestTypecheck.new; end
|
176
190
|
}
|
177
191
|
|
178
192
|
assert_raises(RDL::Typecheck::StaticTypeError) {
|
179
193
|
self.class.class_eval {
|
180
|
-
type "() -> self",
|
194
|
+
type "() -> self", typecheck: :now
|
181
195
|
def self3() Object.new; end
|
182
196
|
}
|
183
197
|
}
|
@@ -199,19 +213,19 @@ class TestTypecheck < Minitest::Test
|
|
199
213
|
|
200
214
|
def test_lvar
|
201
215
|
self.class.class_eval {
|
202
|
-
type "(Fixnum, String) -> Fixnum",
|
216
|
+
type "(Fixnum, String) -> Fixnum", typecheck: :now
|
203
217
|
def lvar1(x, y) x; end
|
204
218
|
}
|
205
219
|
|
206
220
|
self.class.class_eval {
|
207
|
-
type "(Fixnum, String) -> String",
|
221
|
+
type "(Fixnum, String) -> String", typecheck: :now
|
208
222
|
def lvar2(x, y) y; end
|
209
223
|
}
|
210
224
|
|
211
225
|
assert_raises(RDL::Typecheck::StaticTypeError) {
|
212
226
|
# really a send
|
213
227
|
self.class.class_eval {
|
214
|
-
type "(Fixnum, String) -> String",
|
228
|
+
type "(Fixnum, String) -> String", typecheck: :now
|
215
229
|
def lvar3(x, y) z; end
|
216
230
|
}
|
217
231
|
}
|
@@ -235,12 +249,12 @@ class TestTypecheck < Minitest::Test
|
|
235
249
|
assert_equal $__rdl_fixnum_type, do_tc("var_type :x, 'Fixnum'; x = 3; x", env: @env)
|
236
250
|
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("var_type :x, 'Fixnum'; x = 'three'", env: @env) }
|
237
251
|
self.class.class_eval {
|
238
|
-
type "(Fixnum) -> nil",
|
252
|
+
type "(Fixnum) -> nil", typecheck: :now
|
239
253
|
def lvar_type_ff(x) x = 42; nil; end
|
240
254
|
}
|
241
255
|
assert_raises(RDL::Typecheck::StaticTypeError) {
|
242
256
|
self.class.class_eval {
|
243
|
-
type "(Fixnum) -> nil",
|
257
|
+
type "(Fixnum) -> nil", typecheck: :now
|
244
258
|
def lvar_type_ff2(x) x = "forty-two"; nil; end
|
245
259
|
}
|
246
260
|
}
|
@@ -508,7 +522,7 @@ class TestTypecheck < Minitest::Test
|
|
508
522
|
|
509
523
|
def test_yield
|
510
524
|
self.class.class_eval {
|
511
|
-
type "(Fixnum) { (Fixnum) -> Fixnum } -> Fixnum",
|
525
|
+
type "(Fixnum) { (Fixnum) -> Fixnum } -> Fixnum", typecheck: :now
|
512
526
|
def _yield1(x)
|
513
527
|
yield x
|
514
528
|
end
|
@@ -516,7 +530,7 @@ class TestTypecheck < Minitest::Test
|
|
516
530
|
|
517
531
|
assert_raises(RDL::Typecheck::StaticTypeError) {
|
518
532
|
self.class.class_eval {
|
519
|
-
type "(Fixnum) { (Fixnum) -> Fixnum } -> Fixnum",
|
533
|
+
type "(Fixnum) { (Fixnum) -> Fixnum } -> Fixnum", typecheck: :now
|
520
534
|
def _yield2(x)
|
521
535
|
yield 'forty-two'
|
522
536
|
end
|
@@ -525,7 +539,7 @@ class TestTypecheck < Minitest::Test
|
|
525
539
|
|
526
540
|
assert_raises(RDL::Typecheck::StaticTypeError) {
|
527
541
|
self.class.class_eval {
|
528
|
-
type "(Fixnum) { (Fixnum) -> String } -> Fixnum",
|
542
|
+
type "(Fixnum) { (Fixnum) -> String } -> Fixnum", typecheck: :now
|
529
543
|
def _yield3(x)
|
530
544
|
yield 42
|
531
545
|
end
|
@@ -534,7 +548,7 @@ class TestTypecheck < Minitest::Test
|
|
534
548
|
|
535
549
|
assert_raises(RDL::Typecheck::StaticTypeError) {
|
536
550
|
self.class.class_eval {
|
537
|
-
type "(Fixnum) -> Fixnum",
|
551
|
+
type "(Fixnum) -> Fixnum", typecheck: :now
|
538
552
|
def _yield4(x)
|
539
553
|
yield 42
|
540
554
|
end
|
@@ -543,7 +557,7 @@ class TestTypecheck < Minitest::Test
|
|
543
557
|
|
544
558
|
assert_raises(RDL::Typecheck::StaticTypeError) {
|
545
559
|
self.class.class_eval {
|
546
|
-
type "(Fixnum) { (Fixnum) { (Fixnum) -> Fixnum } -> Fixnum } -> Fixnum",
|
560
|
+
type "(Fixnum) { (Fixnum) { (Fixnum) -> Fixnum } -> Fixnum } -> Fixnum", typecheck: :now
|
547
561
|
def _yield5(x)
|
548
562
|
yield 42
|
549
563
|
end
|
@@ -552,14 +566,14 @@ class TestTypecheck < Minitest::Test
|
|
552
566
|
end
|
553
567
|
|
554
568
|
# class Sup1
|
555
|
-
# type '(Fixnum) -> Fixnum', typecheck:
|
569
|
+
# type '(Fixnum) -> Fixnum', typecheck: :call
|
556
570
|
# def foo(y)
|
557
571
|
# return y
|
558
572
|
# end
|
559
573
|
# end
|
560
574
|
#
|
561
575
|
# class Sup2 < Sup1
|
562
|
-
# type '(Fixnum) -> Fixnum', typecheck:
|
576
|
+
# type '(Fixnum) -> Fixnum', typecheck: :call
|
563
577
|
# def foo(x)
|
564
578
|
# super(x+1)
|
565
579
|
# end
|
@@ -693,7 +707,7 @@ class TestTypecheck < Minitest::Test
|
|
693
707
|
|
694
708
|
def test_return
|
695
709
|
assert self.class.class_eval {
|
696
|
-
type "(Fixnum) -> Fixnum",
|
710
|
+
type "(Fixnum) -> Fixnum", typecheck: :now
|
697
711
|
def return_ff(x)
|
698
712
|
return 42
|
699
713
|
end
|
@@ -701,7 +715,7 @@ class TestTypecheck < Minitest::Test
|
|
701
715
|
|
702
716
|
assert_raises(RDL::Typecheck::StaticTypeError) {
|
703
717
|
self.class.class_eval {
|
704
|
-
type "(Fixnum) -> Fixnum",
|
718
|
+
type "(Fixnum) -> Fixnum", typecheck: :now
|
705
719
|
def return_ff2(x)
|
706
720
|
return "forty-two"
|
707
721
|
end
|
@@ -890,4 +904,30 @@ class TestTypecheck < Minitest::Test
|
|
890
904
|
assert_equal tt("Hash<Symbol or String, Fixnum or String>"), do_tc("x = {'a' => 1, **_kwsplathsf, b: 'two'}", env: @env)
|
891
905
|
end
|
892
906
|
|
907
|
+
def test_attr_etc
|
908
|
+
self.class.class_eval {
|
909
|
+
attr_reader_type :f_attr_reader, "Fixnum", :f_attr_reader2, "String"
|
910
|
+
attr_writer_type :f_attr_writer, "Fixnum"
|
911
|
+
attr_type :f_attr, "Fixnum"
|
912
|
+
attr_accessor_type :f_attr_accessor, "Fixnum"
|
913
|
+
}
|
914
|
+
assert_equal $__rdl_fixnum_type, do_tc("@f_attr_reader", env: @env)
|
915
|
+
assert_equal $__rdl_fixnum_type, do_tc("TestTypecheck.new.f_attr_reader", env: @env)
|
916
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("TestTypecheck.new.f_attr_reader = 4", env: @env) }
|
917
|
+
assert_equal $__rdl_string_type, do_tc("@f_attr_reader2", env: @env)
|
918
|
+
assert_equal $__rdl_string_type, do_tc("TestTypecheck.new.f_attr_reader2", env: @env)
|
919
|
+
|
920
|
+
assert_equal $__rdl_fixnum_type, do_tc("@f_attr", env: @env) # same as attr_reader
|
921
|
+
assert_equal $__rdl_fixnum_type, do_tc("TestTypecheck.new.f_attr", env: @env)
|
922
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("TestTypecheck.new.f_attr = 42", env: @env) }
|
923
|
+
|
924
|
+
assert_equal @t3, do_tc("@f_attr_writer = 3", env: @env)
|
925
|
+
assert_equal $__rdl_fixnum_type, do_tc("TestTypecheck.new.f_attr_writer = 3", env: @env)
|
926
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("TestTypecheck.new.f_attr_writer", env: @env) }
|
927
|
+
|
928
|
+
assert_equal $__rdl_fixnum_type, do_tc("@f_attr_accessor", env: @env)
|
929
|
+
assert_equal $__rdl_fixnum_type, do_tc("TestTypecheck.new.f_attr_accessor", env: @env)
|
930
|
+
assert_equal $__rdl_fixnum_type, do_tc("TestTypecheck.new.f_attr_accessor = 42", env: @env)
|
931
|
+
end
|
932
|
+
|
893
933
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
class Module
|
2
|
+
rdl_nowrap
|
3
|
+
|
4
|
+
type 'self.constants', '() -> Array<Fixnum>' # also constants(inherited), but undocumented
|
5
|
+
type 'self.nesting', '() -> Array<Module>'
|
6
|
+
type 'self.new', '() -> Module'
|
7
|
+
type 'self.new', '() { (Module) -> %any } -> Module'
|
8
|
+
|
9
|
+
type :<, '(Module other) -> %bool or nil'
|
10
|
+
type :<=, '(Module other) -> %bool or nil'
|
11
|
+
type :<=>, '(Module other) -> -1 or 0 or 1 or nil'
|
12
|
+
type :==, '(%any other) -> %bool'
|
13
|
+
type :equal, '(%any other) -> %bool'
|
14
|
+
type :eql, '(%any other) -> %bool'
|
15
|
+
type :===, '(%any other) -> %bool'
|
16
|
+
type :>, '(Module other) -> %bool or nil'
|
17
|
+
type :>=, '(Module other) -> %bool or nil'
|
18
|
+
type :ancestors, '() -> Array<Module>'
|
19
|
+
type :autoload, '(Symbol module, String filename) -> nil'
|
20
|
+
type :autoload?, '(Symbol name) -> String or nil'
|
21
|
+
type :class_eval, '(String, ?String filename, ?Fixnum lineno) -> %any'
|
22
|
+
type :class_exec, '(*%any args) { (*%any args) -> %any } -> %any'
|
23
|
+
type :class_variable_defined?, '(Symbol or String) -> %bool'
|
24
|
+
type :class_variable_get, '(Symbol or String) -> %any'
|
25
|
+
type :class_variable_set, '(Symbol or String, %any) -> %any'
|
26
|
+
type :class_variables, '(?%bool inherit) -> Array<Symbol>'
|
27
|
+
type :const_defined?, '(Symbol or String, ?%bool inherit) -> %bool'
|
28
|
+
type :const_get, '(Symbol or String, ?%bool inherit) -> %any'
|
29
|
+
type :const_missing, '(Symbol) -> %any'
|
30
|
+
type :const_set, '(Symbol or String, %any) -> %any'
|
31
|
+
type :constants, '(?%bool inherit) -> Array<Symbol>'
|
32
|
+
type :freeze, '() -> self'
|
33
|
+
type :include, '(*Module) -> self'
|
34
|
+
type :include?, '(Module) -> %bool'
|
35
|
+
type :included_modules, '() -> Array<Module>'
|
36
|
+
rdl_alias :inspect, :to_s
|
37
|
+
type :instance_method, '(Symbol) -> UnboundMethod'
|
38
|
+
type :instance_methods, '(?%bool include_super) -> Array<Symbol>'
|
39
|
+
type :method_defined?, '(Symbol or String) -> %bool'
|
40
|
+
type :module_eval, '(String, ?String filename, ?Fixnum lineno) -> %any' # matches rdoc example but not type
|
41
|
+
type :module_exec, '(*%any args) { (*%any args) -> %any } -> %any'
|
42
|
+
type :name, '() -> String'
|
43
|
+
type :prepend, '(*Module) -> self'
|
44
|
+
type :private_class_method, '(*(Symbol or String)) -> self'
|
45
|
+
type :private_constant, '(*Symbol) -> self'
|
46
|
+
type :private_instance_methods, '(?%bool include_super) -> Array<Symbol>'
|
47
|
+
type :private_method_defined?, '(Symbol or String) -> %bool'
|
48
|
+
type :protected_instance_methods, '(?%bool include_super) -> Array<Symbol>'
|
49
|
+
type :protected_method_defined?, '(Symbol or String) -> %bool'
|
50
|
+
type :public_class_method, '(*(Symbol or String)) -> self'
|
51
|
+
type :public_constant, '(*Symbol) -> self'
|
52
|
+
type :public_instance_method, '(Symbol) -> UnboundMethod'
|
53
|
+
type :public_instance_methods, '(?%bool include_super) -> Array<Symbol>'
|
54
|
+
type :public_method_defined?, '(Symbol or String) -> %bool'
|
55
|
+
type :remove_class_variable, '(Symbol) -> %any'
|
56
|
+
type :singleton_class?, '() -> %bool'
|
57
|
+
type :to_s, '() -> String'
|
58
|
+
# private methods below here
|
59
|
+
type :alias_method, '(Symbol new_name, Symbol old_name) -> self'
|
60
|
+
type :append_features, '(Module) -> self'
|
61
|
+
rdl_alias :attr, :attr_reader
|
62
|
+
type :attr_accessor, '(*(Symbol or String)) -> nil'
|
63
|
+
type :attr_reader, '(*(Symbol or String)) -> nil'
|
64
|
+
type :attr_writer, '(*(Symbol or String)) -> nil'
|
65
|
+
type :define_method, '(Symbol, Method) -> Symbol'
|
66
|
+
type :define_method, '(Symbol) { (*%any) -> %any } -> Symbol'
|
67
|
+
type :extend_object, '(%any) -> %any'
|
68
|
+
type :extended, '(Module othermod) -> %any'
|
69
|
+
type :included, '(Module othermod) -> %any'
|
70
|
+
type :method_added, '(Symbol method_name) -> %any'
|
71
|
+
type :method_removed, '(Symbol method_name) -> %any'
|
72
|
+
type :module_function, '(*(Symbol or String)) -> self'
|
73
|
+
type :prepend_features, '(Module) -> self'
|
74
|
+
type :prepended, '(Module othermod) -> %any'
|
75
|
+
type :private, '(*(Symbol or String)) -> self'
|
76
|
+
type :protected, '(*(Symbol or String)) -> self'
|
77
|
+
type :public, '(*(Symbol or String)) -> self'
|
78
|
+
type :refine, '(Class) { (%any) -> %any } -> self' # ??
|
79
|
+
type :remove_const, '(Symbol) -> %any'
|
80
|
+
type :remove_method, '(Symbol or String) -> self'
|
81
|
+
type :undef_method, '(Symbol or String) -> self'
|
82
|
+
type :using, '(Module) -> self'
|
83
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rdl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.
|
4
|
+
version: 2.0.0.rc2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeffrey S. Foster
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2016-07-
|
15
|
+
date: 2016-07-19 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: parser
|
@@ -206,6 +206,7 @@ files:
|
|
206
206
|
- types/ruby-2.x/marshal.rb
|
207
207
|
- types/ruby-2.x/matchdata.rb
|
208
208
|
- types/ruby-2.x/math.rb
|
209
|
+
- types/ruby-2.x/module.rb
|
209
210
|
- types/ruby-2.x/nil.rb
|
210
211
|
- types/ruby-2.x/numeric.rb
|
211
212
|
- types/ruby-2.x/object.rb
|