rbs 0.2.0 → 0.6.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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +7 -1
  3. data/.gitignore +1 -1
  4. data/CHANGELOG.md +35 -0
  5. data/COPYING +1 -1
  6. data/Gemfile +16 -2
  7. data/README.md +87 -48
  8. data/Rakefile +54 -22
  9. data/bin/rbs-prof +9 -0
  10. data/bin/run_in_md.rb +49 -0
  11. data/bin/test_runner.rb +0 -2
  12. data/docs/sigs.md +6 -6
  13. data/docs/stdlib.md +3 -5
  14. data/docs/syntax.md +6 -3
  15. data/goodcheck.yml +65 -0
  16. data/lib/rbs.rb +3 -0
  17. data/lib/rbs/ast/declarations.rb +115 -14
  18. data/lib/rbs/ast/members.rb +41 -17
  19. data/lib/rbs/cli.rb +301 -123
  20. data/lib/rbs/constant.rb +4 -4
  21. data/lib/rbs/constant_table.rb +64 -53
  22. data/lib/rbs/definition.rb +175 -59
  23. data/lib/rbs/definition_builder.rb +646 -603
  24. data/lib/rbs/environment.rb +352 -210
  25. data/lib/rbs/environment_walker.rb +14 -23
  26. data/lib/rbs/errors.rb +159 -3
  27. data/lib/rbs/factory.rb +14 -0
  28. data/lib/rbs/namespace.rb +18 -0
  29. data/lib/rbs/parser.y +75 -21
  30. data/lib/rbs/prototype/rb.rb +119 -117
  31. data/lib/rbs/prototype/rbi.rb +5 -3
  32. data/lib/rbs/prototype/runtime.rb +34 -7
  33. data/lib/rbs/substitution.rb +8 -1
  34. data/lib/rbs/test.rb +81 -3
  35. data/lib/rbs/test/errors.rb +1 -1
  36. data/lib/rbs/test/hook.rb +133 -259
  37. data/lib/rbs/test/observer.rb +17 -0
  38. data/lib/rbs/test/setup.rb +13 -14
  39. data/lib/rbs/test/spy.rb +0 -321
  40. data/lib/rbs/test/tester.rb +116 -0
  41. data/lib/rbs/test/type_check.rb +44 -7
  42. data/lib/rbs/type_name_resolver.rb +58 -0
  43. data/lib/rbs/types.rb +94 -2
  44. data/lib/rbs/validator.rb +51 -0
  45. data/lib/rbs/variance_calculator.rb +12 -2
  46. data/lib/rbs/version.rb +1 -1
  47. data/lib/rbs/writer.rb +127 -91
  48. data/rbs.gemspec +0 -9
  49. data/schema/annotation.json +14 -0
  50. data/schema/comment.json +26 -0
  51. data/schema/decls.json +353 -0
  52. data/schema/function.json +87 -0
  53. data/schema/location.json +56 -0
  54. data/schema/members.json +248 -0
  55. data/schema/methodType.json +44 -0
  56. data/schema/types.json +299 -0
  57. data/stdlib/benchmark/benchmark.rbs +151 -151
  58. data/stdlib/builtin/encoding.rbs +2 -0
  59. data/stdlib/builtin/enumerable.rbs +2 -2
  60. data/stdlib/builtin/enumerator.rbs +3 -1
  61. data/stdlib/builtin/fiber.rbs +5 -1
  62. data/stdlib/builtin/file.rbs +0 -3
  63. data/stdlib/builtin/io.rbs +4 -4
  64. data/stdlib/builtin/proc.rbs +1 -2
  65. data/stdlib/builtin/symbol.rbs +1 -1
  66. data/stdlib/builtin/thread.rbs +2 -2
  67. data/stdlib/csv/csv.rbs +4 -6
  68. data/stdlib/fiber/fiber.rbs +117 -0
  69. data/stdlib/json/json.rbs +1 -1
  70. data/stdlib/logger/formatter.rbs +23 -0
  71. data/stdlib/logger/log_device.rbs +39 -0
  72. data/stdlib/logger/logger.rbs +507 -0
  73. data/stdlib/logger/period.rbs +7 -0
  74. data/stdlib/logger/severity.rbs +8 -0
  75. data/stdlib/mutex_m/mutex_m.rbs +77 -0
  76. data/stdlib/pathname/pathname.rbs +6 -6
  77. data/stdlib/prime/integer-extension.rbs +1 -1
  78. data/stdlib/prime/prime.rbs +44 -44
  79. data/stdlib/tmpdir/tmpdir.rbs +1 -1
  80. metadata +26 -116
  81. data/lib/rbs/test/test_helper.rb +0 -183
@@ -6,19 +6,20 @@ module RBS
6
6
 
7
7
  def initialize
8
8
  @source_decls = []
9
- @toplevel_members = []
10
9
  end
11
10
 
12
11
  def decls
13
12
  decls = []
14
13
 
15
- decls.push(*source_decls)
14
+ top_decls, top_members = source_decls.partition {|decl| decl.is_a?(AST::Declarations::Base) }
16
15
 
17
- unless toplevel_members.empty?
18
- top = AST::Declarations::Extension.new(
16
+ decls.push(*top_decls)
17
+
18
+ unless top_members.empty?
19
+ top = AST::Declarations::Class.new(
19
20
  name: TypeName.new(name: :Object, namespace: Namespace.empty),
20
- extension_name: :Toplevel,
21
- members: toplevel_members,
21
+ super_class: nil,
22
+ members: top_members,
22
23
  annotations: [],
23
24
  comment: nil,
24
25
  location: nil,
@@ -27,7 +28,7 @@ module RBS
27
28
  decls << top
28
29
  end
29
30
 
30
- decls.uniq
31
+ decls
31
32
  end
32
33
 
33
34
  def parse(string)
@@ -51,19 +52,15 @@ module RBS
51
52
  end
52
53
  end
53
54
 
54
- process RubyVM::AbstractSyntaxTree.parse(string), namespace: Namespace.empty, current_module: nil, comments: comments, singleton: false
55
- end
56
-
57
- def nested_name(name)
58
- (current_namespace + const_to_name(name).to_namespace).to_type_name.relative!
55
+ process RubyVM::AbstractSyntaxTree.parse(string), decls: source_decls, comments: comments, singleton: false
59
56
  end
60
57
 
61
- def process(node, namespace:, current_module:, comments:, singleton:)
58
+ def process(node, decls:, comments:, singleton:)
62
59
  case node.type
63
60
  when :CLASS
64
61
  class_name, super_class, *class_body = node.children
65
62
  kls = AST::Declarations::Class.new(
66
- name: const_to_name(class_name).with_prefix(namespace).relative!,
63
+ name: const_to_name(class_name),
67
64
  super_class: super_class && AST::Declarations::Class::Super.new(name: const_to_name(super_class), args: []),
68
65
  type_params: AST::Declarations::ModuleTypeParams.empty,
69
66
  members: [],
@@ -72,39 +69,42 @@ module RBS
72
69
  comment: comments[node.first_lineno - 1]
73
70
  )
74
71
 
75
- source_decls.push kls
72
+ decls.push kls
76
73
 
77
74
  each_node class_body do |child|
78
- process child, namespace: kls.name.to_namespace, current_module: kls, comments: comments, singleton: false
75
+ process child, decls: kls.members, comments: comments, singleton: false
79
76
  end
77
+
80
78
  when :MODULE
81
79
  module_name, *module_body = node.children
82
80
 
83
81
  mod = AST::Declarations::Module.new(
84
- name: const_to_name(module_name).with_prefix(namespace).relative!,
82
+ name: const_to_name(module_name),
85
83
  type_params: AST::Declarations::ModuleTypeParams.empty,
86
- self_type: nil,
84
+ self_types: [],
87
85
  members: [],
88
86
  annotations: [],
89
87
  location: nil,
90
88
  comment: comments[node.first_lineno - 1]
91
89
  )
92
90
 
93
- source_decls.push mod
91
+ decls.push mod
94
92
 
95
93
  each_node module_body do |child|
96
- process child, namespace: mod.name.to_namespace, current_module: mod, comments: comments, singleton: false
94
+ process child, decls: mod.members, comments: comments, singleton: false
97
95
  end
96
+
98
97
  when :SCLASS
99
- this = node.children[0]
98
+ this, body = node.children
99
+
100
100
  if this.type != :SELF
101
101
  RBS.logger.warn "`class <<` syntax with not-self may be compiled to incorrect code: #{this}"
102
102
  end
103
103
 
104
- body = node.children[1]
105
104
  each_child(body) do |child|
106
- process child, namespace: namespace, current_module: current_module, comments: comments, singleton: true
105
+ process child, decls: decls, comments: comments, singleton: true
107
106
  end
107
+
108
108
  when :DEFN, :DEFS
109
109
  if node.type == :DEFN
110
110
  def_name, def_body = node.children
@@ -130,116 +130,104 @@ module RBS
130
130
  types: types,
131
131
  kind: kind,
132
132
  comment: comments[node.first_lineno - 1],
133
- attributes: []
133
+ attributes: [],
134
+ overload: false
134
135
  )
135
136
 
136
- if current_module
137
- current_module.members.push member
138
- else
139
- toplevel_members.push member
140
- end
137
+ decls.push member
138
+
141
139
  when :FCALL
142
- if current_module
143
- # Inside method definition cannot reach here.
144
- args = node.children[1]&.children || []
145
-
146
- case node.children[0]
147
- when :include
148
- args.each do |arg|
149
- if (name = const_to_name(arg))
150
- current_module.members << AST::Members::Include.new(
151
- name: name,
152
- args: [],
153
- annotations: [],
154
- location: nil,
155
- comment: comments[node.first_lineno - 1]
156
- )
157
- end
140
+ # Inside method definition cannot reach here.
141
+ args = node.children[1]&.children || []
142
+
143
+ case node.children[0]
144
+ when :include
145
+ args.each do |arg|
146
+ if (name = const_to_name(arg))
147
+ decls << AST::Members::Include.new(
148
+ name: name,
149
+ args: [],
150
+ annotations: [],
151
+ location: nil,
152
+ comment: comments[node.first_lineno - 1]
153
+ )
158
154
  end
159
- when :extend
160
- args.each do |arg|
161
- if (name = const_to_name(arg))
162
- current_module.members << AST::Members::Extend.new(
163
- name: name,
164
- args: [],
165
- annotations: [],
166
- location: nil,
167
- comment: comments[node.first_lineno - 1]
168
- )
169
- end
155
+ end
156
+ when :extend
157
+ args.each do |arg|
158
+ if (name = const_to_name(arg))
159
+ decls << AST::Members::Extend.new(
160
+ name: name,
161
+ args: [],
162
+ annotations: [],
163
+ location: nil,
164
+ comment: comments[node.first_lineno - 1]
165
+ )
170
166
  end
171
- when :attr_reader
172
- args.each do |arg|
173
- if arg&.type == :LIT && arg.children[0].is_a?(Symbol)
174
- current_module.members << AST::Members::AttrReader.new(
175
- name: arg.children[0],
176
- ivar_name: nil,
177
- type: Types::Bases::Any.new(location: nil),
178
- location: nil,
179
- comment: comments[node.first_lineno - 1],
180
- annotations: []
181
- )
182
- end
167
+ end
168
+ when :attr_reader
169
+ args.each do |arg|
170
+ if arg&.type == :LIT && arg.children[0].is_a?(Symbol)
171
+ decls << AST::Members::AttrReader.new(
172
+ name: arg.children[0],
173
+ ivar_name: nil,
174
+ type: Types::Bases::Any.new(location: nil),
175
+ location: nil,
176
+ comment: comments[node.first_lineno - 1],
177
+ annotations: []
178
+ )
183
179
  end
184
- when :attr_accessor
185
- args.each do |arg|
186
- if arg&.type == :LIT && arg.children[0].is_a?(Symbol)
187
- current_module.members << AST::Members::AttrAccessor.new(
188
- name: arg.children[0],
189
- ivar_name: nil,
190
- type: Types::Bases::Any.new(location: nil),
191
- location: nil,
192
- comment: comments[node.first_lineno - 1],
193
- annotations: []
194
- )
195
- end
180
+ end
181
+ when :attr_accessor
182
+ args.each do |arg|
183
+ if arg&.type == :LIT && arg.children[0].is_a?(Symbol)
184
+ decls << AST::Members::AttrAccessor.new(
185
+ name: arg.children[0],
186
+ ivar_name: nil,
187
+ type: Types::Bases::Any.new(location: nil),
188
+ location: nil,
189
+ comment: comments[node.first_lineno - 1],
190
+ annotations: []
191
+ )
196
192
  end
197
- when :attr_writer
198
- args.each do |arg|
199
- if arg&.type == :LIT && arg.children[0].is_a?(Symbol)
200
- current_module.members << AST::Members::AttrWriter.new(
201
- name: arg.children[0],
202
- ivar_name: nil,
203
- type: Types::Bases::Any.new(location: nil),
204
- location: nil,
205
- comment: comments[node.first_lineno - 1],
206
- annotations: []
207
- )
208
- end
193
+ end
194
+ when :attr_writer
195
+ args.each do |arg|
196
+ if arg&.type == :LIT && arg.children[0].is_a?(Symbol)
197
+ decls << AST::Members::AttrWriter.new(
198
+ name: arg.children[0],
199
+ ivar_name: nil,
200
+ type: Types::Bases::Any.new(location: nil),
201
+ location: nil,
202
+ comment: comments[node.first_lineno - 1],
203
+ annotations: []
204
+ )
209
205
  end
210
206
  end
211
207
  end
208
+
212
209
  each_child node do |child|
213
- process child, namespace: namespace, current_module: current_module, comments: comments, singleton: singleton
210
+ process child, decls: decls, comments: comments, singleton: singleton
214
211
  end
215
212
 
216
213
  when :CDECL
217
- type_name = case
218
- when node.children[0].is_a?(Symbol)
219
- ns = if current_module
220
- current_module.name.to_namespace
221
- else
222
- Namespace.empty
223
- end
224
- TypeName.new(name: node.children[0], namespace: ns)
225
- else
226
- name = const_to_name(node.children[0])
227
- if current_module
228
- name.with_prefix current_module.name.to_namespace
229
- else
230
- name
231
- end.relative!
232
- end
233
-
234
- source_decls << AST::Declarations::Constant.new(
235
- name: type_name,
214
+ const_name = case
215
+ when node.children[0].is_a?(Symbol)
216
+ TypeName.new(name: node.children[0], namespace: Namespace.empty)
217
+ else
218
+ const_to_name(node.children[0])
219
+ end
220
+
221
+ decls << AST::Declarations::Constant.new(
222
+ name: const_name,
236
223
  type: node_type(node.children.last),
237
224
  location: nil,
238
225
  comment: comments[node.first_lineno - 1]
239
226
  )
227
+
240
228
  else
241
229
  each_child node do |child|
242
- process child, namespace: namespace, current_module: current_module, comments: comments, singleton: singleton
230
+ process child, decls: decls, comments: comments, singleton: singleton
243
231
  end
244
232
  end
245
233
  end
@@ -328,7 +316,19 @@ module RBS
328
316
  body = node.children[2]
329
317
  return Types::Bases::Nil.new(location: nil) unless body
330
318
 
331
- literal_to_type(body)
319
+ if body.type == :BLOCK
320
+ return_stmts = any_node?(body) do |n|
321
+ n.type == :RETURN
322
+ end&.map do |return_node|
323
+ returned_value = return_node.children[0]
324
+ returned_value ? literal_to_type(returned_value) : Types::Bases::Nil.new(location: nil)
325
+ end || []
326
+ last_node = body.children.last
327
+ last_evaluated = last_node ? literal_to_type(last_node) : Types::Bases::Nil.new(location: nil)
328
+ types_to_union_type([*return_stmts, last_evaluated])
329
+ else
330
+ literal_to_type(body)
331
+ end
332
332
  end
333
333
 
334
334
  def literal_to_type(node)
@@ -393,7 +393,7 @@ module RBS
393
393
  value_types << literal_to_type(v)
394
394
  end
395
395
 
396
- if key_types.all? { |t| t.is_a?(Types::Literal) }
396
+ if !key_types.empty? && key_types.all? { |t| t.is_a?(Types::Literal) }
397
397
  fields = key_types.map { |t| t.literal }.zip(value_types).to_h
398
398
  Types::Record.new(fields: fields, location: nil)
399
399
  else
@@ -408,9 +408,11 @@ module RBS
408
408
 
409
409
  def types_to_union_type(types)
410
410
  return untyped if types.empty?
411
- return untyped if types.include?(untyped)
412
411
 
413
- Types::Union.new(types: types.uniq, location: nil)
412
+ uniq = types.uniq
413
+ return uniq.first if uniq.size == 1
414
+
415
+ Types::Union.new(types: uniq, location: nil)
414
416
  end
415
417
 
416
418
  def range_element_type(types)
@@ -69,7 +69,7 @@ module RBS
69
69
  members: [],
70
70
  annotations: [],
71
71
  location: nil,
72
- self_type: nil,
72
+ self_types: [],
73
73
  comment: comment
74
74
  )
75
75
 
@@ -173,7 +173,8 @@ module RBS
173
173
  types: types,
174
174
  kind: :singleton,
175
175
  comment: comment,
176
- attributes: []
176
+ attributes: [],
177
+ overload: false
177
178
  )
178
179
  end
179
180
 
@@ -193,7 +194,8 @@ module RBS
193
194
  types: types,
194
195
  kind: :instance,
195
196
  comment: comment,
196
- attributes: []
197
+ attributes: [],
198
+ overload: false
197
199
  )
198
200
  end
199
201
 
@@ -128,7 +128,7 @@ module RBS
128
128
 
129
129
  def merge_rbs(module_name, members, instance: nil, singleton: nil)
130
130
  if merge
131
- if env.class?(module_name.absolute!)
131
+ if env.class_decls[module_name.absolute!]
132
132
  case
133
133
  when instance
134
134
  method = builder.build_instance(module_name.absolute!).methods[instance]
@@ -152,9 +152,10 @@ module RBS
152
152
  },
153
153
  kind: kind,
154
154
  location: nil,
155
- comment: method.comment,
155
+ comment: method.comments[0],
156
156
  annotations: method.annotations,
157
- attributes: method.attributes
157
+ attributes: method.attributes,
158
+ overload: false
158
159
  )
159
160
  return
160
161
  end
@@ -192,7 +193,8 @@ module RBS
192
193
  location: nil,
193
194
  comment: nil,
194
195
  annotations: [],
195
- attributes: []
196
+ attributes: [],
197
+ overload: false
196
198
  )
197
199
  end
198
200
  else
@@ -225,7 +227,8 @@ module RBS
225
227
  location: nil,
226
228
  comment: nil,
227
229
  annotations: [],
228
- attributes: []
230
+ attributes: [],
231
+ overload: false
229
232
  )
230
233
  end
231
234
  else
@@ -259,7 +262,8 @@ module RBS
259
262
  location: nil,
260
263
  comment: nil,
261
264
  annotations: [],
262
- attributes: []
265
+ attributes: [],
266
+ overload: false
263
267
  )
264
268
  end
265
269
  else
@@ -281,6 +285,11 @@ module RBS
281
285
  value = mod.const_get(name)
282
286
 
283
287
  next if value.is_a?(Class) || value.is_a?(Module)
288
+ unless value.class.name
289
+ RBS.logger.warn("Skipping constant #{name} #{value} of #{mod} as an instance of anonymous class")
290
+ next
291
+ end
292
+
284
293
  type = case value
285
294
  when true, false
286
295
  Types::Bases::Bool.new(location: nil)
@@ -306,6 +315,9 @@ module RBS
306
315
  type_name = to_type_name(mod.name)
307
316
  super_class = if mod.superclass == ::Object
308
317
  nil
318
+ elsif mod.superclass.name.nil?
319
+ RBS.logger.warn("Skipping anonymous superclass #{mod.superclass} of #{mod}")
320
+ nil
309
321
  else
310
322
  AST::Declarations::Class::Super.new(name: to_type_name(mod.superclass.name), args: [])
311
323
  end
@@ -321,6 +333,11 @@ module RBS
321
333
  )
322
334
 
323
335
  each_mixin(mod.included_modules, *mod.superclass.included_modules, *mod.included_modules.flat_map(&:included_modules)) do |included_module|
336
+ unless included_module.name
337
+ RBS.logger.warn("Skipping anonymous module #{included_module} included in #{mod}")
338
+ next
339
+ end
340
+
324
341
  module_name = to_type_name(included_module.name)
325
342
  if module_name.namespace == type_name.namespace
326
343
  module_name = TypeName.new(name: module_name.name, namespace: Namespace.empty)
@@ -343,12 +360,17 @@ module RBS
343
360
  end
344
361
 
345
362
  def generate_module(mod)
363
+ unless mod.name
364
+ RBS.logger.warn("Skipping anonymous module #{mod}")
365
+ return
366
+ end
367
+
346
368
  type_name = to_type_name(mod.name)
347
369
 
348
370
  decl = AST::Declarations::Module.new(
349
371
  name: type_name,
350
372
  type_params: AST::Declarations::ModuleTypeParams.empty,
351
- self_type: nil,
373
+ self_types: [],
352
374
  members: [],
353
375
  annotations: [],
354
376
  location: nil,
@@ -356,6 +378,11 @@ module RBS
356
378
  )
357
379
 
358
380
  each_mixin(mod.included_modules, *mod.included_modules.flat_map(&:included_modules), namespace: type_name.namespace) do |included_module|
381
+ unless included_module.name
382
+ RBS.logger.warn("Skipping anonymous module #{included_module} included in #{mod}")
383
+ next
384
+ end
385
+
359
386
  module_name = to_type_name(included_module.name)
360
387
  if module_name.namespace == type_name.namespace
361
388
  module_name = TypeName.new(name: module_name.name, namespace: Namespace.empty)