protobuf
protobuf copied to clipboard
generated typespec doesn't seem to take `proto3_optional: true` into account
Just to add more context to the issue, here is a snippet generating typespecs for a message having both proto3_optional?: true
and proto3_optional?: false
:
iex> message_props = %MessageProps{
field_props: %{
1 => %FieldProps{name_atom: :foo, type: :int32, proto3_optional?: true},
2 => %FieldProps{name_atom: :bar, type: :int32, proto3_optional?: false}
},
oneof: []
}
iex> quoted = Typespecs.quoted_message_typespec(message_props)
iex> Macro.to_string(quoted)
%__MODULE__{
foo: integer(),
bar: integer()
}
@JerzyDziala Since we can't have a optional(:field)
typespec for a structure, I am not sure what the typespec should be for the optional fields.
According to Elixir docs, having a key in a Struct type means the key is required:
| %SomeStruct{key: value_type} # struct with required key :key of value_type`
A naive idea is to use multiple definitions, but it may rendered too many permutations:
iex> quoted = Typespecs.quoted_message_typespec_v2(message_props)
iex> Macro.to_string(quoted)
%__MODULE__{foo: integer(), bar: integer()} | %__MODULE__{foo: integer()}
Since we can't have a optional(:field) typespec for a structure, I am not sure what the typespec should be for the optional fields.
When an optional field is not set it will be set to the value nil
, so the field will always be present on the struct. The fix to the typespec would be to add | nil
to the field type:
%__MODULE__{
foo: integer() | nil,
bar: integer()
}
@antedeguemon any chance you want to work on a PR for this? 🙃
@whatyouhide sure thing! I will give it a try this week. Thank you for the support!