rbs 3.3.2 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/comments.yml +2 -5
  3. data/.github/workflows/ruby.yml +7 -8
  4. data/.github/workflows/typecheck.yml +37 -0
  5. data/CHANGELOG.md +65 -0
  6. data/Gemfile +1 -1
  7. data/Gemfile.lock +11 -11
  8. data/README.md +1 -0
  9. data/Rakefile +2 -2
  10. data/Steepfile +2 -2
  11. data/core/array.rbs +19 -49
  12. data/core/basic_object.rbs +2 -2
  13. data/core/comparable.rbs +17 -8
  14. data/core/complex.rbs +82 -43
  15. data/core/data.rbs +2 -4
  16. data/core/dir.rbs +635 -295
  17. data/core/enumerable.rbs +11 -18
  18. data/core/enumerator.rbs +37 -31
  19. data/core/errors.rbs +4 -0
  20. data/core/false_class.rbs +34 -15
  21. data/core/fiber.rbs +23 -0
  22. data/core/file.rbs +329 -120
  23. data/core/float.rbs +17 -32
  24. data/core/gc.rbs +17 -11
  25. data/core/hash.rbs +22 -44
  26. data/core/integer.rbs +82 -113
  27. data/core/io/buffer.rbs +90 -47
  28. data/core/io.rbs +54 -121
  29. data/core/kernel.rbs +442 -489
  30. data/core/match_data.rbs +55 -56
  31. data/core/module.rbs +45 -1
  32. data/core/nil_class.rbs +98 -35
  33. data/core/numeric.rbs +22 -32
  34. data/core/object_space/weak_key_map.rbs +102 -0
  35. data/core/process.rbs +1242 -655
  36. data/core/ractor.rbs +139 -120
  37. data/core/range.rbs +100 -4
  38. data/core/rational.rbs +0 -4
  39. data/core/rbs/unnamed/argf.rbs +16 -8
  40. data/core/rbs/unnamed/env_class.rbs +0 -24
  41. data/core/refinement.rbs +8 -0
  42. data/core/regexp.rbs +1149 -598
  43. data/core/ruby_vm.rbs +126 -12
  44. data/core/rubygems/platform.rbs +9 -0
  45. data/core/rubygems/rubygems.rbs +1 -1
  46. data/core/rubygems/version.rbs +5 -1
  47. data/core/set.rbs +20 -22
  48. data/core/signal.rbs +4 -4
  49. data/core/string.rbs +283 -230
  50. data/core/string_io.rbs +2 -14
  51. data/core/struct.rbs +404 -24
  52. data/core/symbol.rbs +1 -19
  53. data/core/thread.rbs +29 -12
  54. data/core/time.rbs +227 -104
  55. data/core/trace_point.rbs +2 -5
  56. data/core/true_class.rbs +54 -21
  57. data/core/warning.rbs +14 -11
  58. data/docs/data_and_struct.md +29 -0
  59. data/docs/gem.md +58 -0
  60. data/docs/syntax.md +3 -5
  61. data/docs/tools.md +1 -0
  62. data/ext/rbs_extension/lexer.c +643 -559
  63. data/ext/rbs_extension/lexer.re +5 -1
  64. data/ext/rbs_extension/parser.c +12 -3
  65. data/ext/rbs_extension/unescape.c +7 -47
  66. data/lib/rbs/cli/diff.rb +4 -1
  67. data/lib/rbs/cli/validate.rb +280 -0
  68. data/lib/rbs/cli.rb +2 -194
  69. data/lib/rbs/collection/config.rb +5 -6
  70. data/lib/rbs/collection/sources/git.rb +1 -1
  71. data/lib/rbs/collection.rb +1 -0
  72. data/lib/rbs/diff.rb +7 -4
  73. data/lib/rbs/errors.rb +11 -0
  74. data/lib/rbs/test/errors.rb +10 -2
  75. data/lib/rbs/test/guaranteed.rb +2 -3
  76. data/lib/rbs/test/type_check.rb +15 -10
  77. data/lib/rbs/test.rb +3 -3
  78. data/lib/rbs/types.rb +29 -0
  79. data/lib/rbs/unit_test/convertibles.rb +176 -0
  80. data/lib/rbs/unit_test/spy.rb +136 -0
  81. data/lib/rbs/unit_test/type_assertions.rb +341 -0
  82. data/lib/rbs/unit_test/with_aliases.rb +143 -0
  83. data/lib/rbs/unit_test.rb +6 -0
  84. data/lib/rbs/version.rb +1 -1
  85. data/sig/cli/validate.rbs +43 -0
  86. data/sig/diff.rbs +3 -1
  87. data/sig/errors.rbs +8 -0
  88. data/sig/rbs.rbs +1 -1
  89. data/sig/test/errors.rbs +52 -0
  90. data/sig/test/guranteed.rbs +9 -0
  91. data/sig/test/type_check.rbs +19 -0
  92. data/sig/test.rbs +82 -0
  93. data/sig/types.rbs +6 -1
  94. data/sig/unit_test/convertibles.rbs +154 -0
  95. data/sig/unit_test/spy.rbs +28 -0
  96. data/sig/unit_test/type_assertions.rbs +194 -0
  97. data/sig/unit_test/with_aliases.rbs +136 -0
  98. data/stdlib/base64/0/base64.rbs +307 -45
  99. data/stdlib/bigdecimal/0/big_decimal.rbs +35 -15
  100. data/stdlib/coverage/0/coverage.rbs +2 -2
  101. data/stdlib/csv/0/csv.rbs +25 -55
  102. data/stdlib/date/0/date.rbs +1 -43
  103. data/stdlib/date/0/date_time.rbs +1 -13
  104. data/stdlib/delegate/0/delegator.rbs +186 -0
  105. data/stdlib/delegate/0/kernel.rbs +47 -0
  106. data/stdlib/delegate/0/simple_delegator.rbs +98 -0
  107. data/stdlib/did_you_mean/0/did_you_mean.rbs +1 -1
  108. data/stdlib/erb/0/erb.rbs +2 -2
  109. data/stdlib/fileutils/0/fileutils.rbs +0 -19
  110. data/stdlib/io-console/0/io-console.rbs +12 -1
  111. data/stdlib/ipaddr/0/ipaddr.rbs +2 -1
  112. data/stdlib/json/0/json.rbs +320 -81
  113. data/stdlib/logger/0/logger.rbs +9 -5
  114. data/stdlib/minitest/0/minitest/test/lifecycle_hooks.rbs +6 -6
  115. data/stdlib/monitor/0/monitor.rbs +78 -0
  116. data/stdlib/net-http/0/net-http.rbs +1880 -543
  117. data/stdlib/objspace/0/objspace.rbs +19 -13
  118. data/stdlib/openssl/0/openssl.rbs +508 -127
  119. data/stdlib/optparse/0/optparse.rbs +25 -11
  120. data/stdlib/pathname/0/pathname.rbs +1 -1
  121. data/stdlib/pp/0/pp.rbs +2 -5
  122. data/stdlib/prettyprint/0/prettyprint.rbs +2 -2
  123. data/stdlib/pstore/0/pstore.rbs +2 -4
  124. data/stdlib/rdoc/0/comment.rbs +1 -2
  125. data/stdlib/resolv/0/resolv.rbs +4 -2
  126. data/stdlib/socket/0/socket.rbs +2 -2
  127. data/stdlib/socket/0/unix_socket.rbs +2 -2
  128. data/stdlib/strscan/0/string_scanner.rbs +3 -2
  129. data/stdlib/tempfile/0/tempfile.rbs +1 -1
  130. data/stdlib/uri/0/common.rbs +245 -123
  131. metadata +24 -4
  132. 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.name}: #{constant.type}"
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
@@ -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 obj.respond_to?(:inspect)
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
- method = "#{error.klass.name}#{error.method_name}"
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)}`"
@@ -10,8 +10,7 @@ module RBS
10
10
 
11
11
  module_function def guaranteed_inspect(obj)
12
12
  obj.inspect
13
- rescue NoMethodError => err
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 '>'
@@ -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
- const_cache[type_name] ||= begin
212
- Object.const_get(type_name.to_s)
213
- rescue NameError
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
- methods.member?(method_name)
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