rbs 0.5.0 → 0.9.1
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/CHANGELOG.md +33 -0
- data/Gemfile +2 -0
- data/Rakefile +2 -3
- data/docs/stdlib.md +0 -2
- data/docs/syntax.md +6 -3
- data/goodcheck.yml +65 -0
- data/lib/rbs.rb +1 -0
- data/lib/rbs/ast/comment.rb +6 -0
- data/lib/rbs/ast/declarations.rb +44 -6
- data/lib/rbs/cli.rb +21 -3
- data/lib/rbs/constant_table.rb +1 -1
- data/lib/rbs/definition_builder.rb +290 -124
- data/lib/rbs/environment.rb +50 -37
- data/lib/rbs/errors.rb +68 -25
- data/lib/rbs/factory.rb +14 -0
- data/lib/rbs/location.rb +15 -0
- data/lib/rbs/parser.y +89 -28
- data/lib/rbs/prototype/rb.rb +2 -2
- data/lib/rbs/prototype/rbi.rb +1 -1
- data/lib/rbs/prototype/runtime.rb +1 -1
- data/lib/rbs/substitution.rb +6 -2
- data/lib/rbs/test.rb +82 -3
- data/lib/rbs/test/errors.rb +5 -1
- data/lib/rbs/test/hook.rb +133 -259
- data/lib/rbs/test/observer.rb +17 -0
- data/lib/rbs/test/setup.rb +37 -20
- data/lib/rbs/test/setup_helper.rb +29 -0
- data/lib/rbs/test/spy.rb +0 -321
- data/lib/rbs/test/tester.rb +118 -0
- data/lib/rbs/test/type_check.rb +42 -5
- data/lib/rbs/validator.rb +4 -0
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/writer.rb +2 -2
- data/schema/decls.json +21 -10
- data/stdlib/builtin/enumerable.rbs +2 -2
- data/stdlib/builtin/proc.rbs +1 -2
- data/stdlib/json/json.rbs +6 -0
- data/stdlib/logger/formatter.rbs +23 -0
- data/stdlib/logger/log_device.rbs +39 -0
- data/stdlib/logger/logger.rbs +507 -0
- data/stdlib/logger/period.rbs +7 -0
- data/stdlib/logger/severity.rbs +8 -0
- data/stdlib/pty/pty.rbs +159 -0
- metadata +13 -3
- data/lib/rbs/test/test_helper.rb +0 -180
@@ -0,0 +1,17 @@
|
|
1
|
+
module RBS
|
2
|
+
module Test
|
3
|
+
module Observer
|
4
|
+
@@observers = {}
|
5
|
+
|
6
|
+
class <<self
|
7
|
+
def notify(key, *args)
|
8
|
+
@@observers[key]&.call(*args)
|
9
|
+
end
|
10
|
+
|
11
|
+
def register(key, object = nil, &block)
|
12
|
+
@@observers[key] = object || block
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/rbs/test/setup.rb
CHANGED
@@ -1,60 +1,77 @@
|
|
1
1
|
require "rbs"
|
2
2
|
require "rbs/test"
|
3
|
-
|
4
3
|
require "optparse"
|
5
4
|
require "shellwords"
|
6
5
|
|
6
|
+
include RBS::Test::SetupHelper
|
7
|
+
|
7
8
|
logger = Logger.new(STDERR)
|
8
9
|
|
9
10
|
begin
|
10
11
|
opts = Shellwords.shellsplit(ENV["RBS_TEST_OPT"] || "-I sig")
|
11
|
-
filter = ENV.fetch(
|
12
|
-
skips = (ENV[
|
13
|
-
|
14
|
-
|
15
|
-
rescue
|
12
|
+
filter = ENV.fetch('RBS_TEST_TARGET', "").split(',').map! { |e| e.strip }
|
13
|
+
skips = (ENV['RBS_TEST_SKIP'] || '').split(',').map! { |e| e.strip }
|
14
|
+
RBS.logger_level = (ENV["RBS_TEST_LOGLEVEL"] || "info")
|
15
|
+
sample_size = get_sample_size(ENV['RBS_TEST_SAMPLE_SIZE'] || '')
|
16
|
+
rescue InvalidSampleSizeError => exception
|
17
|
+
RBS.logger.error exception.message
|
18
|
+
exit 1
|
19
|
+
end
|
20
|
+
|
21
|
+
if filter.empty?
|
16
22
|
STDERR.puts "rbs/test/setup handles the following environment variables:"
|
17
23
|
STDERR.puts " [REQUIRED] RBS_TEST_TARGET: test target class name, `Foo::Bar,Foo::Baz` for each class or `Foo::*` for all classes under `Foo`"
|
18
24
|
STDERR.puts " [OPTIONAL] RBS_TEST_SKIP: skip testing classes"
|
19
25
|
STDERR.puts " [OPTIONAL] RBS_TEST_OPT: options for signatures (`-r` for libraries or `-I` for signatures)"
|
20
26
|
STDERR.puts " [OPTIONAL] RBS_TEST_LOGLEVEL: one of debug|info|warn|error|fatal (defaults to info)"
|
21
|
-
STDERR.puts " [OPTIONAL]
|
27
|
+
STDERR.puts " [OPTIONAL] RBS_TEST_SAMPLE_SIZE: sets the amount of values in a collection to be type-checked (Set to `ALL` to type check all the values)"
|
22
28
|
exit 1
|
23
29
|
end
|
24
30
|
|
25
|
-
hooks = []
|
26
|
-
|
27
|
-
env = RBS::Environment.new
|
28
|
-
|
29
31
|
loader = RBS::EnvironmentLoader.new
|
30
32
|
OptionParser.new do |opts|
|
31
33
|
opts.on("-r [LIB]") do |name| loader.add(library: name) end
|
32
34
|
opts.on("-I [DIR]") do |dir| loader.add(path: Pathname(dir)) end
|
33
35
|
end.parse!(opts)
|
34
|
-
loader.load(env: env)
|
35
36
|
|
36
|
-
env =
|
37
|
+
env = RBS::Environment.from_loader(loader).resolve_type_names
|
37
38
|
|
38
39
|
def match(filter, name)
|
39
40
|
if filter.end_with?("*")
|
40
|
-
|
41
|
+
size = filter.size
|
42
|
+
name.start_with?(filter[0, size - 1]) || name == filter[0, size-3]
|
41
43
|
else
|
42
44
|
filter == name
|
43
45
|
end
|
44
46
|
end
|
45
47
|
|
48
|
+
def to_absolute_typename(type_name)
|
49
|
+
RBS::Factory.new().type_name(type_name).absolute!
|
50
|
+
end
|
51
|
+
|
52
|
+
tester = RBS::Test::Tester.new(env: env)
|
53
|
+
|
54
|
+
module_name = Module.instance_method(:name)
|
55
|
+
|
46
56
|
TracePoint.trace :end do |tp|
|
47
|
-
class_name = tp.self.name
|
57
|
+
class_name = module_name.bind(tp.self).call&.yield_self {|name| to_absolute_typename name }
|
48
58
|
|
49
59
|
if class_name
|
50
|
-
if filter.any? {|f| match(f, class_name) } && skips.none? {|f| match(f, class_name) }
|
51
|
-
|
52
|
-
|
53
|
-
if env.class_decls.key?(type_name)
|
60
|
+
if filter.any? {|f| match(to_absolute_typename(f).to_s, class_name.to_s) } && skips.none? {|f| match(f, class_name.to_s) }
|
61
|
+
unless tester.targets.include?(tp.self)
|
62
|
+
if env.class_decls.key?(class_name)
|
54
63
|
logger.info "Setting up hooks for #{class_name}"
|
55
|
-
|
64
|
+
tester.install!(tp.self, sample_size: sample_size)
|
56
65
|
end
|
57
66
|
end
|
58
67
|
end
|
59
68
|
end
|
60
69
|
end
|
70
|
+
|
71
|
+
at_exit do
|
72
|
+
if $!.nil? || $!.is_a?(SystemExit) && $!.success?
|
73
|
+
if tester.targets.empty?
|
74
|
+
logger.warn "No type checker was installed!"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module RBS
|
2
|
+
module Test
|
3
|
+
module SetupHelper
|
4
|
+
class InvalidSampleSizeError < StandardError
|
5
|
+
attr_reader :string
|
6
|
+
|
7
|
+
def initialize(string)
|
8
|
+
@string = string
|
9
|
+
super("Sample size should be a positive integer: `#{string}`")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
DEFAULT_SAMPLE_SIZE = 100
|
14
|
+
|
15
|
+
def get_sample_size(string)
|
16
|
+
case string
|
17
|
+
when ""
|
18
|
+
DEFAULT_SAMPLE_SIZE
|
19
|
+
when 'ALL'
|
20
|
+
nil
|
21
|
+
else
|
22
|
+
int_size = string.to_i
|
23
|
+
raise InvalidSampleSizeError.new(string) unless int_size.positive?
|
24
|
+
int_size
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/rbs/test/spy.rb
CHANGED
@@ -1,325 +1,4 @@
|
|
1
1
|
module RBS
|
2
2
|
module Test
|
3
|
-
module Spy
|
4
|
-
def self.singleton_method(object, method_name)
|
5
|
-
spy = SingletonSpy.new(object: object, method_name: method_name)
|
6
|
-
|
7
|
-
if block_given?
|
8
|
-
begin
|
9
|
-
spy.setup
|
10
|
-
yield spy
|
11
|
-
ensure
|
12
|
-
spy.reset
|
13
|
-
end
|
14
|
-
else
|
15
|
-
spy
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.instance_method(mod, method_name)
|
20
|
-
spy = InstanceSpy.new(mod: mod, method_name: method_name)
|
21
|
-
|
22
|
-
if block_given?
|
23
|
-
begin
|
24
|
-
spy.setup
|
25
|
-
yield spy
|
26
|
-
ensure
|
27
|
-
spy.reset
|
28
|
-
end
|
29
|
-
else
|
30
|
-
spy
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.wrap(object, method_name)
|
35
|
-
spy = WrapSpy.new(object: object, method_name: method_name)
|
36
|
-
|
37
|
-
if block_given?
|
38
|
-
begin
|
39
|
-
yield spy, spy.wrapped_object
|
40
|
-
end
|
41
|
-
else
|
42
|
-
spy
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
class SingletonSpy
|
47
|
-
attr_accessor :callback
|
48
|
-
attr_reader :method_name
|
49
|
-
attr_reader :object
|
50
|
-
|
51
|
-
def initialize(object:, method_name:)
|
52
|
-
@object = object
|
53
|
-
@method_name = method_name
|
54
|
-
@callback = -> (_) { }
|
55
|
-
end
|
56
|
-
|
57
|
-
def setup
|
58
|
-
spy = self
|
59
|
-
|
60
|
-
object.singleton_class.class_eval do
|
61
|
-
remove_method spy.method_name
|
62
|
-
define_method spy.method_name, spy.spy()
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def spy()
|
67
|
-
spy = self
|
68
|
-
|
69
|
-
-> (*args, &block) do
|
70
|
-
return_value = nil
|
71
|
-
exception = nil
|
72
|
-
block_calls = []
|
73
|
-
|
74
|
-
spy_block = if block
|
75
|
-
Object.new.instance_eval do |fresh|
|
76
|
-
-> (*block_args) do
|
77
|
-
block_exn = nil
|
78
|
-
block_return = nil
|
79
|
-
|
80
|
-
begin
|
81
|
-
block_return = if self.equal?(fresh)
|
82
|
-
# no instance eval
|
83
|
-
block.call(*block_args)
|
84
|
-
else
|
85
|
-
self.instance_exec(*block_args, &block)
|
86
|
-
end
|
87
|
-
rescue Exception => exn
|
88
|
-
block_exn = exn
|
89
|
-
end
|
90
|
-
|
91
|
-
block_calls << ArgumentsReturn.new(
|
92
|
-
arguments: block_args,
|
93
|
-
return_value: block_return,
|
94
|
-
exception: block_exn
|
95
|
-
)
|
96
|
-
|
97
|
-
if block_exn
|
98
|
-
raise block_exn
|
99
|
-
else
|
100
|
-
block_return
|
101
|
-
end
|
102
|
-
end.ruby2_keywords
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
begin
|
107
|
-
return_value = super(*args, &spy_block)
|
108
|
-
rescue Exception => exn
|
109
|
-
exception = exn
|
110
|
-
end
|
111
|
-
|
112
|
-
trace = CallTrace.new(
|
113
|
-
method_name: spy.method_name,
|
114
|
-
method_call: ArgumentsReturn.new(
|
115
|
-
arguments: args,
|
116
|
-
return_value: return_value,
|
117
|
-
exception: exception,
|
118
|
-
),
|
119
|
-
block_calls: block_calls,
|
120
|
-
block_given: block != nil
|
121
|
-
)
|
122
|
-
|
123
|
-
spy.callback.call(trace)
|
124
|
-
|
125
|
-
if exception
|
126
|
-
raise exception
|
127
|
-
else
|
128
|
-
return_value
|
129
|
-
end
|
130
|
-
end.ruby2_keywords
|
131
|
-
end
|
132
|
-
|
133
|
-
def reset
|
134
|
-
if object.singleton_class.methods.include?(method_name)
|
135
|
-
object.singleton_class.remove_method method_name
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
class InstanceSpy
|
141
|
-
attr_accessor :callback
|
142
|
-
attr_reader :mod
|
143
|
-
attr_reader :method_name
|
144
|
-
attr_reader :original_method
|
145
|
-
|
146
|
-
def initialize(mod:, method_name:)
|
147
|
-
@mod = mod
|
148
|
-
@method_name = method_name
|
149
|
-
@original_method = mod.instance_method(method_name)
|
150
|
-
@callback = -> (_) { }
|
151
|
-
end
|
152
|
-
|
153
|
-
def setup
|
154
|
-
spy = self
|
155
|
-
|
156
|
-
mod.class_eval do
|
157
|
-
remove_method spy.method_name
|
158
|
-
define_method spy.method_name, spy.spy()
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
def reset
|
163
|
-
spy = self
|
164
|
-
|
165
|
-
mod.class_eval do
|
166
|
-
remove_method spy.method_name
|
167
|
-
define_method spy.method_name, spy.original_method
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
def spy
|
172
|
-
spy = self
|
173
|
-
|
174
|
-
-> (*args, &block) do
|
175
|
-
return_value = nil
|
176
|
-
exception = nil
|
177
|
-
block_calls = []
|
178
|
-
|
179
|
-
spy_block = if block
|
180
|
-
Object.new.instance_eval do |fresh|
|
181
|
-
-> (*block_args) do
|
182
|
-
block_exn = nil
|
183
|
-
block_return = nil
|
184
|
-
|
185
|
-
begin
|
186
|
-
block_return = if self.equal?(fresh)
|
187
|
-
# no instance eval
|
188
|
-
block.call(*block_args)
|
189
|
-
else
|
190
|
-
self.instance_exec(*block_args, &block)
|
191
|
-
end
|
192
|
-
rescue Exception => exn
|
193
|
-
block_exn = exn
|
194
|
-
end
|
195
|
-
|
196
|
-
block_calls << ArgumentsReturn.new(
|
197
|
-
arguments: block_args,
|
198
|
-
return_value: block_return,
|
199
|
-
exception: block_exn
|
200
|
-
)
|
201
|
-
|
202
|
-
if block_exn
|
203
|
-
raise block_exn
|
204
|
-
else
|
205
|
-
block_return
|
206
|
-
end
|
207
|
-
end.ruby2_keywords
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
begin
|
212
|
-
return_value = spy.original_method.bind_call(self, *args, &spy_block)
|
213
|
-
rescue Exception => exn
|
214
|
-
exception = exn
|
215
|
-
end
|
216
|
-
|
217
|
-
trace = CallTrace.new(
|
218
|
-
method_name: spy.method_name,
|
219
|
-
method_call: ArgumentsReturn.new(
|
220
|
-
arguments: args,
|
221
|
-
return_value: return_value,
|
222
|
-
exception: exception,
|
223
|
-
),
|
224
|
-
block_calls: block_calls,
|
225
|
-
block_given: block != nil
|
226
|
-
)
|
227
|
-
|
228
|
-
spy.callback.call(trace)
|
229
|
-
|
230
|
-
if exception
|
231
|
-
raise exception
|
232
|
-
else
|
233
|
-
return_value
|
234
|
-
end
|
235
|
-
end.ruby2_keywords
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
class WrapSpy
|
240
|
-
attr_accessor :callback
|
241
|
-
attr_reader :object
|
242
|
-
attr_reader :method_name
|
243
|
-
|
244
|
-
def initialize(object:, method_name:)
|
245
|
-
@callback = -> (_) { }
|
246
|
-
@object = object
|
247
|
-
@method_name = method_name
|
248
|
-
end
|
249
|
-
|
250
|
-
def wrapped_object
|
251
|
-
spy = self
|
252
|
-
|
253
|
-
Class.new(BasicObject) do
|
254
|
-
define_method(:method_missing) do |name, *args, &block|
|
255
|
-
spy.object.__send__(name, *args, &block)
|
256
|
-
end
|
257
|
-
|
258
|
-
define_method(spy.method_name, -> (*args, &block) {
|
259
|
-
return_value = nil
|
260
|
-
exception = nil
|
261
|
-
block_calls = []
|
262
|
-
|
263
|
-
spy_block = if block
|
264
|
-
Object.new.instance_eval do |fresh|
|
265
|
-
-> (*block_args) do
|
266
|
-
block_exn = nil
|
267
|
-
block_return = nil
|
268
|
-
|
269
|
-
begin
|
270
|
-
block_return = if self.equal?(fresh)
|
271
|
-
# no instance eval
|
272
|
-
block.call(*block_args)
|
273
|
-
else
|
274
|
-
self.instance_exec(*block_args, &block)
|
275
|
-
end
|
276
|
-
rescue Exception => exn
|
277
|
-
block_exn = exn
|
278
|
-
end
|
279
|
-
|
280
|
-
block_calls << ArgumentsReturn.new(
|
281
|
-
arguments: block_args,
|
282
|
-
return_value: block_return,
|
283
|
-
exception: block_exn
|
284
|
-
)
|
285
|
-
|
286
|
-
if block_exn
|
287
|
-
raise block_exn
|
288
|
-
else
|
289
|
-
block_return
|
290
|
-
end
|
291
|
-
end.ruby2_keywords
|
292
|
-
end
|
293
|
-
end
|
294
|
-
|
295
|
-
begin
|
296
|
-
return_value = spy.object.__send__(spy.method_name, *args, &spy_block)
|
297
|
-
rescue ::Exception => exn
|
298
|
-
exception = exn
|
299
|
-
end
|
300
|
-
|
301
|
-
trace = CallTrace.new(
|
302
|
-
method_name: spy.method_name,
|
303
|
-
method_call: ArgumentsReturn.new(
|
304
|
-
arguments: args,
|
305
|
-
return_value: return_value,
|
306
|
-
exception: exception,
|
307
|
-
),
|
308
|
-
block_calls: block_calls,
|
309
|
-
block_given: block != nil
|
310
|
-
)
|
311
|
-
|
312
|
-
spy.callback.call(trace)
|
313
|
-
|
314
|
-
if exception
|
315
|
-
spy.object.__send__(:raise, exception)
|
316
|
-
else
|
317
|
-
return_value
|
318
|
-
end
|
319
|
-
}.ruby2_keywords)
|
320
|
-
end.new()
|
321
|
-
end
|
322
|
-
end
|
323
|
-
end
|
324
3
|
end
|
325
4
|
end
|