rbi 0.1.14 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3705c571d4b2685e60fec1c0dc54435caed79ba988239006be0bf14757790c51
4
- data.tar.gz: 4560dc122385781dd604cdc4ca57835caa22e3f29b2cafa5b7e2e468032c5923
3
+ metadata.gz: 8bcb914ddfe3208193a252f650ac6bcbc25c741efa183d28876ad1f0957cd24f
4
+ data.tar.gz: db2f129f6925c498e6112e43a7fc44b9a4a6aeb694cd18e97e64e3531bfe7ae4
5
5
  SHA512:
6
- metadata.gz: 3f70d57182bed826c64ca53ed2d62a1da0aeb0dee1badbe774ed00c8bd505b8e40f00363c4ca069efef457649cff19ce6b2be595e6dca453e56456eb4580ca38
7
- data.tar.gz: 5c60fedeeb8995f9e6ed4ef926f68870ed88021de20e60294e1aec97029c728f24d098a8d297ec967dbfc23c31788dbb30d82b8f925f1c95962df7772580c294
6
+ metadata.gz: 0def2a8d159eba09b59cbd403126a4b198687f018c65acec3d35cfa978d25da1bc97956ccb2d017d81ece08fe8e1f65e06b0ed4968b60fcb3b3e4b5cb497cdfe
7
+ data.tar.gz: 7f065932016677c397967f1dc16ca5115d8279ec65d00962e850496f616c16f76954e334611a66132cdeeea889866f5c41ffd2089ee5f9cdf473d77211cbfd80
data/Gemfile CHANGED
@@ -14,5 +14,5 @@ group(:development, :test) do
14
14
  gem("rubocop-shopify", require: false)
15
15
  gem("rubocop-sorbet", require: false)
16
16
  gem("sorbet", ">= 0.5.9204", require: false)
17
- gem("tapioca", require: false)
17
+ gem("tapioca", github: "Shopify/tapioca", branch: "at-bump-rbi", require: false)
18
18
  end
data/lib/rbi/formatter.rb CHANGED
@@ -17,7 +17,7 @@ module RBI
17
17
  group_nodes: T::Boolean,
18
18
  max_line_length: T.nilable(Integer),
19
19
  nest_singleton_methods: T::Boolean,
20
- nest_non_public_methods: T::Boolean,
20
+ nest_non_public_members: T::Boolean,
21
21
  sort_nodes: T::Boolean,
22
22
  ).void
23
23
  end
@@ -26,14 +26,14 @@ module RBI
26
26
  group_nodes: false,
27
27
  max_line_length: nil,
28
28
  nest_singleton_methods: false,
29
- nest_non_public_methods: false,
29
+ nest_non_public_members: false,
30
30
  sort_nodes: false
31
31
  )
32
32
  @add_sig_templates = add_sig_templates
33
33
  @group_nodes = group_nodes
34
34
  @max_line_length = max_line_length
35
35
  @nest_singleton_methods = nest_singleton_methods
36
- @nest_non_public_methods = nest_non_public_methods
36
+ @nest_non_public_members = nest_non_public_members
37
37
  @sort_nodes = sort_nodes
38
38
  end
39
39
 
@@ -52,7 +52,7 @@ module RBI
52
52
  def format_tree(tree)
53
53
  tree.add_sig_templates! if @add_sig_templates
54
54
  tree.nest_singleton_methods! if @nest_singleton_methods
55
- tree.nest_non_public_methods! if @nest_non_public_methods
55
+ tree.nest_non_public_members! if @nest_non_public_members
56
56
  tree.group_nodes! if @group_nodes
57
57
  tree.sort_nodes! if @sort_nodes
58
58
  end
data/lib/rbi/model.rb CHANGED
@@ -574,7 +574,7 @@ module RBI
574
574
  sig do
575
575
  params(
576
576
  params: T::Array[SigParam],
577
- return_type: T.nilable(String),
577
+ return_type: T.any(String, Type),
578
578
  is_abstract: T::Boolean,
579
579
  is_override: T::Boolean,
580
580
  is_overridable: T::Boolean,
@@ -586,7 +586,7 @@ module RBI
586
586
  end
587
587
  def add_sig(
588
588
  params: [],
589
- return_type: nil,
589
+ return_type: "void",
590
590
  is_abstract: false,
591
591
  is_override: false,
592
592
  is_overridable: false,
@@ -928,8 +928,10 @@ module RBI
928
928
  @visibility = visibility
929
929
  end
930
930
 
931
- sig { params(other: Visibility).returns(T::Boolean) }
931
+ sig { params(other: T.nilable(Object)).returns(T::Boolean) }
932
932
  def ==(other)
933
+ return false unless other.is_a?(Visibility)
934
+
933
935
  visibility == other.visibility
934
936
  end
935
937
 
@@ -1099,13 +1101,13 @@ module RBI
1099
1101
 
1100
1102
  # Sorbet's sigs
1101
1103
 
1102
- class Sig < Node
1104
+ class Sig < NodeWithComments
1103
1105
  extend T::Sig
1104
1106
 
1105
1107
  sig { returns(T::Array[SigParam]) }
1106
1108
  attr_reader :params
1107
1109
 
1108
- sig { returns(T.nilable(String)) }
1110
+ sig { returns(T.any(Type, String)) }
1109
1111
  attr_accessor :return_type
1110
1112
 
1111
1113
  sig { returns(T::Boolean) }
@@ -1120,7 +1122,7 @@ module RBI
1120
1122
  sig do
1121
1123
  params(
1122
1124
  params: T::Array[SigParam],
1123
- return_type: T.nilable(String),
1125
+ return_type: T.any(Type, String),
1124
1126
  is_abstract: T::Boolean,
1125
1127
  is_override: T::Boolean,
1126
1128
  is_overridable: T::Boolean,
@@ -1128,12 +1130,13 @@ module RBI
1128
1130
  type_params: T::Array[String],
1129
1131
  checked: T.nilable(Symbol),
1130
1132
  loc: T.nilable(Loc),
1133
+ comments: T::Array[Comment],
1131
1134
  block: T.nilable(T.proc.params(node: Sig).void),
1132
1135
  ).void
1133
1136
  end
1134
1137
  def initialize(
1135
1138
  params: [],
1136
- return_type: nil,
1139
+ return_type: "void",
1137
1140
  is_abstract: false,
1138
1141
  is_override: false,
1139
1142
  is_overridable: false,
@@ -1141,9 +1144,10 @@ module RBI
1141
1144
  type_params: [],
1142
1145
  checked: nil,
1143
1146
  loc: nil,
1147
+ comments: [],
1144
1148
  &block
1145
1149
  )
1146
- super(loc: loc)
1150
+ super(loc: loc, comments: comments)
1147
1151
  @params = params
1148
1152
  @return_type = return_type
1149
1153
  @is_abstract = is_abstract
@@ -1160,7 +1164,7 @@ module RBI
1160
1164
  @params << param
1161
1165
  end
1162
1166
 
1163
- sig { params(name: String, type: String).void }
1167
+ sig { params(name: String, type: T.any(Type, String)).void }
1164
1168
  def add_param(name, type)
1165
1169
  @params << SigParam.new(name, type)
1166
1170
  end
@@ -1169,7 +1173,7 @@ module RBI
1169
1173
  def ==(other)
1170
1174
  return false unless other.is_a?(Sig)
1171
1175
 
1172
- params == other.params && return_type == other.return_type && is_abstract == other.is_abstract &&
1176
+ params == other.params && return_type.to_s == other.return_type.to_s && is_abstract == other.is_abstract &&
1173
1177
  is_override == other.is_override && is_overridable == other.is_overridable && is_final == other.is_final &&
1174
1178
  type_params == other.type_params && checked == other.checked
1175
1179
  end
@@ -1179,12 +1183,15 @@ module RBI
1179
1183
  extend T::Sig
1180
1184
 
1181
1185
  sig { returns(String) }
1182
- attr_reader :name, :type
1186
+ attr_reader :name
1187
+
1188
+ sig { returns(T.any(Type, String)) }
1189
+ attr_reader :type
1183
1190
 
1184
1191
  sig do
1185
1192
  params(
1186
1193
  name: String,
1187
- type: String,
1194
+ type: T.any(Type, String),
1188
1195
  loc: T.nilable(Loc),
1189
1196
  comments: T::Array[Comment],
1190
1197
  block: T.nilable(T.proc.params(node: SigParam).void),
@@ -1199,7 +1206,7 @@ module RBI
1199
1206
 
1200
1207
  sig { params(other: Object).returns(T::Boolean) }
1201
1208
  def ==(other)
1202
- other.is_a?(SigParam) && name == other.name && type == other.type
1209
+ other.is_a?(SigParam) && name == other.name && type.to_s == other.type.to_s
1203
1210
  end
1204
1211
  end
1205
1212
 
@@ -1229,7 +1236,10 @@ module RBI
1229
1236
  abstract!
1230
1237
 
1231
1238
  sig { returns(String) }
1232
- attr_accessor :name, :type
1239
+ attr_accessor :name
1240
+
1241
+ sig { returns(T.any(Type, String)) }
1242
+ attr_accessor :type
1233
1243
 
1234
1244
  sig { returns(T.nilable(String)) }
1235
1245
  attr_accessor :default
@@ -1237,7 +1247,7 @@ module RBI
1237
1247
  sig do
1238
1248
  params(
1239
1249
  name: String,
1240
- type: String,
1250
+ type: T.any(Type, String),
1241
1251
  default: T.nilable(String),
1242
1252
  loc: T.nilable(Loc),
1243
1253
  comments: T::Array[Comment],
@@ -1260,7 +1270,7 @@ module RBI
1260
1270
  sig do
1261
1271
  params(
1262
1272
  name: String,
1263
- type: String,
1273
+ type: T.any(Type, String),
1264
1274
  default: T.nilable(String),
1265
1275
  loc: T.nilable(Loc),
1266
1276
  comments: T::Array[Comment],
@@ -1290,7 +1300,7 @@ module RBI
1290
1300
  sig do
1291
1301
  params(
1292
1302
  name: String,
1293
- type: String,
1303
+ type: T.any(Type, String),
1294
1304
  default: T.nilable(String),
1295
1305
  loc: T.nilable(Loc),
1296
1306
  comments: T::Array[Comment],
@@ -1333,39 +1343,29 @@ module RBI
1333
1343
  end
1334
1344
  end
1335
1345
 
1336
- class TEnumBlock < NodeWithComments
1346
+ class TEnumBlock < Scope
1337
1347
  extend T::Sig
1338
1348
 
1339
- sig { returns(T::Array[String]) }
1340
- attr_reader :names
1341
-
1342
1349
  sig do
1343
1350
  params(
1344
- names: T::Array[String],
1345
1351
  loc: T.nilable(Loc),
1346
1352
  comments: T::Array[Comment],
1347
1353
  block: T.nilable(T.proc.params(node: TEnumBlock).void),
1348
1354
  ).void
1349
1355
  end
1350
- def initialize(names = [], loc: nil, comments: [], &block)
1351
- super(loc: loc, comments: comments)
1352
- @names = names
1356
+ def initialize(loc: nil, comments: [], &block)
1357
+ super(loc: loc, comments: comments) {}
1353
1358
  block&.call(self)
1354
1359
  end
1355
1360
 
1356
- sig { returns(T::Boolean) }
1357
- def empty?
1358
- names.empty?
1359
- end
1360
-
1361
- sig { params(name: String).void }
1362
- def <<(name)
1363
- @names << name
1361
+ sig { override.returns(String) }
1362
+ def fully_qualified_name
1363
+ "#{parent_scope&.fully_qualified_name}.enums"
1364
1364
  end
1365
1365
 
1366
1366
  sig { override.returns(String) }
1367
1367
  def to_s
1368
- "#{parent_scope&.fully_qualified_name}.enums"
1368
+ fully_qualified_name
1369
1369
  end
1370
1370
  end
1371
1371
 
data/lib/rbi/parser.rb CHANGED
@@ -169,22 +169,38 @@ module RBI
169
169
  @scopes_stack = T.let([@tree], T::Array[Tree])
170
170
  @last_node = T.let(nil, T.nilable(Prism::Node))
171
171
  @last_sigs = T.let([], T::Array[RBI::Sig])
172
- @last_sigs_comments = T.let([], T::Array[Comment])
173
172
  end
174
173
 
175
174
  sig { override.params(node: Prism::ClassNode).void }
176
175
  def visit_class_node(node)
177
176
  @last_node = node
178
- scope = Class.new(
179
- node_string!(node.constant_path),
180
- superclass_name: node_string(node.superclass),
181
- loc: node_loc(node),
182
- comments: node_comments(node),
183
- )
177
+ superclass_name = node_string(node.superclass)
178
+ scope = case superclass_name
179
+ when /^(::)?T::Struct$/
180
+ TStruct.new(
181
+ node_string!(node.constant_path),
182
+ loc: node_loc(node),
183
+ comments: node_comments(node),
184
+ )
185
+ when /^(::)?T::Enum$/
186
+ TEnum.new(
187
+ node_string!(node.constant_path),
188
+ loc: node_loc(node),
189
+ comments: node_comments(node),
190
+ )
191
+ else
192
+ Class.new(
193
+ node_string!(node.constant_path),
194
+ superclass_name: superclass_name,
195
+ loc: node_loc(node),
196
+ comments: node_comments(node),
197
+ )
198
+ end
184
199
 
185
200
  current_scope << scope
186
201
  @scopes_stack << scope
187
202
  visit(node.body)
203
+ scope.nodes.concat(current_sigs)
188
204
  collect_dangling_comments(node)
189
205
  @scopes_stack.pop
190
206
  @last_node = nil
@@ -240,12 +256,19 @@ module RBI
240
256
  sig { override.params(node: Prism::DefNode).void }
241
257
  def visit_def_node(node)
242
258
  @last_node = node
259
+
260
+ # We need to collect the comments with `current_sigs_comments` _before_ visiting the parameters to make sure
261
+ # the method comments are properly associated with the sigs and not the parameters.
262
+ sigs = current_sigs
263
+ comments = detach_comments_from_sigs(sigs) + node_comments(node)
264
+ params = parse_params(node.parameters)
265
+
243
266
  current_scope << Method.new(
244
267
  node.name.to_s,
245
- params: parse_params(node.parameters),
246
- sigs: current_sigs,
268
+ params: params,
269
+ sigs: sigs,
247
270
  loc: node_loc(node),
248
- comments: current_sigs_comments + node_comments(node),
271
+ comments: comments,
249
272
  is_singleton: !!node.receiver,
250
273
  )
251
274
  @last_node = nil
@@ -263,6 +286,7 @@ module RBI
263
286
  current_scope << scope
264
287
  @scopes_stack << scope
265
288
  visit(node.body)
289
+ scope.nodes.concat(current_sigs)
266
290
  collect_dangling_comments(node)
267
291
  @scopes_stack.pop
268
292
  @last_node = nil
@@ -272,7 +296,7 @@ module RBI
272
296
  def visit_program_node(node)
273
297
  @last_node = node
274
298
  super
275
-
299
+ @tree.nodes.concat(current_sigs)
276
300
  collect_orphan_comments
277
301
  separate_header_comments
278
302
  set_root_tree_loc
@@ -290,6 +314,7 @@ module RBI
290
314
  current_scope << scope
291
315
  @scopes_stack << scope
292
316
  visit(node.body)
317
+ scope.nodes.concat(current_sigs)
293
318
  collect_dangling_comments(node)
294
319
  @scopes_stack.pop
295
320
  @last_node = nil
@@ -314,11 +339,14 @@ module RBI
314
339
  return
315
340
  end
316
341
 
342
+ sigs = current_sigs
343
+ comments = detach_comments_from_sigs(sigs) + node_comments(node)
344
+
317
345
  current_scope << AttrReader.new(
318
346
  *T.unsafe(args.arguments.map { |arg| node_string!(arg).delete_prefix(":").to_sym }),
319
- sigs: current_sigs,
347
+ sigs: sigs,
320
348
  loc: node_loc(node),
321
- comments: current_sigs_comments + node_comments(node),
349
+ comments: comments,
322
350
  )
323
351
  when "attr_writer"
324
352
  args = node.arguments
@@ -328,11 +356,14 @@ module RBI
328
356
  return
329
357
  end
330
358
 
359
+ sigs = current_sigs
360
+ comments = detach_comments_from_sigs(sigs) + node_comments(node)
361
+
331
362
  current_scope << AttrWriter.new(
332
363
  *T.unsafe(args.arguments.map { |arg| node_string!(arg).delete_prefix(":").to_sym }),
333
- sigs: current_sigs,
364
+ sigs: sigs,
334
365
  loc: node_loc(node),
335
- comments: current_sigs_comments + node_comments(node),
366
+ comments: comments,
336
367
  )
337
368
  when "attr_accessor"
338
369
  args = node.arguments
@@ -342,32 +373,30 @@ module RBI
342
373
  return
343
374
  end
344
375
 
376
+ sigs = current_sigs
377
+ comments = detach_comments_from_sigs(sigs) + node_comments(node)
378
+
345
379
  current_scope << AttrAccessor.new(
346
380
  *T.unsafe(args.arguments.map { |arg| node_string!(arg).delete_prefix(":").to_sym }),
347
- sigs: current_sigs,
381
+ sigs: sigs,
348
382
  loc: node_loc(node),
349
- comments: current_sigs_comments + node_comments(node),
383
+ comments: comments,
350
384
  )
351
385
  when "enums"
352
- block = node.block
353
-
354
- unless block.is_a?(Prism::BlockNode)
355
- @last_node = nil
356
- return
357
- end
358
-
359
- body = block.body
360
-
361
- unless body.is_a?(Prism::StatementsNode)
362
- @last_node = nil
363
- return
386
+ if node.block && node.arguments.nil?
387
+ scope = TEnumBlock.new(loc: node_loc(node), comments: node_comments(node))
388
+ current_scope << scope
389
+ @scopes_stack << scope
390
+ visit(node.block)
391
+ @scopes_stack.pop
392
+ else
393
+ current_scope << Send.new(
394
+ message,
395
+ parse_send_args(node.arguments),
396
+ loc: node_loc(node),
397
+ comments: node_comments(node),
398
+ )
364
399
  end
365
-
366
- current_scope << TEnumBlock.new(
367
- body.body.map { |stmt| T.cast(stmt, Prism::ConstantWriteNode).name.to_s },
368
- loc: node_loc(node),
369
- comments: node_comments(node),
370
- )
371
400
  when "extend"
372
401
  args = node.arguments
373
402
 
@@ -415,6 +444,13 @@ module RBI
415
444
  case last_node
416
445
  when Method, Attr
417
446
  last_node.visibility = parse_visibility(node.name.to_s, node)
447
+ when Send
448
+ current_scope << Send.new(
449
+ message,
450
+ parse_send_args(node.arguments),
451
+ loc: node_loc(node),
452
+ comments: node_comments(node),
453
+ )
418
454
  else
419
455
  raise ParseError.new(
420
456
  "Unexpected token `#{node.message}` before `#{last_node&.string&.strip}`",
@@ -470,7 +506,7 @@ module RBI
470
506
 
471
507
  last_node_last_line = node.child_nodes.last&.location&.end_line
472
508
 
473
- last_line.downto(first_line) do |line|
509
+ first_line.upto(last_line) do |line|
474
510
  comment = @comments_by_line[line]
475
511
  next unless comment
476
512
  break if last_node_last_line && line <= last_node_last_line
@@ -516,10 +552,15 @@ module RBI
516
552
  sigs
517
553
  end
518
554
 
519
- sig { returns(T::Array[Comment]) }
520
- def current_sigs_comments
521
- comments = @last_sigs_comments.dup
522
- @last_sigs_comments.clear
555
+ sig { params(sigs: T::Array[Sig]).returns(T::Array[Comment]) }
556
+ def detach_comments_from_sigs(sigs)
557
+ comments = T.let([], T::Array[Comment])
558
+
559
+ sigs.each do |sig|
560
+ comments += sig.comments.dup
561
+ sig.comments.clear
562
+ end
563
+
523
564
  comments
524
565
  end
525
566
 
@@ -646,11 +687,10 @@ module RBI
646
687
 
647
688
  sig { params(node: Prism::CallNode).returns(Sig) }
648
689
  def parse_sig(node)
649
- @last_sigs_comments = node_comments(node)
650
-
651
690
  builder = SigBuilder.new(@source, file: @file)
652
691
  builder.current.loc = node_loc(node)
653
692
  builder.visit_call_node(node)
693
+ builder.current.comments = node_comments(node)
654
694
  builder.current
655
695
  end
656
696
 
@@ -745,11 +785,11 @@ module RBI
745
785
  def parse_visibility(name, node)
746
786
  case name
747
787
  when "public"
748
- Public.new(loc: node_loc(node))
788
+ Public.new(loc: node_loc(node), comments: node_comments(node))
749
789
  when "protected"
750
- Protected.new(loc: node_loc(node))
790
+ Protected.new(loc: node_loc(node), comments: node_comments(node))
751
791
  when "private"
752
- Private.new(loc: node_loc(node))
792
+ Private.new(loc: node_loc(node), comments: node_comments(node))
753
793
  else
754
794
  raise ParseError.new("Unexpected visibility `#{name}`", node_loc(node))
755
795
  end
@@ -781,10 +821,7 @@ module RBI
781
821
 
782
822
  sig { params(node: T.nilable(Prism::Node)).returns(T::Boolean) }
783
823
  def type_variable_definition?(node)
784
- return false unless node.is_a?(Prism::CallNode)
785
- return false unless node.block
786
-
787
- node.message == "type_member" || node.message == "type_template"
824
+ node.is_a?(Prism::CallNode) && (node.message == "type_member" || node.message == "type_template")
788
825
  end
789
826
  end
790
827
 
@@ -839,7 +876,7 @@ module RBI
839
876
  end
840
877
  end
841
878
  when "void"
842
- @current.return_type = nil
879
+ @current.return_type = "void"
843
880
  end
844
881
 
845
882
  visit(node.receiver)
data/lib/rbi/printer.rb CHANGED
@@ -169,6 +169,10 @@ module RBI
169
169
  case node
170
170
  when Module
171
171
  printt("module #{node.name}")
172
+ when TEnum
173
+ printt("class #{node.name} < T::Enum")
174
+ when TStruct
175
+ printt("class #{node.name} < T::Struct")
172
176
  when Class
173
177
  printt("class #{node.name}")
174
178
  superclass = node.superclass_name
@@ -184,10 +188,6 @@ module RBI
184
188
  end
185
189
  when SingletonClass
186
190
  printt("class << self")
187
- when TStruct
188
- printt("class #{node.name} < T::Struct")
189
- when TEnum
190
- printt("class #{node.name} < T::Enum")
191
191
  else
192
192
  raise PrinterError, "Unhandled node: #{node.class}"
193
193
  end
@@ -426,6 +426,7 @@ module RBI
426
426
  sig { override.params(node: Sig).void }
427
427
  def visit_sig(node)
428
428
  print_loc(node)
429
+ visit_all(node.comments)
429
430
 
430
431
  max_line_length = self.max_line_length
431
432
  if oneline?(node) && max_line_length.nil?
@@ -492,9 +493,7 @@ module RBI
492
493
 
493
494
  printl("enums do")
494
495
  indent
495
- node.names.each do |name|
496
- printl("#{name} = new")
497
- end
496
+ visit_all(node.nodes)
498
497
  dedent
499
498
  printl("end")
500
499
  end
@@ -611,7 +610,7 @@ module RBI
611
610
  def print_sig_param_comment_leading_space(node, last:)
612
611
  printn
613
612
  printt
614
- print(" " * (node.name.size + node.type.size + 3))
613
+ print(" " * (node.name.size + node.type.to_s.size + 3))
615
614
  print(" ") unless last
616
615
  end
617
616
 
@@ -654,10 +653,10 @@ module RBI
654
653
  print(").")
655
654
  end
656
655
  return_type = node.return_type
657
- if node.return_type && node.return_type != "void"
658
- print("returns(#{return_type})")
659
- else
656
+ if node.return_type.to_s == "void"
660
657
  print("void")
658
+ else
659
+ print("returns(#{return_type})")
661
660
  end
662
661
  printn(" }")
663
662
  end
@@ -707,10 +706,10 @@ module RBI
707
706
  print(".") if modifiers.any? || params.any?
708
707
 
709
708
  return_type = node.return_type
710
- if return_type && return_type != "void"
711
- print("returns(#{return_type})")
712
- else
709
+ if return_type.to_s == "void"
713
710
  print("void")
711
+ else
712
+ print("returns(#{return_type})")
714
713
  end
715
714
  printn
716
715
  dedent
@@ -62,7 +62,7 @@ module RBI
62
62
 
63
63
  private
64
64
 
65
- sig(:final) { returns([T.nilable(Sig), T.nilable(String)]) }
65
+ sig(:final) { returns([T.nilable(Sig), T.nilable(T.any(Type, String))]) }
66
66
  def parse_sig
67
67
  raise UnexpectedMultipleSigsError, self if 1 < sigs.count
68
68
 
@@ -101,7 +101,7 @@ module RBI
101
101
  params(
102
102
  name: String,
103
103
  sig: T.nilable(Sig),
104
- attribute_type: T.nilable(String),
104
+ attribute_type: T.nilable(T.any(Type, String)),
105
105
  visibility: Visibility,
106
106
  loc: T.nilable(Loc),
107
107
  comments: T::Array[Comment],
@@ -0,0 +1,65 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RBI
5
+ module Rewriters
6
+ # Rewrite non-singleton methods inside singleton classes to singleton methods
7
+ #
8
+ # Example:
9
+ # ~~~rb
10
+ # class << self
11
+ # def m1; end
12
+ # def self.m2; end
13
+ #
14
+ # class << self
15
+ # def m3; end
16
+ # end
17
+ # end
18
+ # ~~~
19
+ #
20
+ # will be rewritten to:
21
+ #
22
+ # ~~~rb
23
+ # def self.m1; end
24
+ #
25
+ # class << self
26
+ # def self.m2; end
27
+ # def self.m3; end
28
+ # end
29
+ # ~~~
30
+ class FlattenSingletonMethods < Visitor
31
+ extend T::Sig
32
+
33
+ sig { override.params(node: T.nilable(Node)).void }
34
+ def visit(node)
35
+ return unless node
36
+
37
+ case node
38
+ when SingletonClass
39
+ node.nodes.dup.each do |child|
40
+ visit(child)
41
+ next unless child.is_a?(Method) && !child.is_singleton
42
+
43
+ child.detach
44
+ child.is_singleton = true
45
+ T.must(node.parent_tree) << child
46
+ end
47
+
48
+ node.detach if node.nodes.empty?
49
+ when Tree
50
+ visit_all(node.nodes)
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ class Tree
57
+ extend T::Sig
58
+
59
+ sig { void }
60
+ def flatten_singleton_methods!
61
+ visitor = Rewriters::FlattenSingletonMethods.new
62
+ visitor.visit(self)
63
+ end
64
+ end
65
+ end