rbs 3.2.2 → 3.3.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 (135) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/comments.yml +1 -1
  3. data/.github/workflows/ruby.yml +7 -2
  4. data/.rubocop.yml +1 -1
  5. data/CHANGELOG.md +113 -0
  6. data/Gemfile +3 -0
  7. data/Gemfile.lock +21 -15
  8. data/README.md +11 -2
  9. data/Rakefile +10 -7
  10. data/Steepfile +7 -7
  11. data/core/basic_object.rbs +7 -7
  12. data/core/binding.rbs +3 -3
  13. data/core/builtin.rbs +171 -5
  14. data/core/constants.rbs +17 -17
  15. data/core/dir.rbs +3 -3
  16. data/core/encoding.rbs +434 -628
  17. data/core/enumerator.rbs +37 -0
  18. data/core/exception.rbs +11 -11
  19. data/core/false_class.rbs +5 -11
  20. data/core/fiber.rbs +3 -3
  21. data/core/file_test.rbs +28 -26
  22. data/core/kernel.rbs +900 -21
  23. data/core/marshal.rbs +24 -14
  24. data/core/match_data.rbs +8 -8
  25. data/core/math.rbs +57 -53
  26. data/core/method.rbs +3 -1
  27. data/core/module.rbs +38 -36
  28. data/core/nil_class.rbs +7 -13
  29. data/core/object.rbs +3 -966
  30. data/core/process.rbs +3 -3
  31. data/core/ractor.rbs +2 -2
  32. data/core/rb_config.rbs +64 -43
  33. data/core/regexp.rbs +3 -3
  34. data/core/set.rbs +3 -2
  35. data/core/signal.rbs +10 -4
  36. data/core/struct.rbs +1 -1
  37. data/core/thread.rbs +7 -7
  38. data/core/thread_group.rbs +9 -9
  39. data/core/true_class.rbs +5 -11
  40. data/core/unbound_method.rbs +56 -7
  41. data/core/warning.rbs +33 -0
  42. data/docs/collection.md +56 -6
  43. data/docs/data_and_struct.md +57 -0
  44. data/docs/stdlib.md +61 -2
  45. data/docs/syntax.md +123 -2
  46. data/ext/rbs_extension/lexer.c +624 -569
  47. data/ext/rbs_extension/lexer.h +1 -0
  48. data/ext/rbs_extension/lexer.re +1 -0
  49. data/ext/rbs_extension/lexstate.c +1 -0
  50. data/ext/rbs_extension/parser.c +6 -0
  51. data/goodcheck.yml +2 -2
  52. data/lib/rbs/annotate/formatter.rb +13 -3
  53. data/lib/rbs/annotate/rdoc_source.rb +10 -1
  54. data/lib/rbs/cli/colored_io.rb +48 -0
  55. data/lib/rbs/cli/diff.rb +80 -0
  56. data/lib/rbs/cli.rb +169 -17
  57. data/lib/rbs/collection/config/lockfile.rb +0 -25
  58. data/lib/rbs/collection/config/lockfile_generator.rb +0 -6
  59. data/lib/rbs/collection/installer.rb +1 -1
  60. data/lib/rbs/collection/sources/git.rb +6 -4
  61. data/lib/rbs/collection/sources/local.rb +7 -5
  62. data/lib/rbs/diff.rb +121 -0
  63. data/lib/rbs/environment.rb +1 -1
  64. data/lib/rbs/method_type.rb +23 -0
  65. data/lib/rbs/prototype/rb.rb +2 -9
  66. data/lib/rbs/prototype/rbi.rb +1 -1
  67. data/lib/rbs/prototype/runtime/helpers.rb +59 -0
  68. data/lib/rbs/prototype/runtime/reflection.rb +19 -0
  69. data/lib/rbs/prototype/runtime/value_object_generator.rb +275 -0
  70. data/lib/rbs/prototype/runtime.rb +233 -153
  71. data/lib/rbs/resolver/constant_resolver.rb +1 -1
  72. data/lib/rbs/sorter.rb +144 -117
  73. data/lib/rbs/test/guaranteed.rb +31 -0
  74. data/lib/rbs/test/type_check.rb +4 -4
  75. data/lib/rbs/test.rb +3 -0
  76. data/lib/rbs/types.rb +184 -3
  77. data/lib/rbs/version.rb +1 -1
  78. data/lib/rbs/writer.rb +4 -4
  79. data/lib/rbs.rb +1 -0
  80. data/rbs.gemspec +1 -0
  81. data/sig/annotate/formatter.rbs +2 -2
  82. data/sig/annotate/rdoc_annotater.rbs +1 -1
  83. data/sig/cli/colored_io.rbs +15 -0
  84. data/sig/cli/diff.rbs +21 -0
  85. data/sig/cli.rbs +2 -0
  86. data/sig/collection/config/lockfile.rbs +0 -6
  87. data/sig/diff.rbs +23 -0
  88. data/sig/errors.rbs +1 -5
  89. data/sig/method_types.rbs +6 -0
  90. data/sig/prototype/runtime.rbs +166 -0
  91. data/sig/rdoc/rbs.rbs +4 -0
  92. data/sig/shims/bundler.rbs +5 -0
  93. data/sig/sorter.rbs +23 -5
  94. data/sig/types.rbs +29 -0
  95. data/stdlib/benchmark/0/benchmark.rbs +1 -1
  96. data/stdlib/cgi/0/core.rbs +2 -2
  97. data/stdlib/did_you_mean/0/did_you_mean.rbs +2 -2
  98. data/stdlib/digest/0/digest.rbs +1 -1
  99. data/stdlib/fileutils/0/fileutils.rbs +1 -1
  100. data/stdlib/forwardable/0/forwardable.rbs +4 -4
  101. data/stdlib/io-console/0/io-console.rbs +1 -1
  102. data/stdlib/json/0/json.rbs +37 -0
  103. data/stdlib/logger/0/logger.rbs +2 -2
  104. data/stdlib/net-http/0/manifest.yaml +1 -1
  105. data/stdlib/net-http/0/net-http.rbs +16 -63
  106. data/stdlib/net-protocol/0/manifest.yaml +2 -0
  107. data/stdlib/net-protocol/0/net-protocol.rbs +56 -0
  108. data/stdlib/net-smtp/0/manifest.yaml +2 -0
  109. data/stdlib/net-smtp/0/net-smtp.rbs +55 -0
  110. data/stdlib/open-uri/0/manifest.yaml +3 -0
  111. data/stdlib/open-uri/0/open-uri.rbs +341 -0
  112. data/stdlib/openssl/0/openssl.rbs +1 -1
  113. data/stdlib/pp/0/manifest.yaml +2 -0
  114. data/stdlib/pp/0/pp.rbs +301 -0
  115. data/stdlib/{yaml → psych}/0/dbm.rbs +3 -3
  116. data/stdlib/psych/0/manifest.yaml +3 -0
  117. data/stdlib/psych/0/psych.rbs +391 -0
  118. data/stdlib/{yaml → psych}/0/store.rbs +2 -2
  119. data/stdlib/rdoc/0/code_object.rbs +55 -0
  120. data/stdlib/rdoc/0/comment.rbs +60 -0
  121. data/stdlib/rdoc/0/context.rbs +153 -0
  122. data/stdlib/rdoc/0/markup.rbs +119 -0
  123. data/stdlib/rdoc/0/parser.rbs +56 -0
  124. data/stdlib/rdoc/0/rdoc.rbs +0 -372
  125. data/stdlib/rdoc/0/ri.rbs +17 -0
  126. data/stdlib/rdoc/0/store.rbs +48 -0
  127. data/stdlib/rdoc/0/top_level.rbs +97 -0
  128. data/stdlib/socket/0/basic_socket.rbs +1 -1
  129. data/stdlib/socket/0/socket.rbs +1 -1
  130. data/stdlib/uri/0/common.rbs +1 -1
  131. data/stdlib/yaml/0/manifest.yaml +1 -2
  132. data/stdlib/yaml/0/yaml.rbs +1 -199
  133. metadata +49 -7
  134. data/sig/shims/pp.rbs +0 -3
  135. data/sig/shims.rbs +0 -47
@@ -1,26 +1,83 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'runtime/helpers'
4
+ require_relative 'runtime/value_object_generator'
5
+ require_relative 'runtime/reflection'
6
+
3
7
  module RBS
4
8
  module Prototype
5
9
  class Runtime
6
- include Helpers
10
+ class Todo
11
+ def initialize(builder:)
12
+ @builder = builder
13
+ end
14
+
15
+ def skip_mixin?(type_name:, module_name:, mixin_class:)
16
+ return false unless @builder.env.module_class_entry(type_name.absolute!)
17
+ return false unless @builder.env.module_class_entry(module_name.absolute!)
18
+
19
+ mixin_decls(type_name).any? do |decl|
20
+ decl.instance_of?(mixin_class) && decl.name == module_name.absolute!
21
+ end
22
+ end
23
+
24
+ def skip_singleton_method?(module_name:, method:, accessibility:)
25
+ return false unless @builder.env.module_class_entry(module_name.absolute!)
26
+
27
+ method_definition = @builder.build_singleton(module_name.absolute!).methods[method.name]
28
+ return false unless method_definition
29
+
30
+ method_definition.accessibility == accessibility
31
+ end
32
+
33
+ def skip_instance_method?(module_name:, method:, accessibility:)
34
+ return false unless @builder.env.module_class_entry(module_name.absolute!)
35
+
36
+ method_definition = @builder.build_instance(module_name.absolute!).methods[method.name]
37
+ return false unless method_definition
38
+
39
+ method_definition.accessibility == accessibility
40
+ end
41
+
42
+ def skip_constant?(module_name:, name:)
43
+ namespace = Namespace.new(path: module_name.split('::').map(&:to_sym), absolute: true)
44
+ @builder.env.constant_decl?(TypeName.new(namespace: namespace, name: name))
45
+ end
46
+
47
+ private
48
+
49
+ def mixin_decls(type_name)
50
+ type_name_absolute = type_name.absolute!
51
+ (@mixin_decls_cache ||= {}).fetch(type_name_absolute) do
52
+ @mixin_decls_cache[type_name_absolute] = @builder.env.class_decls[type_name_absolute].decls.flat_map do |d|
53
+ d.decl.members.select { |m| m.kind_of?(AST::Members::Mixin) }
54
+ end
55
+ end
56
+ end
57
+ end
58
+ private_constant :Todo
59
+
60
+ include Prototype::Helpers
61
+ include Runtime::Helpers
7
62
 
8
63
  attr_reader :patterns
9
64
  attr_reader :env
10
65
  attr_reader :merge
66
+ attr_reader :todo
11
67
  attr_reader :owners_included
12
68
  attr_accessor :outline
13
69
 
14
- def initialize(patterns:, env:, merge:, owners_included: [])
70
+ def initialize(patterns:, env:, merge:, todo: false, owners_included: [])
15
71
  @patterns = patterns
16
72
  @decls = nil
17
- @modules = []
73
+ @modules = {}
18
74
  @env = env
19
75
  @merge = merge
20
76
  @owners_included = owners_included.map do |name|
21
77
  Object.const_get(name)
22
78
  end
23
79
  @outline = false
80
+ @todo = todo
24
81
  end
25
82
 
26
83
  def target?(const)
@@ -36,6 +93,10 @@ module RBS
36
93
  end
37
94
  end
38
95
 
96
+ def todo_object
97
+ @todo_object ||= Todo.new(builder: builder) if todo
98
+ end
99
+
39
100
  def builder
40
101
  @builder ||= DefinitionBuilder.new(env: env)
41
102
  end
@@ -47,8 +108,11 @@ module RBS
47
108
  def decls
48
109
  unless @decls
49
110
  @decls = []
50
- @modules = ObjectSpace.each_object(Module).to_a
51
- @modules.select {|mod| target?(mod) }.sort_by{|mod| const_name(mod) }.each do |mod|
111
+ @modules = ObjectSpace.each_object(Module)
112
+ .map { |mod| [const_name(mod), mod] }
113
+ .select { |name, _| name }
114
+ .to_h
115
+ @modules.select { |name, mod| target?(mod) }.sort_by { |name, _| name }.each do |_, mod|
52
116
  case mod
53
117
  when Class
54
118
  generate_class mod
@@ -58,48 +122,46 @@ module RBS
58
122
  end
59
123
  end
60
124
 
61
- @decls
125
+ @decls or raise
62
126
  end
63
127
 
64
- def to_type_name(name, full_name: false)
65
- *prefix, last = name.split(/::/)
66
-
67
- if full_name
68
- if prefix.empty?
69
- TypeName.new(name: last.to_sym, namespace: Namespace.empty)
70
- else
71
- TypeName.new(name: last.to_sym, namespace: Namespace.parse(prefix.join("::")))
72
- end
73
- else
74
- TypeName.new(name: last.to_sym, namespace: Namespace.empty)
128
+ private def each_mixined_module(type_name, mod)
129
+ each_mixined_module_one(type_name, mod) do |module_name, module_full_name, is_prepend|
130
+ yield module_name, module_full_name, is_prepend ? AST::Members::Prepend : AST::Members::Include
131
+ end
132
+ each_mixined_module_one(type_name, mod.singleton_class) do |module_name, module_full_name, _|
133
+ yield module_name, module_full_name, AST::Members::Extend
75
134
  end
76
135
  end
77
136
 
78
- def each_included_module(type_name, mod)
79
- supers = Set[]
137
+ private def each_mixined_module_one(type_name, mod)
138
+ supers = Set[] #: Set[Module]
139
+ prepends = mod.ancestors.take_while { |m| !mod.equal?(m) }.to_set
80
140
 
81
141
  mod.included_modules.each do |mix|
82
142
  supers.merge(mix.included_modules)
83
143
  end
84
144
 
85
- if mod.is_a?(Class) && mod.superclass
86
- mod.superclass.included_modules.each do |mix|
87
- supers << mix
88
- supers.merge(mix.included_modules)
145
+ if mod.is_a?(Class)
146
+ if superclass = mod.superclass
147
+ superclass.included_modules.each do |mix|
148
+ supers << mix
149
+ supers.merge(mix.included_modules)
150
+ end
89
151
  end
90
152
  end
91
153
 
92
- mod.included_modules.each do |mix|
93
- unless supers.include?(mix)
154
+ mod.included_modules.uniq.each do |mix|
155
+ if !supers.include?(mix) || prepends.include?(mix)
94
156
  unless const_name(mix)
95
157
  RBS.logger.warn("Skipping anonymous module #{mix} included in #{mod}")
96
158
  else
97
- module_name = module_full_name = to_type_name(const_name(mix), full_name: true)
159
+ module_name = module_full_name = to_type_name(const_name!(mix), full_name: true)
98
160
  if module_full_name.namespace == type_name.namespace
99
161
  module_name = TypeName.new(name: module_full_name.name, namespace: Namespace.empty)
100
162
  end
101
163
 
102
- yield module_name, module_full_name, mix
164
+ yield module_name, module_full_name, prepends.include?(mix)
103
165
  end
104
166
  end
105
167
  end
@@ -108,19 +170,19 @@ module RBS
108
170
  def method_type(method)
109
171
  untyped = Types::Bases::Any.new(location: nil)
110
172
 
111
- required_positionals = []
112
- optional_positionals = []
113
- rest = nil
114
- trailing_positionals = []
115
- required_keywords = {}
116
- optional_keywords = {}
117
- rest_keywords = nil
173
+ required_positionals = [] #: Array[Types::Function::Param]
174
+ optional_positionals = [] #: Array[Types::Function::Param]
175
+ rest = nil #: Types::Function::Param?
176
+ trailing_positionals = [] #: Array[Types::Function::Param]
177
+ required_keywords = {} #: Hash[Symbol, Types::Function::Param]
178
+ optional_keywords = {} #: Hash[Symbol, Types::Function::Param]
179
+ rest_keywords = nil #: Types::Function::Param?
118
180
 
119
181
  requireds = required_positionals
120
182
 
121
- block = nil
183
+ block = nil #: Types::Block?
122
184
 
123
- method.parameters.each do |kind, name|
185
+ method.parameters.each do |(kind, name)|
124
186
  case kind
125
187
  when :req
126
188
  requireds << Types::Function::Param.new(name: name, type: untyped)
@@ -132,8 +194,10 @@ module RBS
132
194
  name = nil if name == :* # For `def f(...) end` syntax
133
195
  rest = Types::Function::Param.new(name: name, type: untyped)
134
196
  when :keyreq
197
+ name or raise
135
198
  required_keywords[name] = Types::Function::Param.new(name: nil, type: untyped)
136
199
  when :key
200
+ name or raise
137
201
  optional_keywords[name] = Types::Function::Param.new(name: nil, type: untyped)
138
202
  when :keyrest
139
203
  rest_keywords = Types::Function::Param.new(name: nil, type: untyped)
@@ -175,6 +239,7 @@ module RBS
175
239
  def merge_rbs(module_name, members, instance: nil, singleton: nil)
176
240
  if merge
177
241
  if env.class_decls[module_name.absolute!]
242
+ # @type var kind: AST::Members::MethodDefinition::kind
178
243
  case
179
244
  when instance
180
245
  method = builder.build_instance(module_name.absolute!).methods[instance]
@@ -194,6 +259,7 @@ module RBS
194
259
  annotations: [],
195
260
  method_type: type.update.tap do |ty|
196
261
  def ty.to_s
262
+ location or raise
197
263
  location.source
198
264
  end
199
265
  end
@@ -224,14 +290,27 @@ module RBS
224
290
  when singleton
225
291
  method = mod.singleton_class.instance_method(singleton)
226
292
  method.owner == mod.singleton_class || owners_included.any? {|m| method.owner == m.singleton_class }
293
+ else
294
+ raise
227
295
  end
228
296
  end
229
297
 
230
298
  def generate_methods(mod, module_name, members)
299
+ module_name_absolute = to_type_name(const_name!(mod), full_name: true).absolute!
231
300
  mod.singleton_methods.select {|name| target_method?(mod, singleton: name) }.sort.each do |name|
232
301
  method = mod.singleton_class.instance_method(name)
302
+ next if todo_object&.skip_singleton_method?(module_name: module_name_absolute, method: method, accessibility: :public)
233
303
 
234
- if method.name == method.original_name
304
+ if can_alias?(mod.singleton_class, method)
305
+ members << AST::Members::Alias.new(
306
+ new_name: method.name,
307
+ old_name: method.original_name,
308
+ kind: :singleton,
309
+ location: nil,
310
+ comment: nil,
311
+ annotations: [],
312
+ )
313
+ else
235
314
  merge_rbs(module_name, members, singleton: name) do
236
315
  RBS.logger.info "missing #{module_name}.#{name} #{method.source_location}"
237
316
 
@@ -248,15 +327,6 @@ module RBS
248
327
  visibility: nil
249
328
  )
250
329
  end
251
- else
252
- members << AST::Members::Alias.new(
253
- new_name: method.name,
254
- old_name: method.original_name,
255
- kind: :singleton,
256
- location: nil,
257
- comment: nil,
258
- annotations: [],
259
- )
260
330
  end
261
331
  end
262
332
 
@@ -266,8 +336,18 @@ module RBS
266
336
 
267
337
  public_instance_methods.sort.each do |name|
268
338
  method = mod.instance_method(name)
339
+ next if todo_object&.skip_instance_method?(module_name: module_name_absolute, method: method, accessibility: :public)
269
340
 
270
- if method.name == method.original_name
341
+ if can_alias?(mod, method)
342
+ members << AST::Members::Alias.new(
343
+ new_name: method.name,
344
+ old_name: method.original_name,
345
+ kind: :instance,
346
+ location: nil,
347
+ comment: nil,
348
+ annotations: [],
349
+ )
350
+ else
271
351
  merge_rbs(module_name, members, instance: name) do
272
352
  RBS.logger.info "missing #{module_name}##{name} #{method.source_location}"
273
353
 
@@ -284,27 +364,30 @@ module RBS
284
364
  visibility: nil
285
365
  )
286
366
  end
287
- else
288
- members << AST::Members::Alias.new(
289
- new_name: method.name,
290
- old_name: method.original_name,
291
- kind: :instance,
292
- location: nil,
293
- comment: nil,
294
- annotations: [],
295
- )
296
367
  end
297
368
  end
298
369
  end
299
370
 
300
371
  private_instance_methods = mod.private_instance_methods.select {|name| target_method?(mod, instance: name) }
301
372
  unless private_instance_methods.empty?
373
+ added = false
302
374
  members << AST::Members::Private.new(location: nil)
303
375
 
304
376
  private_instance_methods.sort.each do |name|
305
377
  method = mod.instance_method(name)
378
+ next if todo_object&.skip_instance_method?(module_name: module_name_absolute, method: method, accessibility: :private)
306
379
 
307
- if method.name == method.original_name
380
+ added = true
381
+ if can_alias?(mod, method)
382
+ members << AST::Members::Alias.new(
383
+ new_name: method.name,
384
+ old_name: method.original_name,
385
+ kind: :instance,
386
+ location: nil,
387
+ comment: nil,
388
+ annotations: [],
389
+ )
390
+ else
308
391
  merge_rbs(module_name, members, instance: name) do
309
392
  RBS.logger.info "missing #{module_name}##{name} #{method.source_location}"
310
393
 
@@ -321,22 +404,28 @@ module RBS
321
404
  visibility: nil
322
405
  )
323
406
  end
324
- else
325
- members << AST::Members::Alias.new(
326
- new_name: method.name,
327
- old_name: method.original_name,
328
- kind: :instance,
329
- location: nil,
330
- comment: nil,
331
- annotations: [],
332
- )
333
407
  end
334
408
  end
409
+
410
+ members.pop unless added
411
+ end
412
+ end
413
+
414
+ private def can_alias?(mod, method)
415
+ return false if method.name == method.original_name
416
+
417
+ begin
418
+ mod.instance_method(method.original_name) && true
419
+ rescue NameError
420
+ false
335
421
  end
336
422
  end
337
423
 
338
424
  def generate_constants(mod, decls)
339
- mod.constants(false).sort.each do |name|
425
+ module_name = const_name!(mod)
426
+ Reflection.constants_of(mod, false).sort.each do |name|
427
+ next if todo_object&.skip_constant?(module_name: module_name, name: name)
428
+
340
429
  begin
341
430
  value = mod.const_get(name)
342
431
  rescue StandardError, LoadError => e
@@ -344,8 +433,10 @@ module RBS
344
433
  next
345
434
  end
346
435
 
347
- next if value.is_a?(Class) || value.is_a?(Module)
348
- unless value.class.name
436
+ next if Reflection.object_class(value).equal?(Class)
437
+ next if Reflection.object_class(value).equal?(Module)
438
+
439
+ unless Reflection.object_class(value).name
349
440
  RBS.logger.warn("Skipping constant #{name} #{value} of #{mod} as an instance of anonymous class")
350
441
  next
351
442
  end
@@ -358,8 +449,12 @@ module RBS
358
449
  type: Types::Bases::Any.new(location: nil),
359
450
  location: nil
360
451
  )
452
+ when ARGF
453
+ Types::ClassInstance.new(name: TypeName("::RBS::Unnamed::ARGFClass"), args: [], location: nil)
454
+ when ENV
455
+ Types::ClassInstance.new(name: TypeName("::RBS::Unnamed::ENVClass"), args: [], location: nil)
361
456
  else
362
- value_type_name = to_type_name(const_name(value.class))
457
+ value_type_name = to_type_name(const_name!(Reflection.object_class(value)), full_name: true).absolute!
363
458
  args = type_args(value_type_name)
364
459
  Types::ClassInstance.new(name: value_type_name, args: args, location: nil)
365
460
  end
@@ -374,62 +469,56 @@ module RBS
374
469
  end
375
470
 
376
471
  def generate_super_class(mod)
377
- if mod.superclass.nil? || mod.superclass == ::Object
472
+ superclass = mod.superclass
473
+
474
+ if superclass.nil? || superclass == ::Object
378
475
  nil
379
- elsif const_name(mod.superclass).nil?
380
- RBS.logger.warn("Skipping anonymous superclass #{mod.superclass} of #{mod}")
476
+ elsif const_name(superclass).nil?
477
+ RBS.logger.warn("Skipping anonymous superclass #{superclass} of #{mod}")
381
478
  nil
382
479
  else
383
- super_name = to_type_name(const_name(mod.superclass), full_name: true).absolute!
480
+ super_name = to_type_name(const_name!(superclass), full_name: true).absolute!
384
481
  super_args = type_args(super_name)
385
482
  AST::Declarations::Class::Super.new(name: super_name, args: super_args, location: nil)
386
483
  end
387
484
  end
388
485
 
389
486
  def generate_class(mod)
390
- type_name = to_type_name(const_name(mod))
487
+ type_name_absolute = to_type_name(const_name!(mod), full_name: true).absolute!
488
+ type_name = to_type_name(const_name!(mod))
391
489
  outer_decls = ensure_outer_module_declarations(mod)
392
490
 
393
491
  # Check if a declaration exists for the actual module
394
- decl = outer_decls.detect { |decl| decl.is_a?(AST::Declarations::Class) && decl.name.name == only_name(mod).to_sym }
492
+ decl = outer_decls.detect do |decl|
493
+ decl.is_a?(AST::Declarations::Class) && decl.name.name == only_name(mod).to_sym
494
+ end #: AST::Declarations::Class?
495
+
395
496
  unless decl
396
- decl = AST::Declarations::Class.new(
397
- name: to_type_name(only_name(mod)),
398
- type_params: type_params(mod),
399
- super_class: generate_super_class(mod),
400
- members: [],
401
- annotations: [],
402
- location: nil,
403
- comment: nil
404
- )
497
+ if StructGenerator.generatable?(mod)
498
+ decl = StructGenerator.new(mod).build_decl
499
+ elsif DataGenerator.generatable?(mod)
500
+ decl = DataGenerator.new(mod).build_decl
501
+ else
502
+ decl = AST::Declarations::Class.new(
503
+ name: to_type_name(only_name(mod)),
504
+ type_params: type_params(mod),
505
+ super_class: generate_super_class(mod),
506
+ members: [],
507
+ annotations: [],
508
+ location: nil,
509
+ comment: nil
510
+ )
511
+ end
405
512
 
406
513
  outer_decls << decl
407
514
  end
408
515
 
409
- each_included_module(type_name, mod) do |module_name, module_full_name, _|
410
- args = type_args(module_full_name)
411
- decl.members << AST::Members::Include.new(
412
- name: module_name,
413
- args: args,
414
- location: nil,
415
- comment: nil,
416
- annotations: []
417
- )
418
- end
516
+ generate_mixin(mod, decl, type_name, type_name_absolute)
419
517
 
420
- each_included_module(type_name, mod.singleton_class) do |module_name, module_full_name ,_|
421
- args = type_args(module_full_name)
422
- decl.members << AST::Members::Extend.new(
423
- name: module_name,
424
- args: args,
425
- location: nil,
426
- comment: nil,
427
- annotations: []
428
- )
518
+ unless mod < Struct || (RUBY_VERSION >= '3.2' && mod < Data)
519
+ generate_methods(mod, type_name, decl.members) unless outline
429
520
  end
430
521
 
431
- generate_methods(mod, type_name, decl.members) unless outline
432
-
433
522
  generate_constants mod, decl.members
434
523
  end
435
524
 
@@ -441,11 +530,15 @@ module RBS
441
530
  return
442
531
  end
443
532
 
533
+ type_name_absolute = to_type_name(name, full_name: true).absolute!
444
534
  type_name = to_type_name(name)
445
535
  outer_decls = ensure_outer_module_declarations(mod)
446
536
 
447
537
  # Check if a declaration exists for the actual class
448
- decl = outer_decls.detect { |decl| decl.is_a?(AST::Declarations::Module) && decl.name.name == only_name(mod).to_sym }
538
+ decl = outer_decls.detect do |decl|
539
+ decl.is_a?(AST::Declarations::Module) && decl.name.name == only_name(mod).to_sym
540
+ end #: AST::Declarations::Module?
541
+
449
542
  unless decl
450
543
  decl = AST::Declarations::Module.new(
451
544
  name: to_type_name(only_name(mod)),
@@ -460,20 +553,19 @@ module RBS
460
553
  outer_decls << decl
461
554
  end
462
555
 
463
- each_included_module(type_name, mod) do |module_name, module_full_name, _|
464
- args = type_args(module_full_name)
465
- decl.members << AST::Members::Include.new(
466
- name: module_name,
467
- args: args,
468
- location: nil,
469
- comment: nil,
470
- annotations: []
471
- )
472
- end
556
+ generate_mixin(mod, decl, type_name, type_name_absolute)
557
+
558
+ generate_methods(mod, type_name, decl.members) unless outline
559
+
560
+ generate_constants mod, decl.members
561
+ end
562
+
563
+ def generate_mixin(mod, decl, type_name, type_name_absolute)
564
+ each_mixined_module(type_name, mod) do |module_name, module_full_name, mixin_class|
565
+ next if todo_object&.skip_mixin?(type_name: type_name_absolute, module_name: module_full_name, mixin_class: mixin_class)
473
566
 
474
- each_included_module(type_name, mod.singleton_class) do |module_name, module_full_name, _|
475
567
  args = type_args(module_full_name)
476
- decl.members << AST::Members::Extend.new(
568
+ decl.members << mixin_class.new(
477
569
  name: module_name,
478
570
  args: args,
479
571
  location: nil,
@@ -481,26 +573,33 @@ module RBS
481
573
  annotations: []
482
574
  )
483
575
  end
484
-
485
- generate_methods(mod, type_name, decl.members) unless outline
486
-
487
- generate_constants mod, decl.members
488
576
  end
489
577
 
490
578
  # Generate/find outer module declarations
491
579
  # This is broken down into another method to comply with `DRY`
492
580
  # This generates/finds declarations in nested form & returns the last array of declarations
493
581
  def ensure_outer_module_declarations(mod)
494
- *outer_module_names, _ = const_name(mod).split(/::/) #=> parent = [A, B], mod = C
495
- destination = @decls # Copy the entries in ivar @decls, not .dup
582
+ # @type var outer_module_names: Array[String]
583
+ *outer_module_names, _ = const_name!(mod).split(/::/) #=> parent = [A, B], mod = C
584
+ # Copy the entries in ivar @decls, not .dup
585
+ destination = @decls || [] #: Array[AST::Declarations::Class::member]
496
586
 
497
587
  outer_module_names&.each_with_index do |outer_module_name, i|
498
- current_name = outer_module_names[0, i + 1].join('::')
499
- outer_module = @modules.detect { |x| const_name(x) == current_name }
500
- outer_decl = destination.detect { |decl| decl.is_a?(outer_module.is_a?(Class) ? AST::Declarations::Class : AST::Declarations::Module) && decl.name.name == outer_module_name.to_sym }
588
+ current_name = outer_module_names.take(i+1).join('::')
589
+ outer_module = @modules[current_name]
590
+ outer_decl = destination.detect do |decl|
591
+ case outer_module
592
+ when Class
593
+ decl.is_a?(AST::Declarations::Class) && decl.name.name == outer_module_name.to_sym
594
+ when Module
595
+ decl.is_a?(AST::Declarations::Module) && decl.name.name == outer_module_name.to_sym
596
+ end
597
+ end #: AST::Declarations::Class | AST::Declarations::Module | nil
501
598
 
502
599
  # Insert AST::Declarations if declarations are not added previously
503
600
  unless outer_decl
601
+ outer_module or raise
602
+
504
603
  if outer_module.is_a?(Class)
505
604
  outer_decl = AST::Declarations::Class.new(
506
605
  name: to_type_name(outer_module_name),
@@ -533,37 +632,16 @@ module RBS
533
632
  destination
534
633
  end
535
634
 
536
- # Returns the exact name & not compactly declared name
537
- def only_name(mod)
538
- # No nil check because this method is invoked after checking if the module exists
539
- const_name(mod).split(/::/).last # (A::B::C) => C
540
- end
541
-
542
- def const_name(const)
543
- @module_name_method ||= Module.instance_method(:name)
544
- name = @module_name_method.bind(const).call
545
- return nil unless name
546
-
547
- begin
548
- Object.const_get(name)
549
- rescue NameError
550
- # Should generate const name if anonymous or internal module (e.g. NameError::message)
551
- nil
552
- else
553
- name
554
- end
555
- end
556
-
557
635
  def type_args(type_name)
558
- if class_decl = env.class_decls[type_name.absolute!]
559
- class_decl.type_params.size.times.map { :untyped }
636
+ if class_decl = env.class_decls.fetch(type_name.absolute!, nil)
637
+ class_decl.type_params.size.times.map { Types::Bases::Any.new(location: nil) }
560
638
  else
561
639
  []
562
640
  end
563
641
  end
564
642
 
565
643
  def type_params(mod)
566
- type_name = to_type_name(const_name(mod), full_name: true)
644
+ type_name = to_type_name(const_name!(mod), full_name: true)
567
645
  if class_decl = env.class_decls[type_name.absolute!]
568
646
  class_decl.type_params
569
647
  else
@@ -580,7 +658,9 @@ module RBS
580
658
  return # When the method is defined in eval
581
659
  end
582
660
 
583
- block_from_body(ast) if ast&.type == :SCOPE
661
+ if ast && ast.type == :SCOPE
662
+ block_from_body(ast)
663
+ end
584
664
  end
585
665
  end
586
666
  end
@@ -22,7 +22,7 @@ module RBS
22
22
 
23
23
  unless name.namespace.empty?
24
24
  parent = name.namespace.to_type_name
25
- table = children_table[parent] or raise
25
+ table = children_table[parent] or raise "#{parent} not found by #{name}"
26
26
  else
27
27
  table = toplevel
28
28
  end