rbs 3.2.2 → 3.3.0.pre.1

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