Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate enum module definitions #1079

Merged
merged 15 commits into from Aug 15, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 27 additions & 14 deletions lib/tapioca/compilers/dsl/protobuf.rb
Expand Up @@ -78,23 +78,36 @@ def decorate(root, constant)
elsif constant == Google::Protobuf::Map
create_type_members(klass, "Key", "Value")
else
descriptor = T.let(T.unsafe(constant).descriptor, Google::Protobuf::Descriptor)
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)
descriptor = T.let(T.unsafe(constant).descriptor,
T.any(Google::Protobuf::Descriptor, Google::Protobuf::EnumDescriptor))

if descriptor.is_a?(Google::Protobuf::EnumDescriptor)
descriptor.to_h.each do |sym, val|
klass.create_constant(sym.to_s, value: val.to_s)
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also define the lookup and resolve methods that are sig { params(number: Integer).returns(T.nilable(Symbol) } and sig { params(symbol: Symbol).returns(T.nilable(Integer) } respectively?

else
paracycle marked this conversation as resolved.
Show resolved Hide resolved
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

klass.create_method("initialize", parameters: parameters, return_type: "void")
end

klass.create_method("initialize", parameters: parameters, return_type: "void")
end
end
end

sig { override.returns(T::Enumerable[Module]) }
def gather_constants
marker = Google::Protobuf::MessageExts::ClassMethods
results = T.cast(ObjectSpace.each_object(marker).to_a, T::Array[Module])

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

Expand All @@ -117,7 +130,7 @@ def create_type_members(klass, *names)
def type_of(descriptor)
case descriptor.type
when :enum
descriptor.subtype.enummodule.name
"T.any(Symbol, Integer)"
paracycle marked this conversation as resolved.
Show resolved Hide resolved
when :message
descriptor.subtype.msgclass.name
when :int32, :int64, :uint32, :uint64
Expand Down Expand Up @@ -153,7 +166,7 @@ def field_of(descriptor)
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}]))",
paracycle marked this conversation as resolved.
Show resolved Hide resolved
default: "Google::Protobuf::Map.new(#{default_args.join(", ")})"
)
else
Expand All @@ -166,7 +179,7 @@ def field_of(descriptor)
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
Expand All @@ -176,7 +189,7 @@ def field_of(descriptor)
Field.new(
name: descriptor.name,
type: type,
init_type: type,
init_type: "T.nilable(#{type})",
default: "nil"
)
end
Expand All @@ -199,7 +212,7 @@ def create_descriptor_method(klass, desc)
klass.create_method(
"#{field.name}=",
parameters: [create_param("value", type: field.type)],
return_type: field.type
return_type: "void"
)

field
Expand Down
67 changes: 39 additions & 28 deletions spec/tapioca/compilers/dsl/protobuf_spec.rb
Expand Up @@ -62,19 +62,19 @@ class Tapioca::Compilers::Dsl::ProtobufSpec < DslSpec
# typed: strong

class Cart
sig { params(customer_id: Integer, shop_id: Integer).void }
sig { params(customer_id: T.nilable(Integer), shop_id: T.nilable(Integer)).void }
def initialize(customer_id: nil, shop_id: nil); end

sig { returns(Integer) }
def customer_id; end

sig { params(value: Integer).returns(Integer) }
sig { params(value: Integer).void }
def customer_id=(value); end

sig { returns(Integer) }
def shop_id; end

sig { params(value: Integer).returns(Integer) }
sig { params(value: Integer).void }
def shop_id=(value); end
end
RBI
Expand All @@ -99,13 +99,13 @@ def shop_id=(value); end
# typed: strong

class Cart
sig { params(events: String).void }
sig { params(events: T.nilable(String)).void }
def initialize(events: nil); end

sig { returns(String) }
def events; end

sig { params(value: String).returns(String) }
sig { params(value: String).void }
def events=(value); end
end
RBI
Expand Down Expand Up @@ -133,13 +133,13 @@ def events=(value); end
# typed: strong

class Cart
sig { params(cart_item_index: Google::Protobuf::UInt64Value).void }
sig { params(cart_item_index: T.nilable(Google::Protobuf::UInt64Value)).void }
def initialize(cart_item_index: nil); end

sig { returns(Google::Protobuf::UInt64Value) }
def cart_item_index; end

sig { params(value: Google::Protobuf::UInt64Value).returns(Google::Protobuf::UInt64Value) }
sig { params(value: Google::Protobuf::UInt64Value).void }
def cart_item_index=(value); end
end
RBI
Expand Down Expand Up @@ -173,17 +173,28 @@ def cart_item_index=(value); end
# typed: strong

class Cart
sig { params(value_type: Cart::VALUE_TYPE).void }
sig { params(value_type: T.nilable(T.any(Symbol, Integer))).void }
def initialize(value_type: nil); end

sig { returns(Cart::VALUE_TYPE) }
sig { returns(T.any(Symbol, Integer)) }
def value_type; end

sig { params(value: Cart::VALUE_TYPE).returns(Cart::VALUE_TYPE) }
sig { params(value: T.any(Symbol, Integer)).void }
def value_type=(value); end
end
RBI

expected_enum_rbi = <<~RBI
# typed: strong

module Cart::VALUE_TYPE
FIXED_AMOUNT = 1
NULL = 0
PERCENTAGE = 2
end
RBI

assert_equal(expected_enum_rbi, rbi_for("Cart::VALUE_TYPE"))
assert_equal(expected, rbi_for(:Cart))
end

Expand Down Expand Up @@ -213,13 +224,13 @@ def value_type=(value); end
# typed: strong

class Cart
sig { params(value_type: Cart::MYVALUETYPE).void }
sig { params(value_type: T.nilable(T.any(Symbol, Integer))).void }
def initialize(value_type: nil); end

sig { returns(Cart::MYVALUETYPE) }
sig { returns(T.any(Symbol, Integer)) }
def value_type; end

sig { params(value: Cart::MYVALUETYPE).returns(Cart::MYVALUETYPE) }
sig { params(value: T.any(Symbol, Integer)).void }
def value_type=(value); end
end
RBI
Expand Down Expand Up @@ -247,19 +258,19 @@ def value_type=(value); end
# typed: strong

class Cart
sig { params(customer_ids: T.any(Google::Protobuf::RepeatedField[Integer], T::Array[Integer]), indices: T.any(Google::Protobuf::RepeatedField[Google::Protobuf::UInt64Value], T::Array[Google::Protobuf::UInt64Value])).void }
sig { params(customer_ids: T.nilable(T.any(Google::Protobuf::RepeatedField[Integer], T::Array[Integer])), indices: T.nilable(T.any(Google::Protobuf::RepeatedField[Google::Protobuf::UInt64Value], T::Array[Google::Protobuf::UInt64Value]))).void }
def initialize(customer_ids: Google::Protobuf::RepeatedField.new(:int32), indices: Google::Protobuf::RepeatedField.new(:message, Google::Protobuf::UInt64Value)); end

sig { returns(Google::Protobuf::RepeatedField[Integer]) }
def customer_ids; end

sig { params(value: Google::Protobuf::RepeatedField[Integer]).returns(Google::Protobuf::RepeatedField[Integer]) }
sig { params(value: Google::Protobuf::RepeatedField[Integer]).void }
def customer_ids=(value); end

sig { returns(Google::Protobuf::RepeatedField[Google::Protobuf::UInt64Value]) }
def indices; end

sig { params(value: Google::Protobuf::RepeatedField[Google::Protobuf::UInt64Value]).returns(Google::Protobuf::RepeatedField[Google::Protobuf::UInt64Value]) }
sig { params(value: Google::Protobuf::RepeatedField[Google::Protobuf::UInt64Value]).void }
def indices=(value); end
end
RBI
Expand Down Expand Up @@ -287,19 +298,19 @@ def indices=(value); end
# typed: strong

class Cart
sig { params(customers: T.any(Google::Protobuf::Map[String, Integer], T::Hash[String, Integer]), stores: T.any(Google::Protobuf::Map[String, Google::Protobuf::UInt64Value], T::Hash[String, Google::Protobuf::UInt64Value])).void }
sig { params(customers: T.nilable(T.any(Google::Protobuf::Map[String, Integer], T::Hash[String, Integer])), stores: T.nilable(T.any(Google::Protobuf::Map[String, Google::Protobuf::UInt64Value], T::Hash[String, Google::Protobuf::UInt64Value]))).void }
def initialize(customers: Google::Protobuf::Map.new(:string, :int32), stores: Google::Protobuf::Map.new(:string, :message, Google::Protobuf::UInt64Value)); end

sig { returns(Google::Protobuf::Map[String, Integer]) }
def customers; end

sig { params(value: Google::Protobuf::Map[String, Integer]).returns(Google::Protobuf::Map[String, Integer]) }
sig { params(value: Google::Protobuf::Map[String, Integer]).void }
def customers=(value); end

sig { returns(Google::Protobuf::Map[String, Google::Protobuf::UInt64Value]) }
def stores; end

sig { params(value: Google::Protobuf::Map[String, Google::Protobuf::UInt64Value]).returns(Google::Protobuf::Map[String, Google::Protobuf::UInt64Value]) }
sig { params(value: Google::Protobuf::Map[String, Google::Protobuf::UInt64Value]).void }
def stores=(value); end
end
RBI
Expand Down Expand Up @@ -334,47 +345,47 @@ def stores=(value); end
rbi_output = rbi_for(:Cart)

assert_includes(rbi_output, indented(<<~RBI, 2))
sig { params(value: T::Boolean).returns(T::Boolean) }
sig { params(value: T::Boolean).void }
def bool_value=(value); end
RBI

assert_includes(rbi_output, indented(<<~RBI, 2))
sig { params(value: String).returns(String) }
sig { params(value: String).void }
def byte_value=(value); end
RBI

assert_includes(rbi_output, indented(<<~RBI, 2))
sig { params(value: Integer).returns(Integer) }
sig { params(value: Integer).void }
def customer_id=(value); end
RBI

assert_includes(rbi_output, indented(<<~RBI, 2))
sig { params(value: Integer).returns(Integer) }
sig { params(value: Integer).void }
def id=(value); end
RBI

assert_includes(rbi_output, indented(<<~RBI, 2))
sig { params(value: Integer).returns(Integer) }
sig { params(value: Integer).void }
def item_id=(value); end
RBI

assert_includes(rbi_output, indented(<<~RBI, 2))
sig { params(value: Float).returns(Float) }
sig { params(value: Float).void }
def money_value=(value); end
RBI

assert_includes(rbi_output, indented(<<~RBI, 2))
sig { params(value: Float).returns(Float) }
sig { params(value: Float).void }
def number_value=(value); end
RBI

assert_includes(rbi_output, indented(<<~RBI, 2))
sig { params(value: Integer).returns(Integer) }
sig { params(value: Integer).void }
def shop_id=(value); end
RBI

assert_includes(rbi_output, indented(<<~RBI, 2))
sig { params(value: String).returns(String) }
sig { params(value: String).void }
def string_value=(value); end
RBI
end
Expand Down