lib/tapioca/dsl/compilers/protobuf.rb in tapioca-0.9.4 vs lib/tapioca/dsl/compilers/protobuf.rb in tapioca-0.10.0
- old
+ new
@@ -88,37 +88,74 @@
if constant == Google::Protobuf::RepeatedField
create_type_members(klass, "Elem")
elsif constant == Google::Protobuf::Map
create_type_members(klass, "Key", "Value")
else
- descriptor = T.let(T.unsafe(constant).descriptor, Google::Protobuf::Descriptor)
- descriptor.each_oneof { |oneof| create_oneof_method(klass, oneof) }
- fields = descriptor.map { |desc| create_descriptor_method(klass, desc) }
- fields.sort_by!(&:name)
+ descriptor = T.unsafe(constant).descriptor
- parameters = fields.map do |field|
- create_kw_opt_param(field.name, type: field.init_type, default: field.default)
- end
+ case descriptor
+ when Google::Protobuf::EnumDescriptor
+ descriptor.to_h.each do |sym, val|
+ klass.create_constant(sym.to_s, value: val.to_s)
+ end
- if fields.all? { |field| FIELD_RE.match?(field.name) }
- klass.create_method("initialize", parameters: parameters, return_type: "void")
+ klass.create_method(
+ "lookup",
+ parameters: [create_param("number", type: "Integer")],
+ return_type: "T.nilable(Symbol)",
+ class_method: true,
+ )
+ klass.create_method(
+ "resolve",
+ parameters: [create_param("symbol", type: "Symbol")],
+ return_type: "T.nilable(Integer)",
+ class_method: true,
+ )
+ klass.create_method(
+ "descriptor",
+ return_type: "Google::Protobuf::EnumDescriptor",
+ class_method: true,
+ )
+ when Google::Protobuf::Descriptor
+ descriptor.each_oneof { |oneof| create_oneof_method(klass, oneof) }
+ fields = descriptor.map { |desc| create_descriptor_method(klass, desc) }
+ fields.sort_by!(&:name)
+
+ parameters = fields.map do |field|
+ create_kw_opt_param(field.name, type: field.init_type, default: field.default)
+ end
+
+ if fields.all? { |field| FIELD_RE.match?(field.name) }
+ klass.create_method("initialize", parameters: parameters, return_type: "void")
+ else
+ # One of the fields has an incorrect name for a named parameter so creating the default initialize for
+ # it would create a RBI with a syntax error.
+ # The workaround is to create an initialize that takes a **kwargs instead.
+ kwargs_parameter = create_kw_rest_param("fields", type: "T.untyped")
+ klass.create_method("initialize", parameters: [kwargs_parameter], return_type: "void")
+ end
else
- # One of the fields has an incorrect name for a named parameter so creating the default initialize for
- # it would create a RBI with a syntax error.
- # The workaround is to create an initialize that takes a **kwargs instead.
- kwargs_parameter = create_kw_rest_param("fields", type: "T.untyped")
- klass.create_method("initialize", parameters: [kwargs_parameter], return_type: "void")
+ raise TypeError, "Unexpected descriptor class: #{descriptor.class.name}"
end
end
end
end
- sig { override.returns(T::Enumerable[Module]) }
- def self.gather_constants
- marker = Google::Protobuf::MessageExts::ClassMethods
- results = T.cast(ObjectSpace.each_object(marker).to_a, T::Array[Module])
- results.any? ? results + [Google::Protobuf::RepeatedField, Google::Protobuf::Map] : []
+ class << self
+ extend T::Sig
+
+ sig { override.returns(T::Enumerable[Module]) }
+ def gather_constants
+ marker = Google::Protobuf::MessageExts::ClassMethods
+
+ enum_modules = ObjectSpace.each_object(Google::Protobuf::EnumDescriptor).map do |desc|
+ T.cast(desc, Google::Protobuf::EnumDescriptor).enummodule
+ end
+
+ results = T.cast(ObjectSpace.each_object(marker).to_a, T::Array[Module]).concat(enum_modules)
+ results.any? ? results + [Google::Protobuf::RepeatedField, Google::Protobuf::Map] : []
+ end
end
private
sig { params(klass: RBI::Scope, names: String).void }
@@ -136,11 +173,17 @@
).returns(String)
end
def type_of(descriptor)
case descriptor.type
when :enum
- descriptor.subtype.enummodule.name
+ # According to https://developers.google.com/protocol-buffers/docs/reference/ruby-generated#enum
+ # > You may assign either a number or a symbol to an enum field.
+ # > When reading the value back, it will be a symbol if the enum
+ # > value is known, or a number if it is unknown. Since proto3 uses
+ # > open enum semantics, any number may be assigned to an enum
+ # > field, even if it was not defined in the enum.
+ "T.any(Symbol, Integer)"
when :message
descriptor.subtype.msgclass.name
when :int32, :int64, :uint32, :uint64
"Integer"
when :double, :float
@@ -177,11 +220,11 @@
default_args << value_type if [:enum, :message].include?(value.type)
Field.new(
name: descriptor.name,
type: type,
- init_type: "T.any(#{type}, T::Hash[#{key_type}, #{value_type}])",
+ init_type: "T.nilable(T.any(#{type}, T::Hash[#{key_type}, #{value_type}]))",
default: "Google::Protobuf::Map.new(#{default_args.join(", ")})"
)
else
elem_type = type_of(descriptor)
type = "Google::Protobuf::RepeatedField[#{elem_type}]"
@@ -190,22 +233,23 @@
default_args << elem_type if [:enum, :message].include?(descriptor.type)
Field.new(
name: descriptor.name,
type: type,
- init_type: "T.any(#{type}, T::Array[#{elem_type}])",
+ init_type: "T.nilable(T.any(#{type}, T::Array[#{elem_type}]))",
default: "Google::Protobuf::RepeatedField.new(#{default_args.join(", ")})"
)
end
else
type = type_of(descriptor)
- type = as_nilable_type(type) if nilable_descriptor?(descriptor)
+ nilable_type = as_nilable_type(type)
+ type = nilable_type if nilable_descriptor?(descriptor)
Field.new(
name: descriptor.name,
type: type,
- init_type: type,
+ init_type: nilable_type,
default: "nil"
)
end
end
@@ -224,10 +268,10 @@
)
klass.create_method(
"#{field.name}=",
parameters: [create_param("value", type: field.type)],
- return_type: field.type
+ return_type: "void"
)
field
end