|
|
@@ -52,9 +52,9 @@ const (
|
|
|
// XXX_WellKnownType methods on well-known types.
|
|
|
generateWKTMarkerMethods = false
|
|
|
|
|
|
- // generateMessateStateFields specifies whether to generate an unexported
|
|
|
+ // generateMessageStateFields specifies whether to generate an unexported
|
|
|
// protoimpl.MessageState as the first field.
|
|
|
- generateMessateStateFields = true
|
|
|
+ generateMessageStateFields = true
|
|
|
|
|
|
// generateNoUnkeyedLiteralFields specifies whether to generate
|
|
|
// the XXX_NoUnkeyedLiteral field.
|
|
|
@@ -98,6 +98,28 @@ type goImportPath interface {
|
|
|
Ident(string) protogen.GoIdent
|
|
|
}
|
|
|
|
|
|
+// Names of messages and enums for which we will generate XXX_WellKnownType methods.
|
|
|
+var wellKnownTypes = map[protoreflect.FullName]bool{
|
|
|
+ "google.protobuf.Any": true,
|
|
|
+ "google.protobuf.Duration": true,
|
|
|
+ "google.protobuf.Empty": true,
|
|
|
+ "google.protobuf.Struct": true,
|
|
|
+ "google.protobuf.Timestamp": true,
|
|
|
+
|
|
|
+ "google.protobuf.BoolValue": true,
|
|
|
+ "google.protobuf.BytesValue": true,
|
|
|
+ "google.protobuf.DoubleValue": true,
|
|
|
+ "google.protobuf.FloatValue": true,
|
|
|
+ "google.protobuf.Int32Value": true,
|
|
|
+ "google.protobuf.Int64Value": true,
|
|
|
+ "google.protobuf.ListValue": true,
|
|
|
+ "google.protobuf.NullValue": true,
|
|
|
+ "google.protobuf.StringValue": true,
|
|
|
+ "google.protobuf.UInt32Value": true,
|
|
|
+ "google.protobuf.UInt64Value": true,
|
|
|
+ "google.protobuf.Value": true,
|
|
|
+}
|
|
|
+
|
|
|
type fileInfo struct {
|
|
|
*protogen.File
|
|
|
|
|
|
@@ -353,7 +375,7 @@ func genEnum(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, enum
|
|
|
g.P("}")
|
|
|
g.P()
|
|
|
|
|
|
- genReflectEnum(gen, g, f, enum)
|
|
|
+ genEnumReflectMethods(gen, g, f, enum)
|
|
|
|
|
|
// UnmarshalJSON method.
|
|
|
if generateEnumJSONMethods && enum.Desc.Syntax() == protoreflect.Proto2 {
|
|
|
@@ -382,7 +404,11 @@ func genEnum(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, enum
|
|
|
g.P()
|
|
|
}
|
|
|
|
|
|
- genWellKnownType(g, "", enum.GoIdent, enum.Desc)
|
|
|
+ // XXX_WellKnownType method.
|
|
|
+ if generateWKTMarkerMethods && wellKnownTypes[enum.Desc.FullName()] {
|
|
|
+ g.P("func (", enum.GoIdent, `) XXX_WellKnownType() string { return "`, enum.Desc.Name(), `" }`)
|
|
|
+ g.P()
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// enumLegacyName returns the name used by the v1 proto package.
|
|
|
@@ -413,64 +439,78 @@ func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, me
|
|
|
}
|
|
|
g.Annotate(message.GoIdent.GoName, message.Location)
|
|
|
g.P("type ", message.GoIdent, " struct {")
|
|
|
+ genMessageFields(g, f, message)
|
|
|
+ g.P("}")
|
|
|
+ g.P()
|
|
|
+
|
|
|
+ genDefaultConsts(g, message)
|
|
|
+ genMessageMethods(gen, g, f, message)
|
|
|
+ genOneofWrapperTypes(gen, g, f, message)
|
|
|
+}
|
|
|
+
|
|
|
+func genMessageFields(g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message) {
|
|
|
sf := f.allMessageFieldsByPtr[message]
|
|
|
- if generateMessateStateFields {
|
|
|
+ if generateMessageStateFields {
|
|
|
g.P("state ", protoimplPackage.Ident("MessageState"))
|
|
|
sf.append("state")
|
|
|
}
|
|
|
- hasWeak := false
|
|
|
for _, field := range message.Fields {
|
|
|
- if field.Oneof != nil {
|
|
|
- // It would be a bit simpler to iterate over the oneofs below,
|
|
|
- // but generating the field here keeps the contents of the Go
|
|
|
- // struct in the same order as the contents of the source
|
|
|
- // .proto file.
|
|
|
- oneof := field.Oneof
|
|
|
- if field != oneof.Fields[0] {
|
|
|
- continue // already generated oneof field for first entry
|
|
|
- }
|
|
|
- if g.PrintLeadingComments(oneof.Location) {
|
|
|
- g.P("//")
|
|
|
- }
|
|
|
- g.P("// Types that are valid to be assigned to ", oneofFieldName(oneof), ":")
|
|
|
- for _, field := range oneof.Fields {
|
|
|
- g.PrintLeadingComments(field.Location)
|
|
|
- g.P("//\t*", fieldOneofType(field))
|
|
|
- }
|
|
|
- g.Annotate(message.GoIdent.GoName+"."+oneofFieldName(oneof), oneof.Location)
|
|
|
- g.P(oneofFieldName(oneof), " ", oneofInterfaceName(oneof), " `protobuf_oneof:\"", oneof.Desc.Name(), "\"`")
|
|
|
- sf.append(oneofFieldName(oneof))
|
|
|
- continue
|
|
|
- }
|
|
|
- g.PrintLeadingComments(field.Location)
|
|
|
- goType, pointer := fieldGoType(g, field)
|
|
|
- if pointer {
|
|
|
- goType = "*" + goType
|
|
|
+ genMessageField(g, message, field, sf)
|
|
|
+ }
|
|
|
+ genMessageInternalFields(g, message, sf)
|
|
|
+}
|
|
|
+
|
|
|
+func genMessageField(g *protogen.GeneratedFile, message *protogen.Message, field *protogen.Field, sf *structFields) {
|
|
|
+ if oneof := field.Oneof; oneof != nil {
|
|
|
+ // It would be a bit simpler to iterate over the oneofs below,
|
|
|
+ // but generating the field here keeps the contents of the Go
|
|
|
+ // struct in the same order as the contents of the source
|
|
|
+ // .proto file.
|
|
|
+ if oneof.Fields[0] != field {
|
|
|
+ return // only generate for first appearance
|
|
|
}
|
|
|
- tags := []string{
|
|
|
- fmt.Sprintf("protobuf:%q", fieldProtobufTag(field)),
|
|
|
- fmt.Sprintf("json:%q", fieldJSONTag(field)),
|
|
|
+ if g.PrintLeadingComments(oneof.Location) {
|
|
|
+ g.P("//")
|
|
|
}
|
|
|
- if field.Desc.IsMap() {
|
|
|
- key := field.Message.Fields[0]
|
|
|
- val := field.Message.Fields[1]
|
|
|
- tags = append(tags,
|
|
|
- fmt.Sprintf("protobuf_key:%q", fieldProtobufTag(key)),
|
|
|
- fmt.Sprintf("protobuf_val:%q", fieldProtobufTag(val)),
|
|
|
- )
|
|
|
+ g.P("// Types that are valid to be assigned to ", oneof.GoName, ":")
|
|
|
+ for _, field := range oneof.Fields {
|
|
|
+ g.PrintLeadingComments(field.Location)
|
|
|
+ g.P("//\t*", fieldOneofType(field))
|
|
|
}
|
|
|
+ g.Annotate(message.GoIdent.GoName+"."+oneof.GoName, oneof.Location)
|
|
|
+ g.P(oneof.GoName, " ", oneofInterfaceName(oneof), " `protobuf_oneof:\"", oneof.Desc.Name(), "\"`")
|
|
|
+ sf.append(oneof.GoName)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ g.PrintLeadingComments(field.Location)
|
|
|
+ goType, pointer := fieldGoType(g, field)
|
|
|
+ if pointer {
|
|
|
+ goType = "*" + goType
|
|
|
+ }
|
|
|
+ tags := []string{
|
|
|
+ fmt.Sprintf("protobuf:%q", fieldProtobufTag(field)),
|
|
|
+ fmt.Sprintf("json:%q", fieldJSONTag(field)),
|
|
|
+ }
|
|
|
+ if field.Desc.IsMap() {
|
|
|
+ key := field.Message.Fields[0]
|
|
|
+ val := field.Message.Fields[1]
|
|
|
+ tags = append(tags,
|
|
|
+ fmt.Sprintf("protobuf_key:%q", fieldProtobufTag(key)),
|
|
|
+ fmt.Sprintf("protobuf_val:%q", fieldProtobufTag(val)),
|
|
|
+ )
|
|
|
+ }
|
|
|
|
|
|
- name := field.GoName
|
|
|
- if field.Desc.IsWeak() {
|
|
|
- hasWeak = true
|
|
|
- name = "XXX_weak_" + name
|
|
|
- }
|
|
|
- g.Annotate(message.GoIdent.GoName+"."+name, field.Location)
|
|
|
- g.P(name, " ", goType, " `", strings.Join(tags, " "), "`",
|
|
|
- deprecationComment(field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated()))
|
|
|
- sf.append(field.GoName)
|
|
|
+ name := field.GoName
|
|
|
+ if field.Desc.IsWeak() {
|
|
|
+ name = "XXX_weak_" + name
|
|
|
}
|
|
|
+ g.Annotate(message.GoIdent.GoName+"."+name, field.Location)
|
|
|
+ g.P(name, " ", goType, " `", strings.Join(tags, " "), "`",
|
|
|
+ deprecationComment(field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated()))
|
|
|
+ sf.append(field.GoName)
|
|
|
+}
|
|
|
|
|
|
+func genMessageInternalFields(g *protogen.GeneratedFile, message *protogen.Message, sf *structFields) {
|
|
|
if generateNoUnkeyedLiteralFields {
|
|
|
g.P("XXX_NoUnkeyedLiteral", " struct{} `json:\"-\"`")
|
|
|
sf.append("XXX_NoUnkeyedLiteral")
|
|
|
@@ -482,7 +522,7 @@ func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, me
|
|
|
g.P("sizeCache", " ", protoimplPackage.Ident("SizeCache"))
|
|
|
sf.append("sizeCache")
|
|
|
}
|
|
|
- if hasWeak {
|
|
|
+ if loadMessageAPIFlags(message).WeakMapField {
|
|
|
g.P("XXX_weak", " ", protoimplPackage.Ident("WeakFields"), " `json:\"-\"`")
|
|
|
sf.append("XXX_weak")
|
|
|
}
|
|
|
@@ -502,24 +542,86 @@ func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, me
|
|
|
sf.append("extensionFields")
|
|
|
}
|
|
|
}
|
|
|
- g.P("}")
|
|
|
+}
|
|
|
+
|
|
|
+// genDefaultConsts generates consts and vars holding the default
|
|
|
+// values of fields.
|
|
|
+func genDefaultConsts(g *protogen.GeneratedFile, message *protogen.Message) {
|
|
|
+ for _, field := range message.Fields {
|
|
|
+ if !field.Desc.HasDefault() {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ defVarName := "Default_" + message.GoIdent.GoName + "_" + field.GoName
|
|
|
+ def := field.Desc.Default()
|
|
|
+ switch field.Desc.Kind() {
|
|
|
+ case protoreflect.StringKind:
|
|
|
+ g.P("const ", defVarName, " string = ", strconv.Quote(def.String()))
|
|
|
+ case protoreflect.BytesKind:
|
|
|
+ g.P("var ", defVarName, " []byte = []byte(", strconv.Quote(string(def.Bytes())), ")")
|
|
|
+ case protoreflect.EnumKind:
|
|
|
+ evalueDesc := field.Desc.DefaultEnumValue()
|
|
|
+ enum := field.Enum
|
|
|
+ evalue := enum.Values[evalueDesc.Index()]
|
|
|
+ g.P("const ", defVarName, " ", field.Enum.GoIdent, " = ", evalue.GoIdent)
|
|
|
+ case protoreflect.FloatKind, protoreflect.DoubleKind:
|
|
|
+ // Floating point numbers need extra handling for -Inf/Inf/NaN.
|
|
|
+ f := field.Desc.Default().Float()
|
|
|
+ goType := "float64"
|
|
|
+ if field.Desc.Kind() == protoreflect.FloatKind {
|
|
|
+ goType = "float32"
|
|
|
+ }
|
|
|
+ // funcCall returns a call to a function in the math package,
|
|
|
+ // possibly converting the result to float32.
|
|
|
+ funcCall := func(fn, param string) string {
|
|
|
+ s := g.QualifiedGoIdent(mathPackage.Ident(fn)) + param
|
|
|
+ if goType != "float64" {
|
|
|
+ s = goType + "(" + s + ")"
|
|
|
+ }
|
|
|
+ return s
|
|
|
+ }
|
|
|
+ switch {
|
|
|
+ case math.IsInf(f, -1):
|
|
|
+ g.P("var ", defVarName, " ", goType, " = ", funcCall("Inf", "(-1)"))
|
|
|
+ case math.IsInf(f, 1):
|
|
|
+ g.P("var ", defVarName, " ", goType, " = ", funcCall("Inf", "(1)"))
|
|
|
+ case math.IsNaN(f):
|
|
|
+ g.P("var ", defVarName, " ", goType, " = ", funcCall("NaN", "()"))
|
|
|
+ default:
|
|
|
+ g.P("const ", defVarName, " ", goType, " = ", field.Desc.Default().Interface())
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ goType, _ := fieldGoType(g, field)
|
|
|
+ g.P("const ", defVarName, " ", goType, " = ", def.Interface())
|
|
|
+ }
|
|
|
+ }
|
|
|
g.P()
|
|
|
+}
|
|
|
+
|
|
|
+func genMessageMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message) {
|
|
|
+ genMessageBaseMethods(gen, g, f, message)
|
|
|
+ genMessageGetterMethods(gen, g, f, message)
|
|
|
+ genMessageSetterMethods(gen, g, f, message)
|
|
|
+}
|
|
|
|
|
|
+func genMessageBaseMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message) {
|
|
|
// Reset method.
|
|
|
g.P("func (x *", message.GoIdent, ") Reset() {")
|
|
|
g.P("*x = ", message.GoIdent, "{}")
|
|
|
g.P("}")
|
|
|
g.P()
|
|
|
+
|
|
|
// String method.
|
|
|
g.P("func (x *", message.GoIdent, ") String() string {")
|
|
|
g.P("return ", protoimplPackage.Ident("X"), ".MessageStringOf(x)")
|
|
|
g.P("}")
|
|
|
g.P()
|
|
|
+
|
|
|
// ProtoMessage method.
|
|
|
g.P("func (*", message.GoIdent, ") ProtoMessage() {}")
|
|
|
g.P()
|
|
|
|
|
|
- genReflectMessage(gen, g, f, message)
|
|
|
+ // ProtoReflect method.
|
|
|
+ genMessageReflectMethods(gen, g, f, message)
|
|
|
|
|
|
// Descriptor method.
|
|
|
if generateRawDescMethods {
|
|
|
@@ -554,70 +656,47 @@ func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, me
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- genWellKnownType(g, "*", message.GoIdent, message.Desc)
|
|
|
+ // XXX_OneofWrappers method.
|
|
|
+ if generateOneofWrapperMethods && len(message.Oneofs) > 0 {
|
|
|
+ idx := f.allMessagesByPtr[message]
|
|
|
+ typesVar := messageTypesVarName(f)
|
|
|
+ g.P("// XXX_OneofWrappers is for the internal use of the proto package.")
|
|
|
+ g.P("func (*", message.GoIdent.GoName, ") XXX_OneofWrappers() []interface{} {")
|
|
|
+ g.P("return ", typesVar, "[", idx, "].OneofWrappers")
|
|
|
+ g.P("}")
|
|
|
+ g.P()
|
|
|
+ }
|
|
|
|
|
|
- // Constants and vars holding the default values of fields.
|
|
|
- for _, field := range message.Fields {
|
|
|
- if !field.Desc.HasDefault() {
|
|
|
- continue
|
|
|
- }
|
|
|
- defVarName := "Default_" + message.GoIdent.GoName + "_" + field.GoName
|
|
|
- def := field.Desc.Default()
|
|
|
- switch field.Desc.Kind() {
|
|
|
- case protoreflect.StringKind:
|
|
|
- g.P("const ", defVarName, " string = ", strconv.Quote(def.String()))
|
|
|
- case protoreflect.BytesKind:
|
|
|
- g.P("var ", defVarName, " []byte = []byte(", strconv.Quote(string(def.Bytes())), ")")
|
|
|
- case protoreflect.EnumKind:
|
|
|
- evalueDesc := field.Desc.DefaultEnumValue()
|
|
|
- enum := field.Enum
|
|
|
- evalue := enum.Values[evalueDesc.Index()]
|
|
|
- g.P("const ", defVarName, " ", field.Enum.GoIdent, " = ", evalue.GoIdent)
|
|
|
- case protoreflect.FloatKind, protoreflect.DoubleKind:
|
|
|
- // Floating point numbers need extra handling for -Inf/Inf/NaN.
|
|
|
- f := field.Desc.Default().Float()
|
|
|
- goType := "float64"
|
|
|
- if field.Desc.Kind() == protoreflect.FloatKind {
|
|
|
- goType = "float32"
|
|
|
- }
|
|
|
- // funcCall returns a call to a function in the math package,
|
|
|
- // possibly converting the result to float32.
|
|
|
- funcCall := func(fn, param string) string {
|
|
|
- s := g.QualifiedGoIdent(mathPackage.Ident(fn)) + param
|
|
|
- if goType != "float64" {
|
|
|
- s = goType + "(" + s + ")"
|
|
|
- }
|
|
|
- return s
|
|
|
- }
|
|
|
- switch {
|
|
|
- case math.IsInf(f, -1):
|
|
|
- g.P("var ", defVarName, " ", goType, " = ", funcCall("Inf", "(-1)"))
|
|
|
- case math.IsInf(f, 1):
|
|
|
- g.P("var ", defVarName, " ", goType, " = ", funcCall("Inf", "(1)"))
|
|
|
- case math.IsNaN(f):
|
|
|
- g.P("var ", defVarName, " ", goType, " = ", funcCall("NaN", "()"))
|
|
|
- default:
|
|
|
- g.P("const ", defVarName, " ", goType, " = ", field.Desc.Default().Interface())
|
|
|
- }
|
|
|
- default:
|
|
|
- goType, _ := fieldGoType(g, field)
|
|
|
- g.P("const ", defVarName, " ", goType, " = ", def.Interface())
|
|
|
- }
|
|
|
+ // XXX_WellKnownType method.
|
|
|
+ if generateWKTMarkerMethods && wellKnownTypes[message.Desc.FullName()] {
|
|
|
+ g.P("func (*", message.GoIdent, `) XXX_WellKnownType() string { return "`, message.Desc.Name(), `" }`)
|
|
|
+ g.P()
|
|
|
}
|
|
|
- g.P()
|
|
|
+}
|
|
|
|
|
|
- // Getter methods.
|
|
|
+func genMessageGetterMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message) {
|
|
|
for _, field := range message.Fields {
|
|
|
- if isFirstOneofField(field) {
|
|
|
- genOneofGetter(gen, g, f, message, field.Oneof)
|
|
|
+ // Getter for parent oneof.
|
|
|
+ if oneof := field.Oneof; oneof != nil && oneof.Fields[0] == field {
|
|
|
+ g.Annotate(message.GoIdent.GoName+".Get"+oneof.GoName, oneof.Location)
|
|
|
+ g.P("func (m *", message.GoIdent.GoName, ") Get", oneof.GoName, "() ", oneofInterfaceName(oneof), " {")
|
|
|
+ g.P("if m != nil {")
|
|
|
+ g.P("return m.", oneof.GoName)
|
|
|
+ g.P("}")
|
|
|
+ g.P("return nil")
|
|
|
+ g.P("}")
|
|
|
+ g.P()
|
|
|
}
|
|
|
+
|
|
|
+ // Getter for message field.
|
|
|
goType, pointer := fieldGoType(g, field)
|
|
|
defaultValue := fieldDefaultValue(g, message, field)
|
|
|
if field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated() {
|
|
|
g.P(deprecationComment(true))
|
|
|
}
|
|
|
g.Annotate(message.GoIdent.GoName+".Get"+field.GoName, field.Location)
|
|
|
- if field.Desc.IsWeak() {
|
|
|
+ switch {
|
|
|
+ case field.Desc.IsWeak():
|
|
|
g.P("func (x *", message.GoIdent, ") Get", field.GoName, "() ", protoifacePackage.Ident("MessageV1"), "{")
|
|
|
g.P("if x != nil {")
|
|
|
g.P("v := x.XXX_weak[", field.Desc.Number(), "]")
|
|
|
@@ -628,14 +707,15 @@ func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, me
|
|
|
g.P("}")
|
|
|
g.P("return ", protoimplPackage.Ident("X"), ".WeakNil(", strconv.Quote(string(field.Message.Desc.FullName())), ")")
|
|
|
g.P("}")
|
|
|
- continue
|
|
|
- }
|
|
|
- g.P("func (x *", message.GoIdent, ") Get", field.GoName, "() ", goType, " {")
|
|
|
- if field.Oneof != nil {
|
|
|
+ case field.Oneof != nil:
|
|
|
+ g.P("func (x *", message.GoIdent, ") Get", field.GoName, "() ", goType, " {")
|
|
|
g.P("if x, ok := x.Get", field.Oneof.GoName, "().(*", fieldOneofType(field), "); ok {")
|
|
|
g.P("return x.", field.GoName)
|
|
|
g.P("}")
|
|
|
- } else {
|
|
|
+ g.P("return ", defaultValue)
|
|
|
+ g.P("}")
|
|
|
+ default:
|
|
|
+ g.P("func (x *", message.GoIdent, ") Get", field.GoName, "() ", goType, " {")
|
|
|
if field.Desc.Syntax() == protoreflect.Proto3 || defaultValue == "nil" {
|
|
|
g.P("if x != nil {")
|
|
|
} else {
|
|
|
@@ -647,13 +727,14 @@ func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, me
|
|
|
}
|
|
|
g.P("return ", star, " x.", field.GoName)
|
|
|
g.P("}")
|
|
|
+ g.P("return ", defaultValue)
|
|
|
+ g.P("}")
|
|
|
}
|
|
|
- g.P("return ", defaultValue)
|
|
|
- g.P("}")
|
|
|
g.P()
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- // Setter methods.
|
|
|
+func genMessageSetterMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message) {
|
|
|
for _, field := range message.Fields {
|
|
|
if field.Desc.IsWeak() {
|
|
|
g.Annotate(message.GoIdent.GoName+".Set"+field.GoName, field.Location)
|
|
|
@@ -671,11 +752,6 @@ func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, me
|
|
|
g.P()
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- // Oneof wrapper types.
|
|
|
- if len(message.Oneofs) > 0 {
|
|
|
- genOneofWrappers(gen, g, f, message)
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
// fieldGoType returns the Go type used for a field.
|
|
|
@@ -826,106 +902,33 @@ func deprecationComment(deprecated bool) string {
|
|
|
return "// Deprecated: Do not use."
|
|
|
}
|
|
|
|
|
|
-func genWellKnownType(g *protogen.GeneratedFile, ptr string, ident protogen.GoIdent, desc protoreflect.Descriptor) {
|
|
|
- if generateWKTMarkerMethods && wellKnownTypes[desc.FullName()] {
|
|
|
- g.P("func (", ptr, ident, `) XXX_WellKnownType() string { return "`, desc.Name(), `" }`)
|
|
|
- g.P()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// Names of messages and enums for which we will generate XXX_WellKnownType methods.
|
|
|
-var wellKnownTypes = map[protoreflect.FullName]bool{
|
|
|
- "google.protobuf.Any": true,
|
|
|
- "google.protobuf.Duration": true,
|
|
|
- "google.protobuf.Empty": true,
|
|
|
- "google.protobuf.Struct": true,
|
|
|
- "google.protobuf.Timestamp": true,
|
|
|
-
|
|
|
- "google.protobuf.BoolValue": true,
|
|
|
- "google.protobuf.BytesValue": true,
|
|
|
- "google.protobuf.DoubleValue": true,
|
|
|
- "google.protobuf.FloatValue": true,
|
|
|
- "google.protobuf.Int32Value": true,
|
|
|
- "google.protobuf.Int64Value": true,
|
|
|
- "google.protobuf.ListValue": true,
|
|
|
- "google.protobuf.NullValue": true,
|
|
|
- "google.protobuf.StringValue": true,
|
|
|
- "google.protobuf.UInt32Value": true,
|
|
|
- "google.protobuf.UInt64Value": true,
|
|
|
- "google.protobuf.Value": true,
|
|
|
-}
|
|
|
-
|
|
|
-// genOneofGetter generate a Get method for a oneof.
|
|
|
-func genOneofGetter(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message, oneof *protogen.Oneof) {
|
|
|
- g.Annotate(message.GoIdent.GoName+".Get"+oneof.GoName, oneof.Location)
|
|
|
- g.P("func (m *", message.GoIdent.GoName, ") Get", oneof.GoName, "() ", oneofInterfaceName(oneof), " {")
|
|
|
- g.P("if m != nil {")
|
|
|
- g.P("return m.", oneofFieldName(oneof))
|
|
|
- g.P("}")
|
|
|
- g.P("return nil")
|
|
|
- g.P("}")
|
|
|
- g.P()
|
|
|
-}
|
|
|
-
|
|
|
-// genOneofWrappers generates the oneof wrapper types and associates the types
|
|
|
-// with the parent message type.
|
|
|
-func genOneofWrappers(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message) {
|
|
|
- idx := f.allMessagesByPtr[message]
|
|
|
- typesVar := messageTypesVarName(f)
|
|
|
-
|
|
|
- // Associate the wrapper types through a XXX_OneofWrappers method.
|
|
|
- if generateOneofWrapperMethods {
|
|
|
- g.P("// XXX_OneofWrappers is for the internal use of the proto package.")
|
|
|
- g.P("func (*", message.GoIdent.GoName, ") XXX_OneofWrappers() []interface{} {")
|
|
|
- g.P("return ", typesVar, "[", idx, "].OneofWrappers")
|
|
|
- g.P("}")
|
|
|
- g.P()
|
|
|
- }
|
|
|
-
|
|
|
- // Generate the oneof wrapper types.
|
|
|
+// genOneofWrapperTypes generates the oneof wrapper types and
|
|
|
+// associates the types with the parent message type.
|
|
|
+func genOneofWrapperTypes(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message) {
|
|
|
for _, oneof := range message.Oneofs {
|
|
|
- genOneofTypes(gen, g, f, message, oneof)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// genOneofTypes generates the interface type used for a oneof field,
|
|
|
-// and the wrapper types that satisfy that interface.
|
|
|
-func genOneofTypes(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message, oneof *protogen.Oneof) {
|
|
|
- ifName := oneofInterfaceName(oneof)
|
|
|
- g.P("type ", ifName, " interface {")
|
|
|
- g.P(ifName, "()")
|
|
|
- g.P("}")
|
|
|
- g.P()
|
|
|
- for _, field := range oneof.Fields {
|
|
|
- name := fieldOneofType(field)
|
|
|
- g.Annotate(name.GoName, field.Location)
|
|
|
- g.Annotate(name.GoName+"."+field.GoName, field.Location)
|
|
|
- g.P("type ", name, " struct {")
|
|
|
- goType, _ := fieldGoType(g, field)
|
|
|
- tags := []string{
|
|
|
- fmt.Sprintf("protobuf:%q", fieldProtobufTag(field)),
|
|
|
- }
|
|
|
- g.P(field.GoName, " ", goType, " `", strings.Join(tags, " "), "`")
|
|
|
+ ifName := oneofInterfaceName(oneof)
|
|
|
+ g.P("type ", ifName, " interface {")
|
|
|
+ g.P(ifName, "()")
|
|
|
g.P("}")
|
|
|
g.P()
|
|
|
+ for _, field := range oneof.Fields {
|
|
|
+ name := fieldOneofType(field)
|
|
|
+ g.Annotate(name.GoName, field.Location)
|
|
|
+ g.Annotate(name.GoName+"."+field.GoName, field.Location)
|
|
|
+ g.P("type ", name, " struct {")
|
|
|
+ goType, _ := fieldGoType(g, field)
|
|
|
+ tags := []string{
|
|
|
+ fmt.Sprintf("protobuf:%q", fieldProtobufTag(field)),
|
|
|
+ }
|
|
|
+ g.P(field.GoName, " ", goType, " `", strings.Join(tags, " "), "`")
|
|
|
+ g.P("}")
|
|
|
+ g.P()
|
|
|
+ }
|
|
|
+ for _, field := range oneof.Fields {
|
|
|
+ g.P("func (*", fieldOneofType(field), ") ", ifName, "() {}")
|
|
|
+ g.P()
|
|
|
+ }
|
|
|
}
|
|
|
- for _, field := range oneof.Fields {
|
|
|
- g.P("func (*", fieldOneofType(field), ") ", ifName, "() {}")
|
|
|
- g.P()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// isFirstOneofField reports whether this is the first field in a oneof.
|
|
|
-func isFirstOneofField(field *protogen.Field) bool {
|
|
|
- return field.Oneof != nil && field.Oneof.Fields[0] == field
|
|
|
-}
|
|
|
-
|
|
|
-// oneofFieldName returns the name of the struct field holding the oneof value.
|
|
|
-//
|
|
|
-// This function is trivial, but pulling out the name like this makes it easier
|
|
|
-// to experiment with alternative oneof implementations.
|
|
|
-func oneofFieldName(oneof *protogen.Oneof) string {
|
|
|
- return oneof.GoName
|
|
|
}
|
|
|
|
|
|
// oneofInterfaceName returns the name of the interface type implemented by
|