cmd/protoc-gen-go: refactor package

Refactor the internal logic of protoc-gen-go to better plumb local
settings and parameters down the call tree.

Change-Id: I09fec188d7359f2b66be584aa8f10e682a7b6796
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/214357
Reviewed-by: Patrik Nyblom <pnyb@google.com>
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
This commit is contained in:
Joe Tsai 2020-01-10 11:20:25 -08:00 committed by Joe Tsai
parent 7abc2def69
commit 4a7fc8200d
7 changed files with 284 additions and 269 deletions

View File

@ -11,7 +11,6 @@ import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
var File_grpc_deprecation_proto protoreflect.FileDescriptor
@ -35,18 +34,6 @@ var file_grpc_deprecation_proto_rawDesc = []byte{
0x6f, 0x33,
}
var (
file_grpc_deprecation_proto_rawDescOnce sync.Once
file_grpc_deprecation_proto_rawDescData = file_grpc_deprecation_proto_rawDesc
)
func file_grpc_deprecation_proto_rawDescGZIP() []byte {
file_grpc_deprecation_proto_rawDescOnce.Do(func() {
file_grpc_deprecation_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_deprecation_proto_rawDescData)
})
return file_grpc_deprecation_proto_rawDescData
}
var file_grpc_deprecation_proto_goTypes = []interface{}{
(*Request)(nil), // 0: goproto.protoc.grpc.Request
(*Response)(nil), // 1: goproto.protoc.grpc.Response

View File

@ -1,51 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package internal_gengo
import (
"google.golang.org/protobuf/compiler/protogen"
"google.golang.org/protobuf/internal/encoding/wire"
"google.golang.org/protobuf/types/descriptorpb"
)
// messageFlags provides flags that control the generated API.
type messageFlags struct {
IsTracked bool
HasWeak bool
}
func loadMessageFlags(message *protogen.Message) messageFlags {
var flags messageFlags
flags.IsTracked = isTrackedMessage(message)
for _, field := range message.Fields {
if field.Desc.IsWeak() {
flags.HasWeak = true
break
}
}
return flags
}
// isTrackedMessage reports whether field tracking is enabled on the message.
// It is a variable so that the behavior is easily overridden in another file.
var isTrackedMessage = func(message *protogen.Message) (tracked bool) {
const trackFieldUse_fieldNumber = 37383685
// Decode the option from unknown fields to avoid a dependency on the
// annotation proto from protoc-gen-go.
b := message.Desc.Options().(*descriptorpb.MessageOptions).ProtoReflect().GetUnknown()
for len(b) > 0 {
num, typ, n := wire.ConsumeTag(b)
b = b[n:]
if num == trackFieldUse_fieldNumber && typ == wire.VarintType {
v, _ := wire.ConsumeVarint(b)
tracked = wire.DecodeBool(v)
}
m := wire.ConsumeFieldValue(num, typ, b)
b = b[m:]
}
return tracked
}

View File

@ -0,0 +1,168 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package internal_gengo
import (
"unicode"
"unicode/utf8"
"google.golang.org/protobuf/compiler/protogen"
"google.golang.org/protobuf/internal/encoding/wire"
"google.golang.org/protobuf/types/descriptorpb"
)
type fileInfo struct {
*protogen.File
allEnums []*enumInfo
allMessages []*messageInfo
allExtensions []*extensionInfo
allEnumsByPtr map[*enumInfo]int // value is index into allEnums
allMessagesByPtr map[*messageInfo]int // value is index into allMessages
allMessageFieldsByPtr map[*messageInfo]*structFields
// needRawDesc specifies whether the generator should emit logic to provide
// the legacy raw descriptor in GZIP'd form.
// This is updated by enum and message generation logic as necessary,
// and checked at the end of file generation.
needRawDesc bool
}
type structFields struct {
count int
unexported map[int]string
}
func (sf *structFields) append(name string) {
if r, _ := utf8.DecodeRuneInString(name); !unicode.IsUpper(r) {
if sf.unexported == nil {
sf.unexported = make(map[int]string)
}
sf.unexported[sf.count] = name
}
sf.count++
}
func newFileInfo(file *protogen.File) *fileInfo {
f := &fileInfo{File: file}
// Collect all enums, messages, and extensions in "flattened ordering".
// See filetype.TypeBuilder.
var walkMessages func([]*protogen.Message, func(*protogen.Message))
walkMessages = func(messages []*protogen.Message, f func(*protogen.Message)) {
for _, m := range messages {
f(m)
walkMessages(m.Messages, f)
}
}
initEnumInfos := func(enums []*protogen.Enum) {
for _, enum := range enums {
f.allEnums = append(f.allEnums, newEnumInfo(f, enum))
}
}
initMessageInfos := func(messages []*protogen.Message) {
for _, message := range messages {
f.allMessages = append(f.allMessages, newMessageInfo(f, message))
}
}
initExtensionInfos := func(extensions []*protogen.Extension) {
for _, extension := range extensions {
f.allExtensions = append(f.allExtensions, newExtensionInfo(f, extension))
}
}
initEnumInfos(f.Enums)
initMessageInfos(f.Messages)
initExtensionInfos(f.Extensions)
walkMessages(f.Messages, func(m *protogen.Message) {
initEnumInfos(m.Enums)
initMessageInfos(m.Messages)
initExtensionInfos(m.Extensions)
})
// Derive a reverse mapping of enum and message pointers to their index
// in allEnums and allMessages.
if len(f.allEnums) > 0 {
f.allEnumsByPtr = make(map[*enumInfo]int)
for i, e := range f.allEnums {
f.allEnumsByPtr[e] = i
}
}
if len(f.allMessages) > 0 {
f.allMessagesByPtr = make(map[*messageInfo]int)
f.allMessageFieldsByPtr = make(map[*messageInfo]*structFields)
for i, m := range f.allMessages {
f.allMessagesByPtr[m] = i
f.allMessageFieldsByPtr[m] = new(structFields)
}
}
return f
}
type enumInfo struct {
*protogen.Enum
genJSONMethod bool
genRawDescMethod bool
}
func newEnumInfo(f *fileInfo, enum *protogen.Enum) *enumInfo {
e := &enumInfo{Enum: enum}
e.genJSONMethod = true
e.genRawDescMethod = true
return e
}
type messageInfo struct {
*protogen.Message
genRawDescMethod bool
genExtRangeMethod bool
isTracked bool
hasWeak bool
}
func newMessageInfo(f *fileInfo, message *protogen.Message) *messageInfo {
m := &messageInfo{Message: message}
m.genRawDescMethod = true
m.genExtRangeMethod = true
m.isTracked = isTrackedMessage(m)
for _, field := range m.Fields {
m.hasWeak = m.hasWeak || field.Desc.IsWeak()
}
return m
}
// isTrackedMessage reports whether field tracking is enabled on the message.
func isTrackedMessage(m *messageInfo) (tracked bool) {
const trackFieldUse_fieldNumber = 37383685
// Decode the option from unknown fields to avoid a dependency on the
// annotation proto from protoc-gen-go.
b := m.Desc.Options().(*descriptorpb.MessageOptions).ProtoReflect().GetUnknown()
for len(b) > 0 {
num, typ, n := wire.ConsumeTag(b)
b = b[n:]
if num == trackFieldUse_fieldNumber && typ == wire.VarintType {
v, _ := wire.ConsumeVarint(b)
tracked = wire.DecodeBool(v)
}
m := wire.ConsumeFieldValue(num, typ, b)
b = b[m:]
}
return tracked
}
type extensionInfo struct {
*protogen.Extension
}
func newExtensionInfo(f *fileInfo, extension *protogen.Extension) *extensionInfo {
x := &extensionInfo{Extension: extension}
return x
}

View File

@ -53,68 +53,11 @@ type goImportPath interface {
Ident(string) protogen.GoIdent
}
type fileInfo struct {
*protogen.File
allEnums []*protogen.Enum
allMessages []*protogen.Message
allExtensions []*protogen.Extension
allEnumsByPtr map[*protogen.Enum]int // value is index into allEnums
allMessagesByPtr map[*protogen.Message]int // value is index into allMessages
allMessageFieldsByPtr map[*protogen.Message]*structFields
}
type structFields struct {
count int
unexported map[int]string
}
func (sf *structFields) append(name string) {
if r, _ := utf8.DecodeRuneInString(name); !unicode.IsUpper(r) {
if sf.unexported == nil {
sf.unexported = make(map[int]string)
}
sf.unexported[sf.count] = name
}
sf.count++
}
// GenerateFile generates the contents of a .pb.go file.
func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile {
filename := file.GeneratedFilenamePrefix + ".pb.go"
g := gen.NewGeneratedFile(filename, file.GoImportPath)
f := &fileInfo{
File: file,
}
// Collect all enums, messages, and extensions in "flattened ordering".
// See filetype.TypeBuilder.
f.allEnums = append(f.allEnums, f.Enums...)
f.allMessages = append(f.allMessages, f.Messages...)
f.allExtensions = append(f.allExtensions, f.Extensions...)
walkMessages(f.Messages, func(m *protogen.Message) {
f.allEnums = append(f.allEnums, m.Enums...)
f.allMessages = append(f.allMessages, m.Messages...)
f.allExtensions = append(f.allExtensions, m.Extensions...)
})
// Derive a reverse mapping of enum and message pointers to their index
// in allEnums and allMessages.
if len(f.allEnums) > 0 {
f.allEnumsByPtr = make(map[*protogen.Enum]int)
for i, e := range f.allEnums {
f.allEnumsByPtr[e] = i
}
}
if len(f.allMessages) > 0 {
f.allMessagesByPtr = make(map[*protogen.Message]int)
f.allMessageFieldsByPtr = make(map[*protogen.Message]*structFields)
for i, m := range f.allMessages {
f.allMessagesByPtr[m] = i
f.allMessageFieldsByPtr[m] = new(structFields)
}
}
f := newFileInfo(file)
genStandaloneComments(g, f, fieldnum.FileDescriptorProto_Syntax)
genGeneratedHeader(gen, g, f)
@ -137,26 +80,18 @@ func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.Generated
genImport(gen, g, f, imps.Get(i))
}
for _, enum := range f.allEnums {
genEnum(gen, g, f, enum)
genEnum(g, f, enum)
}
for _, message := range f.allMessages {
genMessage(gen, g, f, message)
genMessage(g, f, message)
}
genExtensions(gen, g, f)
genExtensions(g, f)
genReflectFileDescriptor(gen, g, f)
return g
}
// walkMessages calls f on each message and all of its descendants.
func walkMessages(messages []*protogen.Message, f func(*protogen.Message)) {
for _, m := range messages {
f(m)
walkMessages(m.Messages, f)
}
}
// genStandaloneComments prints all leading comments for a FileDescriptorProto
// location identified by the field number n.
func genStandaloneComments(g *protogen.GeneratedFile, f *fileInfo, n int32) {
@ -276,41 +211,41 @@ func genImport(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, imp
g.P()
}
func genEnum(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, enum *protogen.Enum) {
func genEnum(g *protogen.GeneratedFile, f *fileInfo, e *enumInfo) {
// Enum type declaration.
g.Annotate(enum.GoIdent.GoName, enum.Location)
leadingComments := appendDeprecationSuffix(enum.Comments.Leading,
enum.Desc.Options().(*descriptorpb.EnumOptions).GetDeprecated())
g.Annotate(e.GoIdent.GoName, e.Location)
leadingComments := appendDeprecationSuffix(e.Comments.Leading,
e.Desc.Options().(*descriptorpb.EnumOptions).GetDeprecated())
g.P(leadingComments,
"type ", enum.GoIdent, " int32")
"type ", e.GoIdent, " int32")
// Enum value constants.
g.P("const (")
for _, value := range enum.Values {
for _, value := range e.Values {
g.Annotate(value.GoIdent.GoName, value.Location)
leadingComments := appendDeprecationSuffix(value.Comments.Leading,
value.Desc.Options().(*descriptorpb.EnumValueOptions).GetDeprecated())
g.P(leadingComments,
value.GoIdent, " ", enum.GoIdent, " = ", value.Desc.Number(),
value.GoIdent, " ", e.GoIdent, " = ", value.Desc.Number(),
trailingComment(value.Comments.Trailing))
}
g.P(")")
g.P()
// Enum value maps.
g.P("// Enum value maps for ", enum.GoIdent, ".")
g.P("// Enum value maps for ", e.GoIdent, ".")
g.P("var (")
g.P(enum.GoIdent.GoName+"_name", " = map[int32]string{")
for _, value := range enum.Values {
g.P(e.GoIdent.GoName+"_name", " = map[int32]string{")
for _, value := range e.Values {
duplicate := ""
if value.Desc != enum.Desc.Values().ByNumber(value.Desc.Number()) {
if value.Desc != e.Desc.Values().ByNumber(value.Desc.Number()) {
duplicate = "// Duplicate value: "
}
g.P(duplicate, value.Desc.Number(), ": ", strconv.Quote(string(value.Desc.Name())), ",")
}
g.P("}")
g.P(enum.GoIdent.GoName+"_value", " = map[string]int32{")
for _, value := range enum.Values {
g.P(e.GoIdent.GoName+"_value", " = map[string]int32{")
for _, value := range e.Values {
g.P(strconv.Quote(string(value.Desc.Name())), ": ", value.Desc.Number(), ",")
}
g.P("}")
@ -322,59 +257,55 @@ func genEnum(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, enum
// NOTE: A pointer value is needed to represent presence in proto2.
// Since a proto2 message can reference a proto3 enum, it is useful to
// always generate this method (even on proto3 enums) to support that case.
g.P("func (x ", enum.GoIdent, ") Enum() *", enum.GoIdent, " {")
g.P("p := new(", enum.GoIdent, ")")
g.P("func (x ", e.GoIdent, ") Enum() *", e.GoIdent, " {")
g.P("p := new(", e.GoIdent, ")")
g.P("*p = x")
g.P("return p")
g.P("}")
g.P()
// String method.
g.P("func (x ", enum.GoIdent, ") String() string {")
g.P("func (x ", e.GoIdent, ") String() string {")
g.P("return ", protoimplPackage.Ident("X"), ".EnumStringOf(x.Descriptor(), ", protoreflectPackage.Ident("EnumNumber"), "(x))")
g.P("}")
g.P()
genEnumReflectMethods(gen, g, f, enum)
genEnumReflectMethods(g, f, e)
// UnmarshalJSON method.
if enum.Desc.Syntax() == protoreflect.Proto2 {
if e.genJSONMethod && e.Desc.Syntax() == protoreflect.Proto2 {
g.P("// Deprecated: Do not use.")
g.P("func (x *", enum.GoIdent, ") UnmarshalJSON(b []byte) error {")
g.P("func (x *", e.GoIdent, ") UnmarshalJSON(b []byte) error {")
g.P("num, err := ", protoimplPackage.Ident("X"), ".UnmarshalJSONEnum(x.Descriptor(), b)")
g.P("if err != nil {")
g.P("return err")
g.P("}")
g.P("*x = ", enum.GoIdent, "(num)")
g.P("*x = ", e.GoIdent, "(num)")
g.P("return nil")
g.P("}")
g.P()
}
// EnumDescriptor method.
var indexes []string
for i := 1; i < len(enum.Location.Path); i += 2 {
indexes = append(indexes, strconv.Itoa(int(enum.Location.Path[i])))
if e.genRawDescMethod {
var indexes []string
for i := 1; i < len(e.Location.Path); i += 2 {
indexes = append(indexes, strconv.Itoa(int(e.Location.Path[i])))
}
g.P("// Deprecated: Use ", e.GoIdent, ".Descriptor instead.")
g.P("func (", e.GoIdent, ") EnumDescriptor() ([]byte, []int) {")
g.P("return ", rawDescVarName(f), "GZIP(), []int{", strings.Join(indexes, ","), "}")
g.P("}")
g.P()
f.needRawDesc = true
}
g.P("// Deprecated: Use ", enum.GoIdent, ".Descriptor instead.")
g.P("func (", enum.GoIdent, ") EnumDescriptor() ([]byte, []int) {")
g.P("return ", rawDescVarName(f), "GZIP(), []int{", strings.Join(indexes, ","), "}")
g.P("}")
g.P()
}
type messageInfo struct {
*protogen.Message
messageFlags
}
func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message) {
if message.Desc.IsMapEntry() {
func genMessage(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
if m.Desc.IsMapEntry() {
return
}
m := &messageInfo{message, loadMessageFlags(message)}
// Message type declaration.
g.Annotate(m.GoIdent.GoName, m.Location)
leadingComments := appendDeprecationSuffix(m.Comments.Leading,
@ -386,12 +317,12 @@ func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, me
g.P()
genMessageDefaultDecls(g, f, m)
genMessageMethods(gen, g, f, m)
genMessageOneofWrapperTypes(gen, g, f, m)
genMessageMethods(g, f, m)
genMessageOneofWrapperTypes(g, f, m)
}
func genMessageFields(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
sf := f.allMessageFieldsByPtr[m.Message]
sf := f.allMessageFieldsByPtr[m]
genMessageInternalFields(g, f, m, sf)
for _, field := range m.Fields {
genMessageField(g, f, m, field, sf)
@ -403,7 +334,7 @@ func genMessageInternalFields(g *protogen.GeneratedFile, f *fileInfo, m *message
sf.append(genname.State)
g.P(genname.SizeCache, " ", protoimplPackage.Ident("SizeCache"))
sf.append(genname.SizeCache)
if m.HasWeak {
if m.hasWeak {
g.P(genname.WeakFields, " ", protoimplPackage.Ident("WeakFields"))
sf.append(genname.WeakFields)
}
@ -431,7 +362,7 @@ func genMessageField(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo, fie
tags := structTags{
{"protobuf_oneof", string(oneof.Desc.Name())},
}
if m.IsTracked {
if m.isTracked {
tags = append(tags, gotrackTags...)
}
@ -466,7 +397,7 @@ func genMessageField(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo, fie
{"protobuf_val", fieldProtobufTagValue(val)},
}...)
}
if m.IsTracked {
if m.isTracked {
tags = append(tags, gotrackTags...)
}
@ -541,18 +472,18 @@ func genMessageDefaultDecls(g *protogen.GeneratedFile, f *fileInfo, m *messageIn
g.P()
}
func genMessageMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
genMessageBaseMethods(gen, g, f, m)
genMessageGetterMethods(gen, g, f, m)
genMessageSetterMethods(gen, g, f, m)
func genMessageMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
genMessageBaseMethods(g, f, m)
genMessageGetterMethods(g, f, m)
genMessageSetterMethods(g, f, m)
}
func genMessageBaseMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
func genMessageBaseMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
// Reset method.
g.P("func (x *", m.GoIdent, ") Reset() {")
g.P("*x = ", m.GoIdent, "{}")
g.P("if ", protoimplPackage.Ident("UnsafeEnabled"), " {")
g.P("mi := &", messageTypesVarName(f), "[", f.allMessagesByPtr[m.Message], "]")
g.P("mi := &", messageTypesVarName(f), "[", f.allMessagesByPtr[m], "]")
g.P("ms := ", protoimplPackage.Ident("X"), ".MessageStateOf(", protoimplPackage.Ident("Pointer"), "(x))")
g.P("ms.StoreMessageInfo(mi)")
g.P("}")
@ -570,26 +501,30 @@ func genMessageBaseMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *f
g.P()
// ProtoReflect method.
genMessageReflectMethods(gen, g, f, m)
genMessageReflectMethods(g, f, m)
// Descriptor method.
var indexes []string
for i := 1; i < len(m.Location.Path); i += 2 {
indexes = append(indexes, strconv.Itoa(int(m.Location.Path[i])))
if m.genRawDescMethod {
var indexes []string
for i := 1; i < len(m.Location.Path); i += 2 {
indexes = append(indexes, strconv.Itoa(int(m.Location.Path[i])))
}
g.P("// Deprecated: Use ", m.GoIdent, ".ProtoReflect.Descriptor instead.")
g.P("func (*", m.GoIdent, ") Descriptor() ([]byte, []int) {")
g.P("return ", rawDescVarName(f), "GZIP(), []int{", strings.Join(indexes, ","), "}")
g.P("}")
g.P()
f.needRawDesc = true
}
g.P("// Deprecated: Use ", m.GoIdent, ".ProtoReflect.Descriptor instead.")
g.P("func (*", m.GoIdent, ") Descriptor() ([]byte, []int) {")
g.P("return ", rawDescVarName(f), "GZIP(), []int{", strings.Join(indexes, ","), "}")
g.P("}")
g.P()
// ExtensionRangeArray method.
if extranges := m.Desc.ExtensionRanges(); extranges.Len() > 0 {
extRanges := m.Desc.ExtensionRanges()
if m.genExtRangeMethod && extRanges.Len() > 0 {
protoExtRange := protoifacePackage.Ident("ExtensionRangeV1")
extRangeVar := "extRange_" + m.GoIdent.GoName
g.P("var ", extRangeVar, " = []", protoExtRange, " {")
for i := 0; i < extranges.Len(); i++ {
r := extranges.Get(i)
for i := 0; i < extRanges.Len(); i++ {
r := extRanges.Get(i)
g.P("{Start:", r[0], ", End:", r[1]-1 /* inclusive */, "},")
}
g.P("}")
@ -602,9 +537,9 @@ func genMessageBaseMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *f
}
}
func genMessageGetterMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
func genMessageGetterMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
for _, field := range m.Fields {
genNoInterfacePragma(g, m.IsTracked)
genNoInterfacePragma(g, m.isTracked)
// Getter for parent oneof.
if oneof := field.Oneof; oneof != nil && oneof.Fields[0] == field {
@ -663,13 +598,13 @@ func genMessageGetterMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f
}
}
func genMessageSetterMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
func genMessageSetterMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
for _, field := range m.Fields {
if !field.Desc.IsWeak() {
continue
}
genNoInterfacePragma(g, m.IsTracked)
genNoInterfacePragma(g, m.isTracked)
g.Annotate(m.GoIdent.GoName+".Set"+field.GoName, field.Location)
leadingComments := appendDeprecationSuffix("",
@ -778,29 +713,29 @@ func fieldJSONTagValue(field *protogen.Field) string {
return string(field.Desc.Name()) + ",omitempty"
}
func genExtensions(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) {
func genExtensions(g *protogen.GeneratedFile, f *fileInfo) {
if len(f.allExtensions) == 0 {
return
}
g.P("var ", extensionTypesVarName(f), " = []", protoimplPackage.Ident("ExtensionInfo"), "{")
for _, extension := range f.allExtensions {
for _, x := range f.allExtensions {
// For MessageSet extensions, the name used is the parent message.
name := extension.Desc.FullName()
if messageset.IsMessageSetExtension(extension.Desc) {
name := x.Desc.FullName()
if messageset.IsMessageSetExtension(x.Desc) {
name = name.Parent()
}
g.P("{")
g.P("ExtendedType: (*", extension.Extendee.GoIdent, ")(nil),")
goType, pointer := fieldGoType(g, f, extension)
g.P("ExtendedType: (*", x.Extendee.GoIdent, ")(nil),")
goType, pointer := fieldGoType(g, f, x.Extension)
if pointer {
goType = "*" + goType
}
g.P("ExtensionType: (", goType, ")(nil),")
g.P("Field: ", extension.Desc.Number(), ",")
g.P("Field: ", x.Desc.Number(), ",")
g.P("Name: ", strconv.Quote(string(name)), ",")
g.P("Tag: ", strconv.Quote(fieldProtobufTagValue(extension)), ",")
g.P("Tag: ", strconv.Quote(fieldProtobufTagValue(x.Extension)), ",")
g.P("Filename: ", strconv.Quote(f.Desc.Path()), ",")
g.P("},")
}
@ -809,21 +744,21 @@ func genExtensions(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo)
// Group extensions by the target message.
var orderedTargets []protogen.GoIdent
allExtensionsByTarget := make(map[protogen.GoIdent][]*protogen.Extension)
allExtensionsByPtr := make(map[*protogen.Extension]int)
for i, extension := range f.allExtensions {
target := extension.Extendee.GoIdent
allExtensionsByTarget := make(map[protogen.GoIdent][]*extensionInfo)
allExtensionsByPtr := make(map[*extensionInfo]int)
for i, x := range f.allExtensions {
target := x.Extendee.GoIdent
if len(allExtensionsByTarget[target]) == 0 {
orderedTargets = append(orderedTargets, target)
}
allExtensionsByTarget[target] = append(allExtensionsByTarget[target], extension)
allExtensionsByPtr[extension] = i
allExtensionsByTarget[target] = append(allExtensionsByTarget[target], x)
allExtensionsByPtr[x] = i
}
for _, target := range orderedTargets {
g.P("// Extension fields to ", target, ".")
g.P("var (")
for _, extension := range allExtensionsByTarget[target] {
xd := extension.Desc
for _, x := range allExtensionsByTarget[target] {
xd := x.Desc
typeName := xd.Kind().String()
switch xd.Kind() {
case protoreflect.EnumKind:
@ -833,17 +768,17 @@ func genExtensions(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo)
}
fieldName := string(xd.Name())
leadingComments := extension.Comments.Leading
leadingComments := x.Comments.Leading
if leadingComments != "" {
leadingComments += "\n"
}
leadingComments += protogen.Comments(fmt.Sprintf(" %v %v %v = %v;\n",
xd.Cardinality(), typeName, fieldName, xd.Number()))
leadingComments = appendDeprecationSuffix(leadingComments,
extension.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
x.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
g.P(leadingComments,
"E_", extension.GoIdent, " = &", extensionTypesVarName(f), "[", allExtensionsByPtr[extension], "]",
trailingComment(extension.Comments.Trailing))
"E_", x.GoIdent, " = &", extensionTypesVarName(f), "[", allExtensionsByPtr[x], "]",
trailingComment(x.Comments.Trailing))
}
g.P(")")
g.P()
@ -852,7 +787,7 @@ func genExtensions(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo)
// genMessageOneofWrapperTypes generates the oneof wrapper types and
// associates the types with the parent message type.
func genMessageOneofWrapperTypes(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
func genMessageOneofWrapperTypes(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
for _, oneof := range m.Oneofs {
ifName := oneofInterfaceName(oneof)
g.P("type ", ifName, " interface {")
@ -867,7 +802,7 @@ func genMessageOneofWrapperTypes(gen *protogen.Plugin, g *protogen.GeneratedFile
tags := structTags{
{"protobuf", fieldProtobufTagValue(field)},
}
if m.IsTracked {
if m.isTracked {
tags = append(tags, gotrackTags...)
}
leadingComments := appendDeprecationSuffix(field.Comments.Leading,

View File

@ -79,10 +79,10 @@ func genReflectFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f
}
var depOffsets []offsetEntry
for _, enum := range f.allEnums {
genEnum(enum, "")
genEnum(enum.Enum, "")
}
for _, message := range f.allMessages {
genMessage(message, "")
genMessage(message.Message, "")
}
depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "field type_name"})
for _, message := range f.allMessages {
@ -259,48 +259,50 @@ func genFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileI
g.P("}")
g.P()
onceVar := rawDescVarName(f) + "Once"
dataVar := rawDescVarName(f) + "Data"
g.P("var (")
g.P(onceVar, " ", syncPackage.Ident("Once"))
g.P(dataVar, " = ", rawDescVarName(f))
g.P(")")
g.P()
if f.needRawDesc {
onceVar := rawDescVarName(f) + "Once"
dataVar := rawDescVarName(f) + "Data"
g.P("var (")
g.P(onceVar, " ", syncPackage.Ident("Once"))
g.P(dataVar, " = ", rawDescVarName(f))
g.P(")")
g.P()
g.P("func ", rawDescVarName(f), "GZIP() []byte {")
g.P(onceVar, ".Do(func() {")
g.P(dataVar, " = ", protoimplPackage.Ident("X"), ".CompressGZIP(", dataVar, ")")
g.P("})")
g.P("return ", dataVar)
g.P("}")
g.P()
g.P("func ", rawDescVarName(f), "GZIP() []byte {")
g.P(onceVar, ".Do(func() {")
g.P(dataVar, " = ", protoimplPackage.Ident("X"), ".CompressGZIP(", dataVar, ")")
g.P("})")
g.P("return ", dataVar)
g.P("}")
g.P()
}
}
func genEnumReflectMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, enum *protogen.Enum) {
idx := f.allEnumsByPtr[enum]
func genEnumReflectMethods(g *protogen.GeneratedFile, f *fileInfo, e *enumInfo) {
idx := f.allEnumsByPtr[e]
typesVar := enumTypesVarName(f)
// Descriptor method.
g.P("func (", enum.GoIdent, ") Descriptor() ", protoreflectPackage.Ident("EnumDescriptor"), " {")
g.P("func (", e.GoIdent, ") Descriptor() ", protoreflectPackage.Ident("EnumDescriptor"), " {")
g.P("return ", typesVar, "[", idx, "].Descriptor()")
g.P("}")
g.P()
// Type method.
g.P("func (", enum.GoIdent, ") Type() ", protoreflectPackage.Ident("EnumType"), " {")
g.P("func (", e.GoIdent, ") Type() ", protoreflectPackage.Ident("EnumType"), " {")
g.P("return &", typesVar, "[", idx, "]")
g.P("}")
g.P()
// Number method.
g.P("func (x ", enum.GoIdent, ") Number() ", protoreflectPackage.Ident("EnumNumber"), " {")
g.P("func (x ", e.GoIdent, ") Number() ", protoreflectPackage.Ident("EnumNumber"), " {")
g.P("return ", protoreflectPackage.Ident("EnumNumber"), "(x)")
g.P("}")
g.P()
}
func genMessageReflectMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
idx := f.allMessagesByPtr[m.Message]
func genMessageReflectMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
idx := f.allMessagesByPtr[m]
typesVar := messageTypesVarName(f)
// ProtoReflect method.

View File

@ -12,7 +12,6 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
descriptorpb "google.golang.org/protobuf/types/descriptorpb"
reflect "reflect"
sync "sync"
)
var file_annotation_annotation_proto_extTypes = []protoimpl.ExtensionInfo{
@ -56,18 +55,6 @@ var file_annotation_annotation_proto_rawDesc = []byte{
0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
}
var (
file_annotation_annotation_proto_rawDescOnce sync.Once
file_annotation_annotation_proto_rawDescData = file_annotation_annotation_proto_rawDesc
)
func file_annotation_annotation_proto_rawDescGZIP() []byte {
file_annotation_annotation_proto_rawDescOnce.Do(func() {
file_annotation_annotation_proto_rawDescData = protoimpl.X.CompressGZIP(file_annotation_annotation_proto_rawDescData)
})
return file_annotation_annotation_proto_rawDescData
}
var file_annotation_annotation_proto_goTypes = []interface{}{
(*descriptorpb.MessageOptions)(nil), // 0: google.protobuf.MessageOptions
}

View File

@ -11,7 +11,6 @@ import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
var file_test_ext_proto_extTypes = []protoimpl.ExtensionInfo{
@ -49,18 +48,6 @@ var file_test_ext_proto_rawDesc = []byte{
0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x74, 0x65, 0x73, 0x74,
}
var (
file_test_ext_proto_rawDescOnce sync.Once
file_test_ext_proto_rawDescData = file_test_ext_proto_rawDesc
)
func file_test_ext_proto_rawDescGZIP() []byte {
file_test_ext_proto_rawDescOnce.Do(func() {
file_test_ext_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_ext_proto_rawDescData)
})
return file_test_ext_proto_rawDescData
}
var file_test_ext_proto_goTypes = []interface{}{
(*TestAllExtensions)(nil), // 0: goproto.proto.test.TestAllExtensions
}