rbs 0.3.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +7 -1
  3. data/.gitignore +1 -1
  4. data/CHANGELOG.md +39 -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 +315 -122
  20. data/lib/rbs/constant.rb +4 -4
  21. data/lib/rbs/constant_table.rb +51 -45
  22. data/lib/rbs/definition.rb +175 -59
  23. data/lib/rbs/definition_builder.rb +802 -604
  24. data/lib/rbs/environment.rb +352 -210
  25. data/lib/rbs/environment_walker.rb +14 -23
  26. data/lib/rbs/errors.rb +184 -3
  27. data/lib/rbs/factory.rb +14 -0
  28. data/lib/rbs/parser.y +95 -27
  29. data/lib/rbs/prototype/rb.rb +119 -117
  30. data/lib/rbs/prototype/rbi.rb +5 -3
  31. data/lib/rbs/prototype/runtime.rb +34 -7
  32. data/lib/rbs/substitution.rb +12 -1
  33. data/lib/rbs/test.rb +82 -3
  34. data/lib/rbs/test/errors.rb +5 -1
  35. data/lib/rbs/test/hook.rb +133 -259
  36. data/lib/rbs/test/observer.rb +17 -0
  37. data/lib/rbs/test/setup.rb +35 -19
  38. data/lib/rbs/test/setup_helper.rb +29 -0
  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 +43 -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 +4 -4
  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/pty/pty.rbs +159 -0
  80. data/stdlib/tmpdir/tmpdir.rbs +1 -1
  81. metadata +28 -116
  82. 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 unless decls.include?(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)