cmd/protoc-gen-go: add support for map fields
Generate the proper map[key]value type for map fields.
Include the protobuf_key and protobuf_val field tags.
Do not generate the map entry structs.
Fix an initialization order bug in protogen: While proto files cannot
contain circular dependencies, a single file can contain dependency
cycles. First create types for all the descriptors in a file, then add
in references (currently just field->message and field->enum) in a
second pass.
Change-Id: Ifedfa657d8dbb00413ba493adee1119b19c1b773
Reviewed-on: https://go-review.googlesource.com/135355
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/protogen/protogen.go b/protogen/protogen.go
index 5e1cd83..0064afa 100644
--- a/protogen/protogen.go
+++ b/protogen/protogen.go
@@ -400,6 +400,9 @@
for i, edescs := 0, desc.Enums(); i < edescs.Len(); i++ {
f.Enums = append(f.Enums, newEnum(gen, f, nil, edescs.Get(i)))
}
+ for _, message := range f.Messages {
+ message.init(gen)
+ }
return f, nil
}
@@ -507,6 +510,20 @@
return message, nil
}
+func (message *Message) init(gen *Plugin) error {
+ for _, child := range message.Messages {
+ if err := child.init(gen); err != nil {
+ return err
+ }
+ }
+ for _, field := range message.Fields {
+ if err := field.init(gen); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
// A Field describes a message field.
type Field struct {
Desc protoreflect.FieldDescriptor
@@ -530,23 +547,28 @@
},
Path: pathAppend(message.Path, messageFieldField, int32(desc.Index())),
}
+ return field, nil
+}
+
+func (field *Field) init(gen *Plugin) error {
+ desc := field.Desc
switch desc.Kind() {
case protoreflect.MessageKind, protoreflect.GroupKind:
mname := desc.MessageType().FullName()
message, ok := gen.messagesByName[mname]
if !ok {
- return nil, fmt.Errorf("field %v: no descriptor for type %v", desc.FullName(), mname)
+ return fmt.Errorf("field %v: no descriptor for type %v", desc.FullName(), mname)
}
field.MessageType = message
case protoreflect.EnumKind:
- ename := desc.EnumType().FullName()
+ ename := field.Desc.EnumType().FullName()
enum, ok := gen.enumsByName[ename]
if !ok {
- return nil, fmt.Errorf("field %v: no descriptor for enum %v", desc.FullName(), ename)
+ return fmt.Errorf("field %v: no descriptor for enum %v", desc.FullName(), ename)
}
field.EnumType = enum
}
- return field, nil
+ return nil
}
// An Enum describes an enum.