rbs_protobuf 0.3.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,30 @@
1
1
  module RBSProtobuf
2
2
  module Translator
3
3
  class ProtobufGem < Base
4
+ FIELD_ARRAY = Name::Class.new(TypeName("::Protobuf::Field::FieldArray"))
5
+
6
+ FIELD_HASH = Name::Class.new(TypeName("::Protobuf::Field::FieldHash"))
7
+
8
+ ENUM = Name::Class.new(TypeName("::Protobuf::Enum"))
9
+
10
+ MESSAGE = Name::Class.new(TypeName("::Protobuf::Message"))
11
+
12
+ TO_PROTO = Name::Interface.new(TypeName("_ToProto"))
13
+
14
+ FIELD_ARRAY_a = Name::Alias.new(TypeName("::Protobuf::field_array"))
15
+
16
+ FIELD_HASH_a = Name::Alias.new(TypeName("::Protobuf::field_hash"))
17
+
4
18
  attr_reader :stderr
5
19
 
6
- def initialize(input, upcase_enum:, nested_namespace:, extension:, stderr: STDERR)
20
+ attr_reader :accept_nil_writer
21
+
22
+ def initialize(input, upcase_enum:, nested_namespace:, extension:, accept_nil_writer:, stderr: STDERR)
7
23
  super(input)
8
24
  @upcase_enum = upcase_enum
9
25
  @nested_namespace = nested_namespace
10
26
  @extension = extension
27
+ @accept_nil_writer = accept_nil_writer
11
28
  @stderr = stderr
12
29
  end
13
30
 
@@ -90,26 +107,22 @@ module RBSProtobuf
90
107
  end
91
108
  end
92
109
 
93
- file.extension.group_by(&:extendee).each.with_index do |(name, extensions), index|
110
+ file.extension.each.with_index do |extension, index|
94
111
  if ignore_extension?
95
112
  if print_extension_message?
96
- stderr.puts "Extension for `#{name}` ignored in `#{file.name}`; Set RBS_PROTOBUF_EXTENSION env var to generate RBS for extensions."
113
+ stderr.puts "Extension for `#{extension.extendee}` ignored in `#{file.name}`; Set RBS_PROTOBUF_EXTENSION env var to generate RBS for extensions."
97
114
  end
98
115
  else
99
- exts = extension_to_decl(name,
100
- extensions,
101
- prefix: RBS::Namespace.root,
102
- source_code_info: source_code_info,
103
- path: [7, index])
116
+ ext = extension_to_decl(extension, prefix: RBS::Namespace.root, source_code_info: source_code_info, path: [7, index])
104
117
 
105
118
  if print_extension?
106
119
  stderr.puts "#=========================================================="
107
120
  stderr.puts "# Printing RBS for extensions from #{file.name}"
108
121
  stderr.puts "#"
109
- RBS::Writer.new(out: stderr).write(exts)
122
+ RBS::Writer.new(out: stderr).write([ext])
110
123
  stderr.puts
111
124
  else
112
- decls.push(*exts)
125
+ decls.push(ext)
113
126
  end
114
127
  end
115
128
  end
@@ -119,37 +132,20 @@ module RBSProtobuf
119
132
  end.string
120
133
  end
121
134
 
122
- def message_base_class
123
- RBS::AST::Declarations::Class::Super.new(
124
- name: RBS::TypeName.new(
125
- name: :Message,
126
- namespace: RBS::Namespace.parse("::Protobuf")
127
- ),
128
- args: [],
129
- location: nil
130
- )
131
- end
132
-
133
- def repeated_field_type(type, wtype = type)
134
- factory.instance_type(
135
- factory.type_name("::Protobuf::Field::FieldArray"),
136
- type,
137
- wtype
138
- )
139
- end
140
-
141
135
  def message_to_decl(message, prefix:, message_path:, source_code_info:, path:)
142
136
  class_name = ActiveSupport::Inflector.upcase_first(message.name)
143
137
 
144
138
  RBS::AST::Declarations::Class.new(
145
139
  name: RBS::TypeName.new(name: class_name.to_sym, namespace: prefix),
146
- super_class: message_base_class,
140
+ super_class: MESSAGE.super_class,
147
141
  type_params: [],
148
142
  location: nil,
149
143
  comment: comment_for_path(source_code_info, path, options: message.options),
150
144
  members: [],
151
145
  annotations: []
152
146
  ).tap do |class_decl|
147
+ class_instance_type = factory.instance_type(RBS::TypeName.new(name: class_decl.name.name, namespace: RBS::Namespace.empty))
148
+
153
149
  maps = {}
154
150
 
155
151
  message.nested_type.each_with_index do |nested_type, index|
@@ -177,63 +173,17 @@ module RBSProtobuf
177
173
  )
178
174
  end
179
175
 
180
- field_read_types = {}
181
- field_write_types = {}
176
+ # @type var field_types: Hash[Symbol, [RBS::Types::t, Array[RBS::Types::t], RBS::Types::t]]
177
+ field_types = {}
182
178
 
183
179
  message.field.each_with_index do |field, index|
184
180
  field_name = field.name.to_sym
185
181
  comment = comment_for_path(source_code_info, path + [2, index], options: field.options)
186
182
 
187
- read_type, write_type = field_type(field, maps)
188
-
189
- field_read_types[field_name] = read_type
190
- field_write_types[field_name] = write_type
191
-
192
- if read_type == write_type
193
- class_decl.members << RBS::AST::Members::AttrAccessor.new(
194
- name: field_name,
195
- type: read_type,
196
- comment: comment,
197
- location: nil,
198
- annotations: [],
199
- ivar_name: false,
200
- kind: :instance
201
- )
202
- else
203
- class_decl.members << RBS::AST::Members::AttrReader.new(
204
- name: field_name,
205
- type: read_type,
206
- comment: comment,
207
- location: nil,
208
- annotations: [],
209
- ivar_name: false,
210
- kind: :instance
211
- )
212
-
213
- class_decl.members << RBS::AST::Members::AttrWriter.new(
214
- name: field_name,
215
- type: write_type,
216
- comment: comment,
217
- location: nil,
218
- annotations: [],
219
- ivar_name: false,
220
- kind: :instance
221
- )
222
- end
183
+ read_type, write_types, init_type = field_type(field, maps)
184
+ field_types[field_name] = [read_type, write_types, init_type]
223
185
 
224
- class_decl.members << RBS::AST::Members::MethodDefinition.new(
225
- name: :"#{field_name}!",
226
- types: [
227
- factory.method_type(
228
- type: factory.function(factory.optional_type(read_type))
229
- )
230
- ],
231
- annotations: [],
232
- comment: nil,
233
- location: nil,
234
- overload: false,
235
- kind: :instance
236
- )
186
+ add_field(class_decl.members, name: field_name, read_type: read_type, write_types: write_types, comment: comment)
237
187
  end
238
188
 
239
189
  class_decl.members << RBS::AST::Members::MethodDefinition.new(
@@ -241,8 +191,9 @@ module RBSProtobuf
241
191
  types: [
242
192
  factory.method_type(
243
193
  type: factory.function().update(
244
- optional_keywords: field_write_types.transform_values {|ty|
245
- factory.param(ty)
194
+ optional_keywords: field_types.transform_values {|pair|
195
+ _, _, init_type = pair
196
+ factory.param(init_type)
246
197
  }
247
198
  )
248
199
  )
@@ -254,15 +205,17 @@ module RBSProtobuf
254
205
  kind: :instance
255
206
  )
256
207
 
257
- unless field_read_types.empty?
208
+ unless field_types.empty?
258
209
  class_decl.members << RBS::AST::Members::MethodDefinition.new(
259
210
  name: :[],
260
211
  types:
261
- field_read_types.keys.map do |key|
212
+ field_types.map do |field_name, pair|
213
+ read_type, _ = pair
214
+
262
215
  factory.method_type(
263
- type: factory.function(field_read_types[key]).update(
216
+ type: factory.function(read_type).update(
264
217
  required_positionals: [
265
- factory.param(factory.literal_type(key))
218
+ factory.param(factory.literal_type(field_name))
266
219
  ]
267
220
  )
268
221
  )
@@ -282,21 +235,34 @@ module RBSProtobuf
282
235
  overload: false,
283
236
  kind: :instance
284
237
  )
285
- end
286
238
 
287
- unless field_write_types.empty?
288
239
  class_decl.members << RBS::AST::Members::MethodDefinition.new(
289
240
  name: :[]=,
290
241
  types:
291
- field_write_types.keys.map do |key|
292
- factory.method_type(
293
- type: factory.function(field_write_types[key]).update(
294
- required_positionals: [
295
- factory.literal_type(key),
296
- field_write_types[key]
297
- ].map {|t| factory.param(t) }
298
- )
299
- )
242
+ field_types.flat_map do |field_name, pair|
243
+ read_type, write_types = pair
244
+
245
+ [read_type, *write_types].map do |type|
246
+ if (type_param, type_var = interface_type?(type))
247
+ factory.method_type(
248
+ type: factory.function(type_var).update(
249
+ required_positionals: [
250
+ factory.literal_type(field_name),
251
+ type_var
252
+ ].map {|t| factory.param(t) }
253
+ )
254
+ ).update(type_params: [type_param])
255
+ else
256
+ factory.method_type(
257
+ type: factory.function(type).update(
258
+ required_positionals: [
259
+ factory.literal_type(field_name),
260
+ type
261
+ ].map {|t| factory.param(t) }
262
+ )
263
+ )
264
+ end
265
+ end
300
266
  end +
301
267
  [
302
268
  factory.method_type(
@@ -333,82 +299,310 @@ module RBSProtobuf
333
299
  )
334
300
  end
335
301
  end
302
+
303
+ class_decl.members << RBS::AST::Declarations::Interface.new(
304
+ name: TO_PROTO.name,
305
+ type_params: [],
306
+ members: [],
307
+ annotations: [],
308
+ comment: nil,
309
+ location: nil
310
+ ).tap do |interface_decl|
311
+ interface_decl.members << RBS::AST::Members::MethodDefinition.new(
312
+ name: :to_proto,
313
+ types: [
314
+ factory.method_type(
315
+ type: factory.function(class_instance_type)
316
+ )
317
+ ],
318
+ annotations: [],
319
+ comment: nil,
320
+ location: nil,
321
+ overload: false,
322
+ kind: :instance
323
+ )
324
+ end
325
+
326
+ class_decl.members << RBS::AST::Declarations::Alias.new(
327
+ name: TypeName("init"),
328
+ type_params: [],
329
+ type: factory.union_type(class_instance_type, TO_PROTO[]),
330
+ annotations: [],
331
+ comment: RBS::AST::Comment.new(string: "The type of `#initialize` parameter.", location: nil),
332
+ location: nil
333
+ )
334
+
335
+ class_decl.members << RBS::AST::Declarations::Alias.new(
336
+ name: TypeName("field_array"),
337
+ type_params: [],
338
+ type: FIELD_ARRAY[
339
+ class_instance_type,
340
+ factory.union_type(class_instance_type, TO_PROTO[])
341
+ ],
342
+ annotations: [],
343
+ comment: RBS::AST::Comment.new(string: "The type of `repeated` field.", location: nil),
344
+ location: nil
345
+ )
346
+
347
+ class_decl.members << RBS::AST::Declarations::Alias.new(
348
+ name: TypeName("field_hash"),
349
+ type_params: [RBS::AST::TypeParam.new(name: :KEY, variance: :invariant, upper_bound: nil, location: nil)],
350
+ type: FIELD_HASH[
351
+ factory.type_var(:KEY),
352
+ class_instance_type,
353
+ factory.union_type(class_instance_type, TO_PROTO[])
354
+ ],
355
+ annotations: [],
356
+ comment: RBS::AST::Comment.new(string: "The type of `map` field.", location: nil),
357
+ location: nil
358
+ )
359
+
360
+ class_decl.members << RBS::AST::Declarations::Alias.new(
361
+ name: TypeName("array"),
362
+ type_params: [],
363
+ type: RBS::BuiltinNames::Array.instance_type(factory.union_type(class_instance_type, TO_PROTO[])),
364
+ annotations: [],
365
+ comment: nil,
366
+ location: nil
367
+ )
368
+
369
+ class_decl.members << RBS::AST::Declarations::Alias.new(
370
+ name: TypeName("hash"),
371
+ type_params: [RBS::AST::TypeParam.new(name: :KEY, variance: :invariant, upper_bound: nil, location: nil)],
372
+ type: RBS::BuiltinNames::Hash.instance_type(
373
+ factory.type_var(:KEY),
374
+ factory.union_type(class_instance_type, TO_PROTO[])
375
+ ),
376
+ annotations: [],
377
+ comment: nil,
378
+ location: nil
379
+ )
336
380
  end
337
381
  end
338
382
 
383
+ def message_to_proto_type(type)
384
+ namespace = type.name.to_namespace
385
+ RBS::Types::Interface.new(
386
+ name: RBS::TypeName.new(name: :_ToProto, namespace: namespace),
387
+ args: [],
388
+ location: nil
389
+ )
390
+ end
391
+
392
+ def message_init_type(type)
393
+ RBS::Types::Alias.new(
394
+ name: RBS::TypeName.new(name: :init, namespace: type.name.to_namespace),
395
+ args: [],
396
+ location: nil
397
+ )
398
+ end
399
+
400
+ def message_field_array_type(type)
401
+ RBS::Types::Alias.new(
402
+ name: RBS::TypeName.new(name: :field_array, namespace: type.name.to_namespace),
403
+ args: [],
404
+ location: nil
405
+ )
406
+ end
407
+
408
+ def message_array_type(type)
409
+ RBS::Types::Alias.new(
410
+ name: RBS::TypeName.new(name: :array, namespace: type.name.to_namespace),
411
+ args: [],
412
+ location: nil
413
+ )
414
+ end
415
+
416
+ def message_hash_type(type, key)
417
+ RBS::Types::Alias.new(
418
+ name: RBS::TypeName.new(name: :hash, namespace: type.name.to_namespace),
419
+ args: [key],
420
+ location: nil
421
+ )
422
+ end
423
+
424
+ def message_field_hash_type(type, key)
425
+ RBS::Types::Alias.new(
426
+ name: RBS::TypeName.new(name: :field_hash, namespace: type.name.to_namespace),
427
+ args: [key],
428
+ location: nil
429
+ )
430
+ end
431
+
339
432
  def field_type(field, maps)
340
- case
341
- when field.type == FieldDescriptorProto::Type::TYPE_MESSAGE
342
- if maps.key?(field.type_name)
343
- key_field, value_field = maps[field.type_name]
344
-
345
- key_type_r, _ = field_type(key_field, maps)
346
- value_type_r, value_type_w = field_type(value_field, maps)
347
-
348
- hash_type = factory.instance_type(
349
- factory.type_name("::Protobuf::Field::FieldHash"),
350
- key_type_r,
351
- factory.unwrap_optional(value_type_r),
352
- factory.unwrap_optional(value_type_w)
353
- )
433
+ # @type var triple: [RBS::Types::t, Array[RBS::Types::t], RBS::Types::t]
434
+ triple =
435
+ case
436
+ when field.type == FieldDescriptorProto::Type::TYPE_MESSAGE
437
+ if maps.key?(field.type_name)
438
+ key_field, value_field = maps[field.type_name]
439
+
440
+ key_type_r, _ = field_type(key_field, maps)
441
+ value_type_r, value_write_types = field_type(value_field, maps)
442
+
443
+ value_type_r = factory.unwrap_optional(value_type_r)
444
+ value_write_types = value_write_types.map {|type| factory.unwrap_optional(type) }
445
+
446
+ case value_field.type
447
+ when FieldDescriptorProto::Type::TYPE_MESSAGE, FieldDescriptorProto::Type::TYPE_ENUM
448
+ value_type_r.is_a?(RBS::Types::ClassInstance) or raise
449
+ [
450
+ message_field_hash_type(value_type_r, key_type_r),
451
+ [message_hash_type(value_type_r, key_type_r)],
452
+ message_hash_type(value_type_r, key_type_r)
453
+ ]
454
+ else
455
+ hash_type = FIELD_HASH[
456
+ key_type_r,
457
+ value_type_r,
458
+ factory.union_type(value_type_r, *value_write_types)
459
+ ]
460
+
461
+ [
462
+ FIELD_HASH_a[key_type_r, value_type_r],
463
+ [RBS::BuiltinNames::Hash.instance_type(key_type_r, value_type_r)],
464
+ RBS::BuiltinNames::Hash.instance_type(key_type_r, value_type_r)
465
+ ]
466
+ end
467
+ else
468
+ type = message_type(field.type_name)
354
469
 
355
- [
356
- hash_type,
357
- hash_type
358
- ]
359
- else
470
+ case field.label
471
+ when FieldDescriptorProto::Label::LABEL_OPTIONAL
472
+ [
473
+ factory.optional_type(type),
474
+ [
475
+ factory.optional_type(message_to_proto_type(type))
476
+ ],
477
+ factory.optional_type(message_init_type(type))
478
+ ]
479
+ when FieldDescriptorProto::Label::LABEL_REPEATED
480
+ [
481
+ message_field_array_type(type),
482
+ [
483
+ message_array_type(type)
484
+ ],
485
+ message_array_type(type)
486
+ ]
487
+ else
488
+ [
489
+ type,
490
+ [message_to_proto_type(type)],
491
+ message_init_type(type)
492
+ ]
493
+ end
494
+ end
495
+ when field.type == FieldDescriptorProto::Type::TYPE_ENUM
360
496
  type = message_type(field.type_name)
361
-
362
- case field.label
363
- when FieldDescriptorProto::Label::LABEL_OPTIONAL
364
- type = factory.optional_type(type)
365
- [type, type]
366
- when FieldDescriptorProto::Label::LABEL_REPEATED
367
- type = repeated_field_type(type)
368
- [type, type]
497
+ enum_namespace = type.name.to_namespace
498
+ values = factory.alias_type(RBS::TypeName.new(name: :values, namespace: enum_namespace))
499
+
500
+ if field.label == FieldDescriptorProto::Label::LABEL_REPEATED
501
+ [
502
+ message_field_array_type(type),
503
+ [message_array_type(type)],
504
+ message_array_type(type)
505
+ ]
506
+ else
507
+ [
508
+ type,
509
+ [values],
510
+ message_init_type(type)
511
+ ]
512
+ end
513
+ else
514
+ type = base_type(field.type)
515
+
516
+ if field.label == FieldDescriptorProto::Label::LABEL_REPEATED
517
+ [
518
+ FIELD_ARRAY_a[type],
519
+ [RBS::BuiltinNames::Array.instance_type(type)],
520
+ RBS::BuiltinNames::Array.instance_type(type)
521
+ ]
369
522
  else
370
- [type, factory.optional_type(type)]
523
+ [type, [], type]
371
524
  end
372
525
  end
373
- when field.type == FieldDescriptorProto::Type::TYPE_ENUM
374
- type = message_type(field.type_name)
375
- enum_namespace = type.name.to_namespace
376
526
 
377
- wtype = factory.union_type(
378
- type,
379
- factory.alias_type(RBS::TypeName.new(name: :values, namespace: enum_namespace))
380
- )
381
-
382
- if field.label == FieldDescriptorProto::Label::LABEL_REPEATED
383
- type = repeated_field_type(type, wtype)
527
+ if accept_nil_writer
528
+ read_type, write_types, init_type = triple
529
+ [
530
+ read_type,
531
+ ([factory.optional_type(read_type)] + write_types.map {|t| factory.optional_type(t) }).uniq,
532
+ factory.optional_type(init_type)
533
+ ]
534
+ else
535
+ triple
536
+ end
537
+ end
384
538
 
539
+ def interface_type?(type)
540
+ case
541
+ when type.is_a?(RBS::Types::Interface)
542
+ [
543
+ RBS::AST::TypeParam.new(name: :M, upper_bound: type, variance: :invariant, location: nil),
544
+ factory.type_var(:M)
545
+ ]
546
+ when type.is_a?(RBS::Types::Optional)
547
+ if (type = type.type).is_a?(RBS::Types::Interface)
385
548
  [
386
- type,
387
- type
388
- ]
389
- else
390
- [
391
- type,
392
- factory.optional_type(wtype)
549
+ RBS::AST::TypeParam.new(name: :M, upper_bound: type, variance: :invariant, location: nil),
550
+ factory.optional_type(factory.type_var(:M))
393
551
  ]
394
552
  end
395
- else
396
- type = base_type(field.type)
397
-
398
- if field.label == FieldDescriptorProto::Label::LABEL_REPEATED
399
- type = repeated_field_type(type)
400
- [type, type]
401
- else
402
- [type, factory.optional_type(type)]
403
- end
404
553
  end
405
554
  end
406
555
 
407
- def enum_base_class
408
- RBS::AST::Declarations::Class::Super.new(
409
- name: factory.type_name("::Protobuf::Enum"),
410
- args: [],
411
- location: nil
556
+ def add_field(members, name:, read_type:, write_types:, comment:)
557
+ members << RBS::AST::Members::AttrAccessor.new(
558
+ name: name,
559
+ type: read_type,
560
+ comment: comment,
561
+ location: nil,
562
+ annotations: [],
563
+ ivar_name: false,
564
+ kind: :instance
565
+ )
566
+
567
+ unless write_types.empty?
568
+ members << RBS::AST::Members::MethodDefinition.new(
569
+ name: :"#{name}=",
570
+ types:
571
+ write_types.map do |write_type|
572
+ if (type_param, type = interface_type?(write_type))
573
+ factory.method_type(
574
+ type: factory.function(type).update(
575
+ required_positionals:[factory.param(type)]
576
+ )
577
+ ).update(type_params: [type_param])
578
+ else
579
+ factory.method_type(
580
+ type: factory.function(write_type).update(
581
+ required_positionals:[factory.param(write_type)]
582
+ )
583
+ )
584
+ end
585
+ end,
586
+ annotations: [],
587
+ comment: comment,
588
+ location: nil,
589
+ overload: true,
590
+ kind: :instance
591
+ )
592
+ end
593
+
594
+ members << RBS::AST::Members::MethodDefinition.new(
595
+ name: :"#{name}!",
596
+ types: [
597
+ factory.method_type(
598
+ type: factory.function(factory.optional_type(read_type))
599
+ )
600
+ ],
601
+ annotations: [],
602
+ comment: nil,
603
+ location: nil,
604
+ overload: false,
605
+ kind: :instance
412
606
  )
413
607
  end
414
608
 
@@ -425,7 +619,7 @@ module RBSProtobuf
425
619
 
426
620
  RBS::AST::Declarations::Class.new(
427
621
  name: RBS::TypeName.new(name: enum_name.to_sym, namespace: prefix),
428
- super_class: enum_base_class(),
622
+ super_class: ENUM.super_class,
429
623
  type_params: factory.module_type_params(),
430
624
  members: [],
431
625
  comment: comment_for_path(source_code_info, path, options: enum_type.options),
@@ -514,79 +708,117 @@ module RBSProtobuf
514
708
  location: nil
515
709
  )
516
710
  end
517
- end
518
- end
519
711
 
520
- def extension_to_decl(extendee_name, extensions, prefix:, source_code_info:, path:)
521
- class_name = message_type(extendee_name).name
712
+ enum_instance_type = factory.instance_type(RBS::TypeName.new(name: enum_name.to_sym, namespace: RBS::Namespace.empty))
713
+ values_type = factory.alias_type(RBS::TypeName.new(name: :values, namespace: RBS::Namespace.empty))
522
714
 
523
- extensions.map do |field|
524
- field_name = field.name.to_sym
715
+ enum_decl.members << RBS::AST::Declarations::Alias.new(
716
+ name: TypeName("init"),
717
+ type_params: [],
718
+ type: factory.union_type(enum_instance_type, values_type),
719
+ annotations: [],
720
+ comment: RBS::AST::Comment.new(string: "The type of `#initialize` parameter.", location: nil),
721
+ location: nil
722
+ )
525
723
 
526
- RBS::AST::Declarations::Class.new(
527
- name: class_name,
528
- super_class: nil,
724
+ enum_decl.members << RBS::AST::Declarations::Alias.new(
725
+ name: TypeName("field_array"),
529
726
  type_params: [],
530
- location: nil,
727
+ type: FIELD_ARRAY[
728
+ enum_instance_type,
729
+ factory.union_type(enum_instance_type, values_type)
730
+ ],
731
+ annotations: [],
732
+ comment: RBS::AST::Comment.new(string: "The type of `repeated` field.", location: nil),
733
+ location: nil
734
+ )
735
+
736
+ enum_decl.members << RBS::AST::Declarations::Alias.new(
737
+ name: TypeName("field_hash"),
738
+ type_params: [RBS::AST::TypeParam.new(name: :KEY, variance: :invariant, upper_bound: nil, location: nil)],
739
+ type: FIELD_HASH[
740
+ factory.type_var(:KEY),
741
+ enum_instance_type,
742
+ factory.union_type(enum_instance_type, values_type)
743
+ ],
744
+ annotations: [],
745
+ comment: RBS::AST::Comment.new(string: "The type of `map` field.", location: nil),
746
+ location: nil
747
+ )
748
+
749
+ enum_decl.members << RBS::AST::Declarations::Alias.new(
750
+ name: TypeName("array"),
751
+ type_params: [],
752
+ type: RBS::BuiltinNames::Array.instance_type(factory.union_type(enum_instance_type, values_type)),
753
+ annotations: [],
531
754
  comment: nil,
532
- members: [],
533
- annotations: []
534
- ).tap do |class_decl|
535
- read_type, write_type = field_type(field, {})
755
+ location: nil
756
+ )
536
757
 
537
- if read_type == write_type
538
- class_decl.members << RBS::AST::Members::AttrAccessor.new(
539
- name: field_name,
540
- type: read_type,
541
- comment: nil,
542
- location: nil,
543
- annotations: [],
544
- ivar_name: false,
545
- kind: :instance
546
- )
547
- else
548
- class_decl.members << RBS::AST::Members::AttrReader.new(
549
- name: field_name,
550
- type: read_type,
551
- comment: nil,
552
- location: nil,
553
- annotations: [],
554
- ivar_name: false,
555
- kind: :instance
556
- )
758
+ enum_decl.members << RBS::AST::Declarations::Alias.new(
759
+ name: TypeName("hash"),
760
+ type_params: [RBS::AST::TypeParam.new(name: :KEY, variance: :invariant, upper_bound: nil, location: nil)],
761
+ type: RBS::BuiltinNames::Hash.instance_type(
762
+ factory.type_var(:KEY),
763
+ factory.union_type(enum_instance_type, values_type)
764
+ ),
765
+ annotations: [],
766
+ comment: nil,
767
+ location: nil
768
+ )
769
+ end
770
+ end
557
771
 
558
- class_decl.members << RBS::AST::Members::AttrWriter.new(
559
- name: field_name,
560
- type: write_type,
561
- comment: nil,
562
- location: nil,
563
- annotations: [],
564
- ivar_name: false,
565
- kind: :instance
772
+ def extension_to_decl(extension, prefix:, source_code_info:, path:)
773
+ class_name = message_type(extension.extendee).name
774
+
775
+ comment = comment_for_path(source_code_info, path, options: extension.options)
776
+ field_name = extension.name.to_sym
777
+
778
+ RBS::AST::Declarations::Class.new(
779
+ name: class_name,
780
+ super_class: nil,
781
+ type_params: [],
782
+ location: nil,
783
+ comment: nil,
784
+ members: [],
785
+ annotations: []
786
+ ).tap do |class_decl|
787
+ read_type, write_types, _ = field_type(extension, {})
788
+
789
+ add_field(class_decl.members, name: field_name, read_type: read_type, write_types: write_types, comment: comment)
790
+
791
+ class_decl.members << RBS::AST::Members::MethodDefinition.new(
792
+ name: :[],
793
+ types: [
794
+ factory.method_type(
795
+ type: factory.function(read_type).update(
796
+ required_positionals: [
797
+ factory.param(factory.literal_type(field_name))
798
+ ]
799
+ )
566
800
  )
567
- end
801
+ ],
802
+ annotations: [],
803
+ comment: nil,
804
+ location: nil,
805
+ overload: true,
806
+ kind: :instance
807
+ )
568
808
 
569
- class_decl.members << RBS::AST::Members::MethodDefinition.new(
570
- name: :[],
571
- types: [
809
+ class_decl.members << RBS::AST::Members::MethodDefinition.new(
810
+ name: :[]=,
811
+ types: [read_type, *write_types].map do |write_type|
812
+ if (type_param, type_var = interface_type?(write_type))
572
813
  factory.method_type(
573
- type: factory.function(read_type).update(
814
+ type: factory.function(type_var).update(
574
815
  required_positionals: [
575
- factory.param(factory.literal_type(field_name))
816
+ factory.param(factory.literal_type(field_name)),
817
+ factory.param(type_var)
576
818
  ]
577
819
  )
578
- )
579
- ],
580
- annotations: [],
581
- comment: nil,
582
- location: nil,
583
- overload: true,
584
- kind: :instance
585
- )
586
-
587
- class_decl.members << RBS::AST::Members::MethodDefinition.new(
588
- name: :[]=,
589
- types: [
820
+ ).update(type_params: [type_param])
821
+ else
590
822
  factory.method_type(
591
823
  type: factory.function(write_type).update(
592
824
  required_positionals: [
@@ -595,14 +827,14 @@ module RBSProtobuf
595
827
  ]
596
828
  )
597
829
  )
598
- ],
599
- annotations: [],
600
- comment: nil,
601
- location: nil,
602
- overload: true,
603
- kind: :instance
604
- )
605
- end
830
+ end
831
+ end,
832
+ annotations: [],
833
+ comment: nil,
834
+ location: nil,
835
+ overload: true,
836
+ kind: :instance
837
+ )
606
838
  end
607
839
  end
608
840