Skip to content

Commit

Permalink
Implement optional semantics for proto3
Browse files Browse the repository at this point in the history
This commit adds support for the proto3 optional keyword.

Proto3 optional fields will have the label "optional" added,
to match the behaviour of proto2 optional fields.

Fields in proto3 that are not marked as optional are unaffected
and will continue to have no label (unless they are repeated, in
which case they will continue to have the "repeated" label).
  • Loading branch information
ezimanyi committed Jun 11, 2020
1 parent 4f7232b commit f042560
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 6 deletions.
3 changes: 3 additions & 0 deletions plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ type PluginOptions struct {
ExcludePatterns []*regexp.Regexp
}

var SupportedFeatures = uint64(plugin_go.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL)

// Plugin describes a protoc code generate plugin. It's an implementation of Plugin from github.com/pseudomuto/protokit
type Plugin struct{}

Expand Down Expand Up @@ -56,6 +58,7 @@ func (p *Plugin) Generate(r *plugin_go.CodeGeneratorRequest) (*plugin_go.CodeGen
Name: proto.String(options.OutputFile),
Content: proto.String(string(output)),
})
resp.SupportedFeatures = proto.Uint64(SupportedFeatures)

return resp, nil
}
Expand Down
8 changes: 4 additions & 4 deletions template.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ func parseFileExtension(pe *protokit.ExtensionDescriptor) *FileExtension {
LongName: pe.GetLongName(),
FullName: pe.GetFullName(),
Description: description(pe.GetComments().String()),
Label: labelName(pe.GetLabel(), pe.IsProto3()),
Label: labelName(pe.GetLabel(), pe.IsProto3(), pe.GetProto3Optional()),
Type: t,
LongType: lt,
FullType: ft,
Expand Down Expand Up @@ -473,7 +473,7 @@ func parseMessageField(pf *protokit.FieldDescriptor) *MessageField {
m := &MessageField{
Name: pf.GetName(),
Description: description(pf.GetComments().String()),
Label: labelName(pf.GetLabel(), pf.IsProto3()),
Label: labelName(pf.GetLabel(), pf.IsProto3(), pf.GetProto3Optional()),
Type: t,
LongType: lt,
FullType: ft,
Expand Down Expand Up @@ -532,8 +532,8 @@ func baseName(name string) string {
return parts[len(parts)-1]
}

func labelName(lbl descriptor.FieldDescriptorProto_Label, proto3 bool) string {
if proto3 && lbl != descriptor.FieldDescriptorProto_LABEL_REPEATED {
func labelName(lbl descriptor.FieldDescriptorProto_Label, proto3 bool, proto3Opt bool) string {
if proto3 && !proto3Opt && lbl != descriptor.FieldDescriptorProto_LABEL_REPEATED {
return ""
}

Expand Down
3 changes: 1 addition & 2 deletions template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,8 +340,7 @@ func TestFieldPropertiesProto3Optional(t *testing.T) {
field = findField("name", msg)
require.Equal(t, "name", field.Name)
require.Equal(t, "The name of the cookie.", field.Description)
//TODO(ezimanyi): This is a proto3 optional field, and should have label "optional"
require.Equal(t, "", field.Label)
require.Equal(t, "optional", field.Label)
require.Equal(t, "string", field.Type)
require.Equal(t, "string", field.LongType)
require.Equal(t, "string", field.FullType)
Expand Down

0 comments on commit f042560

Please sign in to comment.