+ face := gogoproto.IsFace(file.FileDescriptorProto, msg.DescriptorProto)
+ for _, field := range msg.GetField() {
+ if len(field.GetDefaultValue()) > 0 {
+ if !getters {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot have a default value and not have a getter method", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ os.Exit(1)
+ }
+ if face {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot have a default value be in a face", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ os.Exit(1)
+ }
+ }
+ if gogoproto.IsNullable(field) {
+ continue
+ }
+ if len(field.GetDefaultValue()) > 0 {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be non-nullable and have a default value", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ os.Exit(1)
+ }
+ if !field.IsMessage() && !gogoproto.IsCustomType(field) {
+ if field.IsRepeated() {
+ fmt.Fprintf(os.Stderr, "WARNING: field %v.%v is a repeated non-nullable native type, nullable=false has no effect\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ } else if proto3 {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v is a native type and in proto3 syntax with nullable=false there exists conflicting implementations when encoding zero values", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ os.Exit(1)
+ }
+ if field.IsBytes() {
+ fmt.Fprintf(os.Stderr, "WARNING: field %v.%v is a non-nullable bytes type, nullable=false has no effect\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ if len(enum.Value) == 0 || enum.Value[0].GetNumber() != 0 {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be non-nullable and be an enum type %v which does not start with zero", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name), enum.GetName())
+ os.Exit(1)
+ }
+ }
+ }
+ for _, e := range file.GetExtension() {
+ if !gogoproto.IsNullable(e) {
+ fmt.Fprintf(os.Stderr, "ERROR: extended field %v cannot be nullable %v", generator.CamelCase(e.GetName()), generator.CamelCase(*e.Name))
+ if !gogoproto.IsEnumStringer(file.FileDescriptorProto, enum.EnumDescriptorProto) {
+ continue
+ }
+ if gogoproto.IsGoEnumStringer(file.FileDescriptorProto, enum.EnumDescriptorProto) {
+ panic("Go enum stringer conflicts with new enumstringer plugin: please use gogoproto.goproto_enum_stringer or gogoproto.goproto_enum_string_all and set it to false")
+ face := gogoproto.IsFace(file.FileDescriptorProto, msg.DescriptorProto)
+ for _, field := range msg.GetField() {
+ if field.OneofIndex == nil {
+ continue
+ }
+ if face {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in a face and oneof\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ os.Exit(1)
+ }
+ if gogoproto.IsEmbed(field) {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and an embedded field\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ os.Exit(1)
+ }
+ if !gogoproto.IsNullable(field) {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and a non-nullable field\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+ os.Exit(1)
+ }
+ if gogoproto.IsUnion(file.FileDescriptorProto, msg.DescriptorProto) {
+ fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and in an union (deprecated)\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
+// The different types of fields in a message and how to actually print them
+// Most of the logic for generateMessage is in the methods of these types.
+//
+// Note that the content of the field is irrelevant, a simpleField can contain
+// anything from a scalar to a group (which is just a message).
+//
+// Extension fields (and message sets) are however handled separately.
+//
+// simpleField - a field that is neiter weak nor oneof, possibly repeated
+// oneofField - field containing list of subfields:
+// - oneofSubField - a field within the oneof
+
+// msgCtx contains the context for the generator functions.
+type msgCtx struct {
+ goName string // Go struct name of the message, e.g. MessageName
+ message *Descriptor // The descriptor for the message
+}
+
+// fieldCommon contains data common to all types of fields.
+type fieldCommon struct {
+ goName string // Go name of field, e.g. "FieldName" or "Descriptor_"
+ protoName string // Name of field in proto language, e.g. "field_name" or "descriptor"
+ getterName string // Name of the getter, e.g. "GetFieldName" or "GetDescriptor_"
+ goType string // The Go type as a string, e.g. "*int32" or "*OtherMessage"
+ tags string // The tag string/annotation for the type, e.g. `protobuf:"varint,8,opt,name=region_id,json=regionId"`
+ fullPath string // The full path of the field as used by Annotate etc, e.g. "4,0,2,0"
+ protoField *descriptor.FieldDescriptorProto // gogo. Passing in the fieldDescriptor in for gogo options. TODO rethink this, we might need a better way of getting options.
+}
+
+// getProtoName gets the proto name of a field, e.g. "field_name" or "descriptor".
+func (f *fieldCommon) getProtoName() string {
+ return f.protoName
+}
+
+// getGoType returns the go type of the field as a string, e.g. "*int32".
+func (f *fieldCommon) getGoType() string {
+ return f.goType
+}
+
+// simpleField is not weak, not a oneof, not an extension. Can be required, optional or repeated.
+type simpleField struct {
+ fieldCommon
+ protoTypeName string // Proto type name, empty if primitive, e.g. ".google.protobuf.Duration"
+ protoType descriptor.FieldDescriptorProto_Type // Actual type enum value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64
+ deprecated string // Deprecation comment, if any, e.g. "// Deprecated: Do not use."
+ getterDef string // Default for getters, e.g. "nil", `""` or "Default_MessageType_FieldName"
+ protoDef string // Default value as defined in the proto file, e.g "yoshi" or "5"
+ comment string // The full comment for the field, e.g. "// Useful information"
+}
+
+// decl prints the declaration of the field in the struct (if any).
+func (f *simpleField) decl(g *Generator, mc *msgCtx) {
+ g.Fail("illegal default value: ", df.getProtoName(), " in ", mc.message.GetName(), " is not nullable and is thus not allowed to have a default value")
+ g.P(fmt.Sprintf(`// %sClient is the client API for %s service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.`, servName, servName))
+
+ // Client interface.
+ if deprecated {
+ g.P("//")
+ g.P(deprecationComment)
+ }
+ g.P("type ", servName, "Client interface {")
+ for i, method := range service.Method {
+ g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service.
+func genService(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile, service *protogen.Service) {
+ clientName := service.GoName + "Client"
+
+ g.P("// ", clientName, " is the client API for ", service.GoName, " service.")
+ g.P("//")
+ g.P("// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.")
+
+ // Client interface.
+ if service.Desc.Options().(*descriptorpb.ServiceOptions).GetDeprecated() {