rbs 0.18.0 → 1.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/Rakefile +4 -0
  4. data/core/builtin.rbs +4 -0
  5. data/core/file.rbs +0 -4
  6. data/core/hash.rbs +1 -3
  7. data/core/io.rbs +159 -6
  8. data/core/kernel.rbs +1 -1
  9. data/core/time.rbs +0 -12
  10. data/goodcheck.yml +20 -0
  11. data/lib/rbs.rb +2 -0
  12. data/lib/rbs/ast/declarations.rb +7 -2
  13. data/lib/rbs/ast/members.rb +10 -4
  14. data/lib/rbs/cli.rb +10 -10
  15. data/lib/rbs/definition.rb +70 -3
  16. data/lib/rbs/definition_builder.rb +544 -989
  17. data/lib/rbs/definition_builder/ancestor_builder.rb +476 -0
  18. data/lib/rbs/definition_builder/method_builder.rb +217 -0
  19. data/lib/rbs/environment.rb +5 -1
  20. data/lib/rbs/environment_loader.rb +1 -1
  21. data/lib/rbs/environment_walker.rb +16 -10
  22. data/lib/rbs/errors.rb +71 -66
  23. data/lib/rbs/method_type.rb +1 -31
  24. data/lib/rbs/parser.rb +1000 -894
  25. data/lib/rbs/parser.y +108 -57
  26. data/lib/rbs/prototype/rb.rb +14 -3
  27. data/lib/rbs/prototype/rbi.rb +6 -6
  28. data/lib/rbs/prototype/runtime.rb +53 -33
  29. data/lib/rbs/substitution.rb +4 -0
  30. data/lib/rbs/test.rb +3 -1
  31. data/lib/rbs/test/hook.rb +24 -7
  32. data/lib/rbs/types.rb +63 -6
  33. data/lib/rbs/validator.rb +4 -2
  34. data/lib/rbs/variance_calculator.rb +5 -1
  35. data/lib/rbs/version.rb +1 -1
  36. data/lib/rbs/writer.rb +9 -1
  37. data/schema/members.json +5 -1
  38. data/sig/definition.rbs +6 -1
  39. data/sig/definition_builder.rbs +3 -0
  40. data/sig/errors.rbs +20 -0
  41. data/sig/members.rbs +4 -1
  42. data/sig/method_types.rbs +3 -16
  43. data/sig/type_name_resolver.rbs +4 -2
  44. data/sig/types.rbs +17 -1
  45. data/sig/validator.rbs +12 -0
  46. data/stdlib/dbm/0/dbm.rbs +0 -2
  47. data/stdlib/logger/0/log_device.rbs +1 -2
  48. data/stdlib/monitor/0/monitor.rbs +119 -0
  49. data/stdlib/time/0/time.rbs +327 -0
  50. data/stdlib/tsort/0/tsort.rbs +8 -0
  51. data/stdlib/uri/0/common.rbs +401 -0
  52. data/stdlib/uri/0/rfc2396_parser.rbs +9 -0
  53. data/stdlib/uri/0/rfc3986_parser.rbs +2 -0
  54. data/steep/Gemfile.lock +13 -14
  55. metadata +14 -5
@@ -20,7 +20,7 @@ class RBS::Parser
20
20
  nonassoc kARROW
21
21
  preclow
22
22
 
23
- expect 2
23
+ expect 5
24
24
 
25
25
  rule
26
26
 
@@ -99,11 +99,13 @@ rule
99
99
  { result = nil }
100
100
  | kLT class_name {
101
101
  result = Declarations::Class::Super.new(name: val[1].value,
102
- args: [])
102
+ args: [],
103
+ location: val[1].location)
103
104
  }
104
105
  | kLT class_name kLBRACKET type_list kRBRACKET {
105
106
  result = Declarations::Class::Super.new(name: val[1].value,
106
- args: val[3])
107
+ args: val[3],
108
+ location: val[1].location + val[4].location)
107
109
  }
108
110
 
109
111
  module_decl:
@@ -202,57 +204,67 @@ rule
202
204
  | alias_member
203
205
  | signature
204
206
 
207
+ attribute_kind:
208
+ { result = :instance }
209
+ | kSELF kDOT { result = :singleton }
210
+
205
211
  attribute_member:
206
- annotations kATTRREADER keyword type {
207
- location = val[1].location + val[3].location
208
- result = Members::AttrReader.new(name: val[2].value,
212
+ annotations kATTRREADER attribute_kind keyword type {
213
+ location = val[1].location + val[4].location
214
+ result = Members::AttrReader.new(name: val[3].value,
209
215
  ivar_name: nil,
210
- type: val[3],
216
+ type: val[4],
217
+ kind: val[2],
211
218
  annotations: val[0],
212
219
  location: location,
213
220
  comment: leading_comment(val[0].first&.location || location))
214
221
  }
215
- | annotations kATTRREADER method_name attr_var_opt kCOLON type {
216
- location = val[1].location + val[5].location
217
- result = Members::AttrReader.new(name: val[2].value.to_sym,
218
- ivar_name: val[3],
219
- type: val[5],
222
+ | annotations kATTRREADER attribute_kind method_name attr_var_opt kCOLON type {
223
+ location = val[1].location + val[6].location
224
+ result = Members::AttrReader.new(name: val[3].value.to_sym,
225
+ ivar_name: val[4],
226
+ type: val[6],
227
+ kind: val[2],
220
228
  annotations: val[0],
221
229
  location: location,
222
230
  comment: leading_comment(val[0].first&.location || location))
223
231
  }
224
- | annotations kATTRWRITER keyword type {
225
- location = val[1].location + val[3].location
226
- result = Members::AttrWriter.new(name: val[2].value,
232
+ | annotations kATTRWRITER attribute_kind keyword type {
233
+ location = val[1].location + val[4].location
234
+ result = Members::AttrWriter.new(name: val[3].value,
227
235
  ivar_name: nil,
228
- type: val[3],
236
+ kind: val[2],
237
+ type: val[4],
229
238
  annotations: val[0],
230
239
  location: location,
231
240
  comment: leading_comment(val[0].first&.location || location))
232
241
  }
233
- | annotations kATTRWRITER method_name attr_var_opt kCOLON type {
234
- location = val[1].location + val[5].location
235
- result = Members::AttrWriter.new(name: val[2].value.to_sym,
236
- ivar_name: val[3],
237
- type: val[5],
242
+ | annotations kATTRWRITER attribute_kind method_name attr_var_opt kCOLON type {
243
+ location = val[1].location + val[6].location
244
+ result = Members::AttrWriter.new(name: val[3].value.to_sym,
245
+ ivar_name: val[4],
246
+ kind: val[2],
247
+ type: val[6],
238
248
  annotations: val[0],
239
249
  location: location,
240
250
  comment: leading_comment(val[0].first&.location || location))
241
251
  }
242
- | annotations kATTRACCESSOR keyword type {
243
- location = val[1].location + val[3].location
244
- result = Members::AttrAccessor.new(name: val[2].value,
252
+ | annotations kATTRACCESSOR attribute_kind keyword type {
253
+ location = val[1].location + val[4].location
254
+ result = Members::AttrAccessor.new(name: val[3].value,
245
255
  ivar_name: nil,
246
- type: val[3],
256
+ kind: val[2],
257
+ type: val[4],
247
258
  annotations: val[0],
248
259
  location: location,
249
260
  comment: leading_comment(val[0].first&.location || location))
250
261
  }
251
- | annotations kATTRACCESSOR method_name attr_var_opt kCOLON type {
252
- location = val[1].location + val[5].location
253
- result = Members::AttrAccessor.new(name: val[2].value.to_sym,
254
- ivar_name: val[3],
255
- type: val[5],
262
+ | annotations kATTRACCESSOR attribute_kind method_name attr_var_opt kCOLON type {
263
+ location = val[1].location + val[6].location
264
+ result = Members::AttrAccessor.new(name: val[3].value.to_sym,
265
+ ivar_name: val[4],
266
+ kind: val[2],
267
+ type: val[6],
256
268
  annotations: val[0],
257
269
  location: location,
258
270
  comment: leading_comment(val[0].first&.location || location))
@@ -474,26 +486,13 @@ rule
474
486
  }
475
487
 
476
488
  method_type:
477
- start_merged_scope type_params params_opt block_opt kARROW simple_type {
489
+ start_merged_scope type_params proc_type {
478
490
  reset_variable_scope
479
491
 
480
- location = (val[1] || val[2] || val[3] || val[4]).location + val[5].location
492
+ location = (val[1] || val[2]).location + val[2].location
481
493
  type_params = val[1]&.value || []
482
494
 
483
- params = val[2]&.value || empty_params_result
484
-
485
- type = Types::Function.new(
486
- required_positionals: params[0],
487
- optional_positionals: params[1],
488
- rest_positionals: params[2],
489
- trailing_positionals: params[3],
490
- required_keywords: params[4],
491
- optional_keywords: params[5],
492
- rest_keywords: params[6],
493
- return_type: val[5]
494
- )
495
-
496
- block = val[3]&.value
495
+ type, block = val[2].value
497
496
 
498
497
  result = MethodType.new(type_params: type_params,
499
498
  type: type,
@@ -507,14 +506,13 @@ rule
507
506
  result = LocatedValue.new(value: val[1], location: val[0].location + val[2].location)
508
507
  }
509
508
 
510
- block_opt:
511
- { result = nil }
512
- | kLBRACE function_type kRBRACE {
513
- block = MethodType::Block.new(type: val[1].value, required: true)
509
+ block:
510
+ kLBRACE simple_function_type kRBRACE {
511
+ block = Types::Block.new(type: val[1].value, required: true)
514
512
  result = LocatedValue.new(value: block, location: val[0].location + val[2].location)
515
513
  }
516
- | kQUESTION kLBRACE function_type kRBRACE {
517
- block = MethodType::Block.new(type: val[2].value, required: false)
514
+ | kQUESTION kLBRACE simple_function_type kRBRACE {
515
+ block = Types::Block.new(type: val[2].value, required: false)
518
516
  result = LocatedValue.new(value: block, location: val[0].location + val[3].location)
519
517
  }
520
518
 
@@ -797,8 +795,9 @@ rule
797
795
  result = Types::ClassSingleton.new(name: val[2].value,
798
796
  location: val[0].location + val[3].location)
799
797
  }
800
- | kHAT function_type {
801
- result = Types::Proc.new(type: val[1].value, location: val[0].location + val[1].location)
798
+ | kHAT proc_type {
799
+ type, block = val[1].value
800
+ result = Types::Proc.new(type: type, block: block, location: val[0].location + val[1].location)
802
801
  }
803
802
  | simple_type kQUESTION {
804
803
  result = Types::Optional.new(type: val[0], location: val[0].location + val[1].location)
@@ -842,6 +841,15 @@ rule
842
841
  | keyword type {
843
842
  result = { val[0].value => val[1] }
844
843
  }
844
+ | identifier_keywords kCOLON type {
845
+ result = { val[0].value => val[2] }
846
+ }
847
+ | tQUOTEDIDENT kCOLON type {
848
+ result = { val[0].value => val[2] }
849
+ }
850
+ | tQUOTEDMETHOD kCOLON type {
851
+ result = { val[0].value => val[2] }
852
+ }
845
853
 
846
854
  keyword_name:
847
855
  keyword
@@ -851,7 +859,32 @@ rule
851
859
 
852
860
  keyword: tLKEYWORD | tUKEYWORD | tLKEYWORD_Q_E | tUKEYWORD_Q_E
853
861
 
854
- function_type:
862
+ proc_type:
863
+ params_opt block kARROW simple_type {
864
+ location = (val[0] || val[1] || val[2]).location + val[3].location
865
+
866
+ params = val[0]&.value || [[], [], nil, [], {}, {}, nil]
867
+
868
+ type = Types::Function.new(
869
+ required_positionals: params[0],
870
+ optional_positionals: params[1],
871
+ rest_positionals: params[2],
872
+ trailing_positionals: params[3],
873
+ required_keywords: params[4],
874
+ optional_keywords: params[5],
875
+ rest_keywords: params[6],
876
+ return_type: val[3]
877
+ )
878
+
879
+ block = val[1].value
880
+
881
+ result = LocatedValue.new(value: [type, block], location: location)
882
+ }
883
+ | simple_function_type {
884
+ result = LocatedValue.new(value: [val[0].value, nil], location: val[0].location)
885
+ }
886
+
887
+ simple_function_type:
855
888
  kLPAREN params kRPAREN kARROW simple_type {
856
889
  location = val[0].location + val[4].location
857
890
  type = Types::Function.new(
@@ -883,7 +916,7 @@ rule
883
916
  result = LocatedValue.new(value: type, location: location)
884
917
  }
885
918
 
886
- params:
919
+ params:
887
920
  required_positional kCOMMA params {
888
921
  result = val[2]
889
922
  result[0].unshift(val[0])
@@ -1294,6 +1327,10 @@ ANNOTATION_RE = Regexp.union(/%a\{.*?\}/,
1294
1327
  /%a\(.*?\)/,
1295
1328
  /%a\<.*?\>/,
1296
1329
  /%a\|.*?\|/)
1330
+
1331
+ escape_sequences = %w[a b e f n r s t v "].map { |l| "\\\\#{l}" }
1332
+ DBL_QUOTE_STR_ESCAPE_SEQUENCES_RE = /(#{escape_sequences.join("|")})/
1333
+
1297
1334
  def next_token
1298
1335
  if @type
1299
1336
  type = @type
@@ -1373,7 +1410,21 @@ def next_token
1373
1410
  when input.scan(/[a-z_]\w*\b/)
1374
1411
  new_token(:tLIDENT)
1375
1412
  when input.scan(/"(\\"|[^"])*"/)
1376
- s = input.matched.yield_self {|s| s[1, s.length - 2] }.gsub(/\\"/, '"')
1413
+ s = input.matched.yield_self {|s| s[1, s.length - 2] }
1414
+ .gsub(DBL_QUOTE_STR_ESCAPE_SEQUENCES_RE) do |match|
1415
+ case match
1416
+ when '\\a' then "\a"
1417
+ when '\\b' then "\b"
1418
+ when '\\e' then "\e"
1419
+ when '\\f' then "\f"
1420
+ when '\\n' then "\n"
1421
+ when '\\r' then "\r"
1422
+ when '\\s' then "\s"
1423
+ when '\\t' then "\t"
1424
+ when '\\v' then "\v"
1425
+ when '\\"' then '"'
1426
+ end
1427
+ end
1377
1428
  new_token(:tSTRING, s)
1378
1429
  when input.scan(/'(\\'|[^'])*'/)
1379
1430
  s = input.matched.yield_self {|s| s[1, s.length - 2] }.gsub(/\\'/, "'")
@@ -15,6 +15,14 @@ module RBS
15
15
  :instance
16
16
  end
17
17
  end
18
+
19
+ def attribute_kind
20
+ if singleton
21
+ :singleton
22
+ else
23
+ :instance
24
+ end
25
+ end
18
26
  end
19
27
 
20
28
  attr_reader :source_decls
@@ -77,7 +85,7 @@ module RBS
77
85
  class_name, super_class, *class_body = node.children
78
86
  kls = AST::Declarations::Class.new(
79
87
  name: const_to_name(class_name),
80
- super_class: super_class && AST::Declarations::Class::Super.new(name: const_to_name(super_class), args: []),
88
+ super_class: super_class && AST::Declarations::Class::Super.new(name: const_to_name(super_class), args: [], location: nil),
81
89
  type_params: AST::Declarations::ModuleTypeParams.empty,
82
90
  members: [],
83
91
  annotations: [],
@@ -202,6 +210,7 @@ module RBS
202
210
  name: name,
203
211
  ivar_name: nil,
204
212
  type: Types::Bases::Any.new(location: nil),
213
+ kind: context.attribute_kind,
205
214
  location: nil,
206
215
  comment: comments[node.first_lineno - 1],
207
216
  annotations: []
@@ -215,6 +224,7 @@ module RBS
215
224
  name: name,
216
225
  ivar_name: nil,
217
226
  type: Types::Bases::Any.new(location: nil),
227
+ kind: context.attribute_kind,
218
228
  location: nil,
219
229
  comment: comments[node.first_lineno - 1],
220
230
  annotations: []
@@ -228,6 +238,7 @@ module RBS
228
238
  name: name,
229
239
  ivar_name: nil,
230
240
  type: Types::Bases::Any.new(location: nil),
241
+ kind: context.attribute_kind,
231
242
  location: nil,
232
243
  comment: comments[node.first_lineno - 1],
233
244
  annotations: []
@@ -549,7 +560,7 @@ module RBS
549
560
  method_block = nil
550
561
 
551
562
  if block
552
- method_block = MethodType::Block.new(
563
+ method_block = Types::Block.new(
553
564
  required: true,
554
565
  type: Types::Function.empty(untyped)
555
566
  )
@@ -557,7 +568,7 @@ module RBS
557
568
 
558
569
  if body_node
559
570
  if (yields = any_node?(body_node) {|n| n.type == :YIELD })
560
- method_block = MethodType::Block.new(
571
+ method_block = Types::Block.new(
561
572
  required: true,
562
573
  type: Types::Function.empty(untyped)
563
574
  )
@@ -47,7 +47,7 @@ module RBS
47
47
  def push_class(name, super_class, comment:)
48
48
  modules.push AST::Declarations::Class.new(
49
49
  name: nested_name(name),
50
- super_class: super_class && AST::Declarations::Class::Super.new(name: const_to_name(super_class), args: []),
50
+ super_class: super_class && AST::Declarations::Class::Super.new(name: const_to_name(super_class), args: [], location: nil),
51
51
  type_params: AST::Declarations::ModuleTypeParams.empty,
52
52
  members: [],
53
53
  annotations: [],
@@ -387,19 +387,19 @@ module RBS
387
387
  if block
388
388
  if (type = vars[block])
389
389
  if type.is_a?(Types::Proc)
390
- method_block = MethodType::Block.new(required: true, type: type.type)
390
+ method_block = Types::Block.new(required: true, type: type.type)
391
391
  elsif type.is_a?(Types::Bases::Any)
392
- method_block = MethodType::Block.new(
392
+ method_block = Types::Block.new(
393
393
  required: true,
394
394
  type: Types::Function.empty(Types::Bases::Any.new(location: nil))
395
395
  )
396
396
  # Handle an optional block like `T.nilable(T.proc.void)`.
397
397
  elsif type.is_a?(Types::Optional) && type.type.is_a?(Types::Proc)
398
- method_block = MethodType::Block.new(required: false, type: type.type.type)
398
+ method_block = Types::Block.new(required: false, type: type.type.type)
399
399
  else
400
400
  STDERR.puts "Unexpected block type: #{type}"
401
401
  PP.pp args_node, STDERR
402
- method_block = MethodType::Block.new(
402
+ method_block = Types::Block.new(
403
403
  required: true,
404
404
  type: Types::Function.empty(Types::Bases::Any.new(location: nil))
405
405
  )
@@ -485,7 +485,7 @@ module RBS
485
485
  Types::Tuple.new(types: types, location: nil)
486
486
  else
487
487
  if proc_type?(type_node)
488
- Types::Proc.new(type: method_type(nil, type_node, variables: variables).type, location: nil)
488
+ Types::Proc.new(type: method_type(nil, type_node, variables: variables).type, block: nil, location: nil)
489
489
  else
490
490
  STDERR.puts "Unexpected type_node:"
491
491
  PP.pp type_node, STDERR
@@ -61,11 +61,32 @@ module RBS
61
61
  end
62
62
  end
63
63
 
64
- def each_mixin(mixins, *super_mixes)
65
- supers = Set.new(super_mixes)
66
- mixins.each do |mix|
64
+ def each_included_module(type_name, mod)
65
+ supers = Set[]
66
+
67
+ mod.included_modules.each do |mix|
68
+ supers.merge(mix.included_modules)
69
+ end
70
+
71
+ if mod.is_a?(Class)
72
+ mod.superclass.included_modules.each do |mix|
73
+ supers << mix
74
+ supers.merge(mix.included_modules)
75
+ end
76
+ end
77
+
78
+ mod.included_modules.each do |mix|
67
79
  unless supers.include?(mix)
68
- yield mix
80
+ unless const_name(mix)
81
+ RBS.logger.warn("Skipping anonymous module #{mix} included in #{mod}")
82
+ else
83
+ module_name = to_type_name(const_name(mix))
84
+ if module_name.namespace == type_name.namespace
85
+ module_name = TypeName.new(name: module_name.name, namespace: Namespace.empty)
86
+ end
87
+
88
+ yield module_name, mix
89
+ end
69
90
  end
70
91
  end
71
92
  end
@@ -103,7 +124,7 @@ module RBS
103
124
  when :keyrest
104
125
  rest_keywords = Types::Function::Param.new(name: nil, type: untyped)
105
126
  when :block
106
- block = MethodType::Block.new(
127
+ block = Types::Block.new(
107
128
  type: Types::Function.empty(untyped).update(rest_positionals: Types::Function::Param.new(name: nil, type: untyped)),
108
129
  required: true
109
130
  )
@@ -298,11 +319,11 @@ module RBS
298
319
  location: nil
299
320
  )
300
321
  else
301
- Types::ClassInstance.new(name: to_type_name(value.class.to_s), args: [], location: nil)
322
+ Types::ClassInstance.new(name: to_type_name(const_name(value.class)), args: [], location: nil)
302
323
  end
303
324
 
304
325
  @decls << AST::Declarations::Constant.new(
305
- name: "#{mod.to_s}::#{name}",
326
+ name: "#{const_name(mod)}::#{name}",
306
327
  type: type,
307
328
  location: nil,
308
329
  comment: nil
@@ -311,14 +332,14 @@ module RBS
311
332
  end
312
333
 
313
334
  def generate_class(mod)
314
- type_name = to_type_name(mod.name)
335
+ type_name = to_type_name(const_name(mod))
315
336
  super_class = if mod.superclass == ::Object
316
337
  nil
317
- elsif mod.superclass.name.nil?
338
+ elsif const_name(mod.superclass).nil?
318
339
  RBS.logger.warn("Skipping anonymous superclass #{mod.superclass} of #{mod}")
319
340
  nil
320
341
  else
321
- AST::Declarations::Class::Super.new(name: to_type_name(mod.superclass.name), args: [])
342
+ AST::Declarations::Class::Super.new(name: to_type_name(const_name(mod.superclass)), args: [], location: nil)
322
343
  end
323
344
 
324
345
  decl = AST::Declarations::Class.new(
@@ -331,17 +352,7 @@ module RBS
331
352
  comment: nil
332
353
  )
333
354
 
334
- each_mixin(mod.included_modules, *mod.superclass.included_modules, *mod.included_modules.flat_map(&:included_modules)) do |included_module|
335
- unless included_module.name
336
- RBS.logger.warn("Skipping anonymous module #{included_module} included in #{mod}")
337
- next
338
- end
339
-
340
- module_name = to_type_name(included_module.name)
341
- if module_name.namespace == type_name.namespace
342
- module_name = TypeName.new(name: module_name.name, namespace: Namespace.empty)
343
- end
344
-
355
+ each_included_module(type_name, mod) do |module_name, _|
345
356
  decl.members << AST::Members::Include.new(
346
357
  name: module_name,
347
358
  args: [],
@@ -351,6 +362,16 @@ module RBS
351
362
  )
352
363
  end
353
364
 
365
+ each_included_module(type_name, mod.singleton_class) do |module_name, _|
366
+ decl.members << AST::Members::Extend.new(
367
+ name: module_name,
368
+ args: [],
369
+ location: nil,
370
+ comment: nil,
371
+ annotations: []
372
+ )
373
+ end
374
+
354
375
  generate_methods(mod, type_name, decl.members)
355
376
 
356
377
  @decls << decl
@@ -378,18 +399,7 @@ module RBS
378
399
  comment: nil
379
400
  )
380
401
 
381
- each_mixin(mod.included_modules, *mod.included_modules.flat_map(&:included_modules), namespace: type_name.namespace) do |included_module|
382
- included_module_name = const_name(included_module)
383
- unless included_module_name
384
- RBS.logger.warn("Skipping anonymous module #{included_module} included in #{mod}")
385
- next
386
- end
387
-
388
- module_name = to_type_name(included_module_name)
389
- if module_name.namespace == type_name.namespace
390
- module_name = TypeName.new(name: module_name.name, namespace: Namespace.empty)
391
- end
392
-
402
+ each_included_module(type_name, mod) do |module_name, _|
393
403
  decl.members << AST::Members::Include.new(
394
404
  name: module_name,
395
405
  args: [],
@@ -399,6 +409,16 @@ module RBS
399
409
  )
400
410
  end
401
411
 
412
+ each_included_module(type_name, mod.singleton_class) do |module_name, _|
413
+ decl.members << AST::Members::Extend.new(
414
+ name: module_name,
415
+ args: [],
416
+ location: nil,
417
+ comment: nil,
418
+ annotations: []
419
+ )
420
+ end
421
+
402
422
  generate_methods(mod, type_name, decl.members)
403
423
 
404
424
  @decls << decl