rbs_protobuf 0.3.0 → 1.0.0

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