rbs 3.2.2 → 3.3.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
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