rbs 3.3.2 → 3.4.0
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/.github/workflows/comments.yml +2 -5
- data/.github/workflows/ruby.yml +7 -8
- data/.github/workflows/typecheck.yml +37 -0
- data/CHANGELOG.md +65 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +11 -11
- data/README.md +1 -0
- data/Rakefile +2 -2
- data/Steepfile +2 -2
- data/core/array.rbs +19 -49
- data/core/basic_object.rbs +2 -2
- data/core/comparable.rbs +17 -8
- data/core/complex.rbs +82 -43
- data/core/data.rbs +2 -4
- data/core/dir.rbs +635 -295
- data/core/enumerable.rbs +11 -18
- data/core/enumerator.rbs +37 -31
- data/core/errors.rbs +4 -0
- data/core/false_class.rbs +34 -15
- data/core/fiber.rbs +23 -0
- data/core/file.rbs +329 -120
- data/core/float.rbs +17 -32
- data/core/gc.rbs +17 -11
- data/core/hash.rbs +22 -44
- data/core/integer.rbs +82 -113
- data/core/io/buffer.rbs +90 -47
- data/core/io.rbs +54 -121
- data/core/kernel.rbs +442 -489
- data/core/match_data.rbs +55 -56
- data/core/module.rbs +45 -1
- data/core/nil_class.rbs +98 -35
- data/core/numeric.rbs +22 -32
- data/core/object_space/weak_key_map.rbs +102 -0
- data/core/process.rbs +1242 -655
- data/core/ractor.rbs +139 -120
- data/core/range.rbs +100 -4
- data/core/rational.rbs +0 -4
- data/core/rbs/unnamed/argf.rbs +16 -8
- data/core/rbs/unnamed/env_class.rbs +0 -24
- data/core/refinement.rbs +8 -0
- data/core/regexp.rbs +1149 -598
- data/core/ruby_vm.rbs +126 -12
- data/core/rubygems/platform.rbs +9 -0
- data/core/rubygems/rubygems.rbs +1 -1
- data/core/rubygems/version.rbs +5 -1
- data/core/set.rbs +20 -22
- data/core/signal.rbs +4 -4
- data/core/string.rbs +283 -230
- data/core/string_io.rbs +2 -14
- data/core/struct.rbs +404 -24
- data/core/symbol.rbs +1 -19
- data/core/thread.rbs +29 -12
- data/core/time.rbs +227 -104
- data/core/trace_point.rbs +2 -5
- data/core/true_class.rbs +54 -21
- data/core/warning.rbs +14 -11
- data/docs/data_and_struct.md +29 -0
- data/docs/gem.md +58 -0
- data/docs/syntax.md +3 -5
- data/docs/tools.md +1 -0
- data/ext/rbs_extension/lexer.c +643 -559
- data/ext/rbs_extension/lexer.re +5 -1
- data/ext/rbs_extension/parser.c +12 -3
- data/ext/rbs_extension/unescape.c +7 -47
- data/lib/rbs/cli/diff.rb +4 -1
- data/lib/rbs/cli/validate.rb +280 -0
- data/lib/rbs/cli.rb +2 -194
- data/lib/rbs/collection/config.rb +5 -6
- data/lib/rbs/collection/sources/git.rb +1 -1
- data/lib/rbs/collection.rb +1 -0
- data/lib/rbs/diff.rb +7 -4
- data/lib/rbs/errors.rb +11 -0
- data/lib/rbs/test/errors.rb +10 -2
- data/lib/rbs/test/guaranteed.rb +2 -3
- data/lib/rbs/test/type_check.rb +15 -10
- data/lib/rbs/test.rb +3 -3
- data/lib/rbs/types.rb +29 -0
- data/lib/rbs/unit_test/convertibles.rb +176 -0
- data/lib/rbs/unit_test/spy.rb +136 -0
- data/lib/rbs/unit_test/type_assertions.rb +341 -0
- data/lib/rbs/unit_test/with_aliases.rb +143 -0
- data/lib/rbs/unit_test.rb +6 -0
- data/lib/rbs/version.rb +1 -1
- data/sig/cli/validate.rbs +43 -0
- data/sig/diff.rbs +3 -1
- data/sig/errors.rbs +8 -0
- data/sig/rbs.rbs +1 -1
- data/sig/test/errors.rbs +52 -0
- data/sig/test/guranteed.rbs +9 -0
- data/sig/test/type_check.rbs +19 -0
- data/sig/test.rbs +82 -0
- data/sig/types.rbs +6 -1
- data/sig/unit_test/convertibles.rbs +154 -0
- data/sig/unit_test/spy.rbs +28 -0
- data/sig/unit_test/type_assertions.rbs +194 -0
- data/sig/unit_test/with_aliases.rbs +136 -0
- data/stdlib/base64/0/base64.rbs +307 -45
- data/stdlib/bigdecimal/0/big_decimal.rbs +35 -15
- data/stdlib/coverage/0/coverage.rbs +2 -2
- data/stdlib/csv/0/csv.rbs +25 -55
- data/stdlib/date/0/date.rbs +1 -43
- data/stdlib/date/0/date_time.rbs +1 -13
- data/stdlib/delegate/0/delegator.rbs +186 -0
- data/stdlib/delegate/0/kernel.rbs +47 -0
- data/stdlib/delegate/0/simple_delegator.rbs +98 -0
- data/stdlib/did_you_mean/0/did_you_mean.rbs +1 -1
- data/stdlib/erb/0/erb.rbs +2 -2
- data/stdlib/fileutils/0/fileutils.rbs +0 -19
- data/stdlib/io-console/0/io-console.rbs +12 -1
- data/stdlib/ipaddr/0/ipaddr.rbs +2 -1
- data/stdlib/json/0/json.rbs +320 -81
- data/stdlib/logger/0/logger.rbs +9 -5
- data/stdlib/minitest/0/minitest/test/lifecycle_hooks.rbs +6 -6
- data/stdlib/monitor/0/monitor.rbs +78 -0
- data/stdlib/net-http/0/net-http.rbs +1880 -543
- data/stdlib/objspace/0/objspace.rbs +19 -13
- data/stdlib/openssl/0/openssl.rbs +508 -127
- data/stdlib/optparse/0/optparse.rbs +25 -11
- data/stdlib/pathname/0/pathname.rbs +1 -1
- data/stdlib/pp/0/pp.rbs +2 -5
- data/stdlib/prettyprint/0/prettyprint.rbs +2 -2
- data/stdlib/pstore/0/pstore.rbs +2 -4
- data/stdlib/rdoc/0/comment.rbs +1 -2
- data/stdlib/resolv/0/resolv.rbs +4 -2
- data/stdlib/socket/0/socket.rbs +2 -2
- data/stdlib/socket/0/unix_socket.rbs +2 -2
- data/stdlib/strscan/0/string_scanner.rbs +3 -2
- data/stdlib/tempfile/0/tempfile.rbs +1 -1
- data/stdlib/uri/0/common.rbs +245 -123
- metadata +24 -4
- data/lib/rbs/test/spy.rb +0 -6
data/lib/rbs/diff.rb
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
module RBS
|
|
4
4
|
class Diff
|
|
5
|
-
def initialize(type_name:, library_options:, after_path: [], before_path: [])
|
|
5
|
+
def initialize(type_name:, library_options:, after_path: [], before_path: [], detail: false)
|
|
6
6
|
@type_name = type_name
|
|
7
7
|
@library_options = library_options
|
|
8
8
|
@after_path = after_path
|
|
9
9
|
@before_path = before_path
|
|
10
|
+
@detail = detail
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
def each_diff(&block)
|
|
@@ -100,11 +101,12 @@ module RBS
|
|
|
100
101
|
if definition_method
|
|
101
102
|
prefix = kind == :instance ? "" : "self."
|
|
102
103
|
|
|
104
|
+
detail_to_s = @detail ? "[#{definition_method.defined_in} #{definition_method.accessibility}] " : ""
|
|
103
105
|
if definition_method.alias_of
|
|
104
106
|
first_def = definition_method.alias_of.defs.first #: Definition::Method::TypeDef
|
|
105
|
-
"alias #{prefix}#{key} #{prefix}#{first_def.member.name}"
|
|
107
|
+
"#{detail_to_s}alias #{prefix}#{key} #{prefix}#{first_def.member.name}"
|
|
106
108
|
else
|
|
107
|
-
"def #{prefix}#{key}: #{definition_method.method_types.join(" | ")}"
|
|
109
|
+
"#{detail_to_s}def #{prefix}#{key}: #{definition_method.method_types.join(" | ")}"
|
|
108
110
|
end
|
|
109
111
|
else
|
|
110
112
|
+"-"
|
|
@@ -113,7 +115,8 @@ module RBS
|
|
|
113
115
|
|
|
114
116
|
def constant_to_s(constant)
|
|
115
117
|
if constant
|
|
116
|
-
"#{constant.name.
|
|
118
|
+
detail_to_s = @detail ? "[#{constant.name.namespace.to_type_name.to_s}] " : ""
|
|
119
|
+
"#{detail_to_s}#{constant.name.name}: #{constant.type}"
|
|
117
120
|
else
|
|
118
121
|
+"-"
|
|
119
122
|
end
|
data/lib/rbs/errors.rb
CHANGED
|
@@ -557,4 +557,15 @@ module RBS
|
|
|
557
557
|
@alias_entry.decl.location
|
|
558
558
|
end
|
|
559
559
|
end
|
|
560
|
+
|
|
561
|
+
class WillSyntaxError < DefinitionError
|
|
562
|
+
include DetailedMessageable
|
|
563
|
+
|
|
564
|
+
attr_reader :location
|
|
565
|
+
|
|
566
|
+
def initialize(message, location:)
|
|
567
|
+
super "#{Location.to_string(location)}: #{message}"
|
|
568
|
+
@location = location
|
|
569
|
+
end
|
|
570
|
+
end
|
|
560
571
|
end
|
data/lib/rbs/test/errors.rb
CHANGED
|
@@ -29,8 +29,11 @@ module RBS
|
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
RESPOND_TO = ::Kernel.instance_method :respond_to?
|
|
33
|
+
private_constant :RESPOND_TO
|
|
34
|
+
|
|
32
35
|
def self.inspect_(obj)
|
|
33
|
-
if
|
|
36
|
+
if RESPOND_TO.bind_call(obj, :inspect)
|
|
34
37
|
obj.inspect
|
|
35
38
|
else
|
|
36
39
|
Test::INSPECT.bind(obj).call # For the case inspect is not defined (like BasicObject)
|
|
@@ -38,7 +41,12 @@ module RBS
|
|
|
38
41
|
end
|
|
39
42
|
|
|
40
43
|
def self.to_string(error)
|
|
41
|
-
|
|
44
|
+
name = if error.klass.singleton_class?
|
|
45
|
+
inspect_(error.klass).sub(/\A#<Class:(.*)>\z/, '\1')
|
|
46
|
+
else
|
|
47
|
+
error.klass.name
|
|
48
|
+
end
|
|
49
|
+
method = "#{name}#{error.method_name}"
|
|
42
50
|
case error
|
|
43
51
|
when ArgumentTypeError
|
|
44
52
|
"[#{method}] ArgumentTypeError: expected #{format_param error.param} but given `#{inspect_(error.value)}`"
|
data/lib/rbs/test/guaranteed.rb
CHANGED
|
@@ -10,8 +10,7 @@ module RBS
|
|
|
10
10
|
|
|
11
11
|
module_function def guaranteed_inspect(obj)
|
|
12
12
|
obj.inspect
|
|
13
|
-
rescue NoMethodError
|
|
14
|
-
raise unless err.name == :inspect && EQUAL.bind_call(obj, err.receiver)
|
|
13
|
+
rescue NoMethodError
|
|
15
14
|
INSPECT.bind_call(obj)
|
|
16
15
|
end
|
|
17
16
|
|
|
@@ -20,7 +19,7 @@ module RBS
|
|
|
20
19
|
|
|
21
20
|
instance_variables.each_with_index do |variable, index|
|
|
22
21
|
string.concat ', ' unless index.zero?
|
|
23
|
-
string.concat "#{variable}: #{guaranteed_inspect(variable)}"
|
|
22
|
+
string.concat "#{variable}: #{guaranteed_inspect(instance_variable_get(variable))}"
|
|
24
23
|
end
|
|
25
24
|
|
|
26
25
|
string.concat '>'
|
data/lib/rbs/test/type_check.rb
CHANGED
|
@@ -10,8 +10,6 @@ module RBS
|
|
|
10
10
|
attr_reader :instance_class
|
|
11
11
|
attr_reader :class_class
|
|
12
12
|
|
|
13
|
-
attr_reader :const_cache
|
|
14
|
-
|
|
15
13
|
DEFAULT_SAMPLE_SIZE = 100
|
|
16
14
|
|
|
17
15
|
def initialize(self_class:, builder:, sample_size:, unchecked_classes:, instance_class: Object, class_class: Module)
|
|
@@ -21,7 +19,6 @@ module RBS
|
|
|
21
19
|
@builder = builder
|
|
22
20
|
@sample_size = sample_size
|
|
23
21
|
@unchecked_classes = unchecked_classes.uniq
|
|
24
|
-
@const_cache = {}
|
|
25
22
|
end
|
|
26
23
|
|
|
27
24
|
def overloaded_call(method, method_name, call, errors:)
|
|
@@ -38,6 +35,17 @@ module RBS
|
|
|
38
35
|
if es.size == 1
|
|
39
36
|
errors.push(*es[0])
|
|
40
37
|
else
|
|
38
|
+
RBS.logger.warn do
|
|
39
|
+
message = +"[#{self_class}#{method_name}] UnresolvedOverloadingError "
|
|
40
|
+
message << method.method_types.zip(es).map do |method_type, es|
|
|
41
|
+
msg = +"method_type=`#{method_type}`"
|
|
42
|
+
details = es.map do |e|
|
|
43
|
+
"\"#{Errors.to_string(e).sub("[#{e.klass.name}#{e.method_name}] ", "") }\""
|
|
44
|
+
end.join(', ')
|
|
45
|
+
msg << " details=[#{details}]"
|
|
46
|
+
end.join(', ')
|
|
47
|
+
message
|
|
48
|
+
end
|
|
41
49
|
errors << Errors::UnresolvedOverloadingError.new(
|
|
42
50
|
klass: self_class,
|
|
43
51
|
method_name: method_name,
|
|
@@ -208,11 +216,9 @@ module RBS
|
|
|
208
216
|
end
|
|
209
217
|
|
|
210
218
|
def get_class(type_name)
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
nil
|
|
215
|
-
end
|
|
219
|
+
Object.const_get(type_name.to_s)
|
|
220
|
+
rescue NameError
|
|
221
|
+
nil
|
|
216
222
|
end
|
|
217
223
|
|
|
218
224
|
def is_double?(value)
|
|
@@ -301,10 +307,9 @@ module RBS
|
|
|
301
307
|
end
|
|
302
308
|
val.is_a?(singleton_class)
|
|
303
309
|
when Types::Interface
|
|
304
|
-
methods = Set.new(Test.call(val, METHODS))
|
|
305
310
|
if (definition = builder.build_interface(type.name.absolute!))
|
|
306
311
|
definition.methods.each_key.all? do |method_name|
|
|
307
|
-
|
|
312
|
+
Test.call(val, RESPOND_TOP, method_name)
|
|
308
313
|
end
|
|
309
314
|
end
|
|
310
315
|
when Types::Variable
|
data/lib/rbs/test.rb
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
require "securerandom"
|
|
4
4
|
require "rbs/test/guaranteed"
|
|
5
5
|
require "rbs/test/observer"
|
|
6
|
-
require "rbs/test/spy"
|
|
7
6
|
require "rbs/test/errors"
|
|
8
7
|
require "rbs/test/type_check"
|
|
9
8
|
require "rbs/test/tester"
|
|
@@ -22,6 +21,7 @@ module RBS
|
|
|
22
21
|
PP = Kernel.instance_method(:pp)
|
|
23
22
|
INSPECT = Kernel.instance_method(:inspect)
|
|
24
23
|
METHODS = Kernel.instance_method(:methods)
|
|
24
|
+
RESPOND_TOP = Kernel.instance_method(:respond_to?)
|
|
25
25
|
|
|
26
26
|
class ArgumentsReturn
|
|
27
27
|
include Guaranteed::Inspect
|
|
@@ -85,11 +85,11 @@ module RBS
|
|
|
85
85
|
|
|
86
86
|
if ::UnboundMethod.instance_methods.include?(:bind_call)
|
|
87
87
|
def self.call(receiver, method, *args, &block)
|
|
88
|
-
method.bind_call(receiver, *args, &block)
|
|
88
|
+
__skip__ = method.bind_call(receiver, *args, &block)
|
|
89
89
|
end
|
|
90
90
|
else
|
|
91
91
|
def self.call(receiver, method, *args, &block)
|
|
92
|
-
method.bind(receiver).call(*args, &block)
|
|
92
|
+
__skip__ = method.bind(receiver).call(*args, &block)
|
|
93
93
|
end
|
|
94
94
|
end
|
|
95
95
|
end
|
data/lib/rbs/types.rb
CHANGED
|
@@ -1399,6 +1399,35 @@ module RBS
|
|
|
1399
1399
|
def with_nonreturn_void?
|
|
1400
1400
|
false
|
|
1401
1401
|
end
|
|
1402
|
+
|
|
1403
|
+
TABLE = {
|
|
1404
|
+
"\\a" => "\a",
|
|
1405
|
+
"\\b" => "\b",
|
|
1406
|
+
"\\e" => "\033",
|
|
1407
|
+
"\\f" => "\f",
|
|
1408
|
+
"\\n" => "\n",
|
|
1409
|
+
"\\r" => "\r",
|
|
1410
|
+
"\\s" => " ",
|
|
1411
|
+
"\\t" => "\t",
|
|
1412
|
+
"\\v" => "\v",
|
|
1413
|
+
"\\\"" => "\"",
|
|
1414
|
+
"\\\'" => "'",
|
|
1415
|
+
"\\\\" => "\\",
|
|
1416
|
+
"\\" => ""
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
def self.unescape_string(string, is_double_quote)
|
|
1420
|
+
if is_double_quote
|
|
1421
|
+
string.gsub!(/\\([0-9]{1,3})/) { ($1 || "").to_i(8).chr }
|
|
1422
|
+
string.gsub!(/\\x([0-9a-f]{1,2})/) { ($1 || "").to_i(16).chr }
|
|
1423
|
+
string.gsub!(/\\u([0-9a-fA-F]{4})/) { ($1 || "").to_i(16).chr(Encoding::UTF_8) }
|
|
1424
|
+
string.gsub!(/\\[abefnrstv"'\\]?/, TABLE)
|
|
1425
|
+
string
|
|
1426
|
+
else
|
|
1427
|
+
string.gsub!(/\\['\\]/, TABLE)
|
|
1428
|
+
string
|
|
1429
|
+
end
|
|
1430
|
+
end
|
|
1402
1431
|
end
|
|
1403
1432
|
end
|
|
1404
1433
|
end
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RBS
|
|
4
|
+
module UnitTest
|
|
5
|
+
module Convertibles
|
|
6
|
+
class BlankSlate < BasicObject
|
|
7
|
+
instance_methods.each do |im|
|
|
8
|
+
next if im == :__send__
|
|
9
|
+
undef_method im
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def __with_object_methods(*methods)
|
|
13
|
+
methods.each do |method|
|
|
14
|
+
singleton_class = ::Object.instance_method(:singleton_class).bind_call(self) #: Class
|
|
15
|
+
singleton_class.instance_eval do
|
|
16
|
+
define_method method, ::Object.instance_method(method)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
self
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class ToIO < BlankSlate
|
|
24
|
+
def initialize(io = $stdout)
|
|
25
|
+
@io = io
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def to_io
|
|
29
|
+
@io
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class ToI < BlankSlate
|
|
34
|
+
def initialize(value = 3)
|
|
35
|
+
@value = value
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def to_i
|
|
39
|
+
@value
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class ToInt < BlankSlate
|
|
44
|
+
def initialize(value = 3)
|
|
45
|
+
@value = value
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def to_int
|
|
49
|
+
@value
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class ToF < BlankSlate
|
|
54
|
+
def initialize(value = 0.1)
|
|
55
|
+
@value = value
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def to_f
|
|
59
|
+
@value
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
class ToR < BlankSlate
|
|
64
|
+
def initialize(value = 1r)
|
|
65
|
+
@value = value
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def to_r
|
|
69
|
+
@value
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class ToC < BlankSlate
|
|
74
|
+
def initialize(value = 1i)
|
|
75
|
+
@value = value
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def to_c
|
|
79
|
+
@value
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
class ToStr < BlankSlate
|
|
84
|
+
def initialize(value = "")
|
|
85
|
+
@value = value
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def to_str
|
|
89
|
+
@value
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
class ToS < BlankSlate
|
|
94
|
+
def initialize(value = "")
|
|
95
|
+
@value = value
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def to_s
|
|
99
|
+
@value
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
class ToSym < BlankSlate
|
|
104
|
+
def initialize(value = :&)
|
|
105
|
+
@value = value
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def to_sym
|
|
109
|
+
@value
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
class ToA < BlankSlate
|
|
114
|
+
def initialize(*args)
|
|
115
|
+
@args = args
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def to_a
|
|
119
|
+
@args
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
class ToArray < BlankSlate
|
|
124
|
+
def initialize(*args)
|
|
125
|
+
@args = args
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def to_ary
|
|
129
|
+
@args
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
class ToHash < BlankSlate
|
|
134
|
+
def initialize(hash = { 'hello' => 'world' })
|
|
135
|
+
@hash = hash
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def to_hash
|
|
139
|
+
@hash
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
class ToPath < BlankSlate
|
|
144
|
+
def initialize(value = "")
|
|
145
|
+
@value = value
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def to_path
|
|
149
|
+
@value
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
class CustomRange < BlankSlate
|
|
154
|
+
attr_reader :begin, :end
|
|
155
|
+
|
|
156
|
+
def initialize(begin_, end_, exclude_end = false)
|
|
157
|
+
@begin = begin_
|
|
158
|
+
@end = end_
|
|
159
|
+
@exclude_end = exclude_end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def exclude_end? = @exclude_end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
class Each < BlankSlate
|
|
166
|
+
def initialize(*args)
|
|
167
|
+
@args = args
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def each(&block)
|
|
171
|
+
@args.each(&block)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RBS
|
|
4
|
+
module UnitTest
|
|
5
|
+
module Spy
|
|
6
|
+
def self.wrap(object, method_name)
|
|
7
|
+
spy = WrapSpy.new(object: object, method_name: method_name)
|
|
8
|
+
|
|
9
|
+
if block_given?
|
|
10
|
+
begin
|
|
11
|
+
yield spy, spy.wrapped_object
|
|
12
|
+
end
|
|
13
|
+
else
|
|
14
|
+
spy
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class WrapSpy
|
|
19
|
+
attr_accessor :callback
|
|
20
|
+
attr_reader :object
|
|
21
|
+
attr_reader :method_name
|
|
22
|
+
|
|
23
|
+
def initialize(object:, method_name:)
|
|
24
|
+
@callback = -> (_) { }
|
|
25
|
+
@object = object
|
|
26
|
+
@method_name = method_name
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def wrapped_object
|
|
30
|
+
spy = self #: WrapSpy[untyped]
|
|
31
|
+
|
|
32
|
+
Class.new(BasicObject) do
|
|
33
|
+
# @type self: Class
|
|
34
|
+
|
|
35
|
+
define_method(:method_missing) do |name, *args, &block|
|
|
36
|
+
spy.object.__send__(name, *args, &block)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
define_method(
|
|
40
|
+
spy.method_name,
|
|
41
|
+
_ = -> (*args, &block) do
|
|
42
|
+
return_value = nil
|
|
43
|
+
exception = nil
|
|
44
|
+
block_calls = [] #: Array[Test::ArgumentsReturn]
|
|
45
|
+
|
|
46
|
+
spy_block = if block
|
|
47
|
+
Object.new.instance_eval do |fresh|
|
|
48
|
+
proc = -> (*block_args) do
|
|
49
|
+
block_exn = nil
|
|
50
|
+
block_return = nil
|
|
51
|
+
|
|
52
|
+
begin
|
|
53
|
+
block_return = if self.equal?(fresh)
|
|
54
|
+
# no instance eval
|
|
55
|
+
block.call(*block_args)
|
|
56
|
+
else
|
|
57
|
+
self.instance_exec(*block_args, &block)
|
|
58
|
+
end
|
|
59
|
+
rescue Exception => exn
|
|
60
|
+
block_exn = exn
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
if block_exn
|
|
64
|
+
block_calls << Test::ArgumentsReturn.exception(
|
|
65
|
+
arguments: block_args,
|
|
66
|
+
exception: block_exn
|
|
67
|
+
)
|
|
68
|
+
else
|
|
69
|
+
block_calls << Test::ArgumentsReturn.return(
|
|
70
|
+
arguments: block_args,
|
|
71
|
+
value: block_return
|
|
72
|
+
)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
if block_exn
|
|
76
|
+
raise block_exn
|
|
77
|
+
else
|
|
78
|
+
block_return
|
|
79
|
+
end
|
|
80
|
+
end #: Proc
|
|
81
|
+
|
|
82
|
+
proc.ruby2_keywords
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
begin
|
|
87
|
+
if spy_block
|
|
88
|
+
return_value = spy.object.__send__(spy.method_name, *args) do |*a, **k, &b|
|
|
89
|
+
spy_block.call(*a, **k, &b)
|
|
90
|
+
end
|
|
91
|
+
else
|
|
92
|
+
return_value = spy.object.__send__(spy.method_name, *args, &spy_block)
|
|
93
|
+
end
|
|
94
|
+
rescue ::Exception => exn
|
|
95
|
+
exception = exn
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
return_value
|
|
99
|
+
|
|
100
|
+
ensure
|
|
101
|
+
call =
|
|
102
|
+
case
|
|
103
|
+
when exception
|
|
104
|
+
Test::ArgumentsReturn.exception(
|
|
105
|
+
arguments: args,
|
|
106
|
+
exception: exception
|
|
107
|
+
)
|
|
108
|
+
when return_value
|
|
109
|
+
Test::ArgumentsReturn.return(
|
|
110
|
+
arguments: args,
|
|
111
|
+
value: return_value
|
|
112
|
+
)
|
|
113
|
+
else
|
|
114
|
+
# break
|
|
115
|
+
Test::ArgumentsReturn.break(arguments: args)
|
|
116
|
+
end
|
|
117
|
+
trace = RBS::Test::CallTrace.new(
|
|
118
|
+
method_name: spy.method_name,
|
|
119
|
+
method_call: call,
|
|
120
|
+
block_calls: block_calls,
|
|
121
|
+
block_given: block != nil
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
spy.callback.call(trace)
|
|
125
|
+
|
|
126
|
+
if exception
|
|
127
|
+
spy.object.__send__(:raise, exception)
|
|
128
|
+
end
|
|
129
|
+
end.ruby2_keywords
|
|
130
|
+
)
|
|
131
|
+
end.new()
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|