cmd/protoc-gen-go: add support for field-tracking

Field-tracking is an experimental feature in the Go linker
where it statically tracks whether a Go struct field is used.
This CL modifies the generator to emit special markers that
tells the linker to know which fields to track.

Change-Id: I235da3f3d6c0ef2021b5fe1c16106ebb8fd6f557
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/189558
Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
Joe Tsai 2019-08-08 17:18:32 -07:00
parent 2e7817f117
commit 26aef9d6d6
8 changed files with 1405 additions and 116 deletions

View File

@ -1,35 +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 (
"sync"
"google.golang.org/protobuf/compiler/protogen"
)
// messageAPIFlags provides flags that control the generated API.
type messageAPIFlags struct {
WeakMapField bool
}
var messageAPIFlagsCache sync.Map
func loadMessageAPIFlags(message *protogen.Message) messageAPIFlags {
if flags, ok := messageAPIFlagsCache.Load(message); ok {
return flags.(messageAPIFlags)
}
var flags messageAPIFlags
for _, field := range message.Fields {
if field.Desc.IsWeak() {
flags.WeakMapField = true
break
}
}
messageAPIFlagsCache.Store(message, flags)
return flags
}

View File

@ -0,0 +1,51 @@
// 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

@ -402,35 +402,42 @@ func genEnum(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, enum
}
}
type messageInfo struct {
*protogen.Message
messageFlags
}
func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message) {
if message.Desc.IsMapEntry() {
return
}
m := &messageInfo{message, loadMessageFlags(message)}
// Message type declaration.
g.Annotate(message.GoIdent.GoName, message.Location)
leadingComments := appendDeprecationSuffix(message.Comments.Leading,
message.Desc.Options().(*descriptorpb.MessageOptions).GetDeprecated())
g.Annotate(m.GoIdent.GoName, m.Location)
leadingComments := appendDeprecationSuffix(m.Comments.Leading,
m.Desc.Options().(*descriptorpb.MessageOptions).GetDeprecated())
g.P(leadingComments,
"type ", message.GoIdent, " struct {")
genMessageFields(g, f, message)
"type ", m.GoIdent, " struct {")
genMessageFields(g, f, m)
g.P("}")
g.P()
genDefaultDecls(g, f, message)
genMessageMethods(gen, g, f, message)
genOneofWrapperTypes(gen, g, f, message)
genMessageDefaultDecls(g, f, m)
genMessageMethods(gen, g, f, m)
genMessageOneofWrapperTypes(gen, g, f, m)
}
func genMessageFields(g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message) {
sf := f.allMessageFieldsByPtr[message]
genMessageInternalFields(g, message, sf)
for _, field := range message.Fields {
genMessageField(g, f, message, field, sf)
func genMessageFields(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
sf := f.allMessageFieldsByPtr[m.Message]
genMessageInternalFields(g, f, m, sf)
for _, field := range m.Fields {
genMessageField(g, f, m, field, sf)
}
}
func genMessageInternalFields(g *protogen.GeneratedFile, message *protogen.Message, sf *structFields) {
func genMessageInternalFields(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo, sf *structFields) {
if generateMessageStateFields {
g.P("state ", protoimplPackage.Ident("MessageState"))
sf.append("state")
@ -442,7 +449,7 @@ func genMessageInternalFields(g *protogen.GeneratedFile, message *protogen.Messa
g.P("sizeCache", " ", protoimplPackage.Ident("SizeCache"))
sf.append("sizeCache")
}
if loadMessageAPIFlags(message).WeakMapField {
if m.HasWeak {
g.P("XXX_weak", " ", protoimplPackage.Ident("WeakFields"), jsonIgnoreTags)
sf.append("XXX_weak")
}
@ -453,7 +460,7 @@ func genMessageInternalFields(g *protogen.GeneratedFile, message *protogen.Messa
g.P("unknownFields", " ", protoimplPackage.Ident("UnknownFields"))
sf.append("unknownFields")
}
if message.Desc.ExtensionRanges().Len() > 0 {
if m.Desc.ExtensionRanges().Len() > 0 {
if generateExportedExtensionFields {
g.P("XXX_InternalExtensions", " ", protoimplPackage.Ident("ExtensionFields"), jsonIgnoreTags)
sf.append("XXX_InternalExtensions")
@ -467,7 +474,7 @@ func genMessageInternalFields(g *protogen.GeneratedFile, message *protogen.Messa
}
}
func genMessageField(g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message, field *protogen.Field, sf *structFields) {
func genMessageField(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo, 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
@ -480,8 +487,11 @@ func genMessageField(g *protogen.GeneratedFile, f *fileInfo, message *protogen.M
tags := structTags{
{"protobuf_oneof", string(oneof.Desc.Name())},
}
if m.IsTracked {
tags = append(tags, gotrackTags...)
}
g.Annotate(message.GoIdent.GoName+"."+oneof.GoName, oneof.Location)
g.Annotate(m.GoIdent.GoName+"."+oneof.GoName, oneof.Location)
leadingComments := oneof.Comments.Leading
if leadingComments != "" {
leadingComments += "\n"
@ -512,12 +522,15 @@ func genMessageField(g *protogen.GeneratedFile, f *fileInfo, message *protogen.M
{"protobuf_val", fieldProtobufTagValue(val)},
}...)
}
if m.IsTracked {
tags = append(tags, gotrackTags...)
}
name := field.GoName
if field.Desc.IsWeak() {
name = "XXX_weak_" + name
}
g.Annotate(message.GoIdent.GoName+"."+name, field.Location)
g.Annotate(m.GoIdent.GoName+"."+name, field.Location)
leadingComments := appendDeprecationSuffix(field.Comments.Leading,
field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
g.P(leadingComments,
@ -526,15 +539,15 @@ func genMessageField(g *protogen.GeneratedFile, f *fileInfo, message *protogen.M
sf.append(field.GoName)
}
// genDefaultDecls generates consts and vars holding the default
// genMessageDefaultDecls generates consts and vars holding the default
// values of fields.
func genDefaultDecls(g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message) {
func genMessageDefaultDecls(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
var consts, vars []string
for _, field := range message.Fields {
for _, field := range m.Fields {
if !field.Desc.HasDefault() {
continue
}
name := "Default_" + message.GoIdent.GoName + "_" + field.GoName
name := "Default_" + m.GoIdent.GoName + "_" + field.GoName
goType, _ := fieldGoType(g, f, field)
defVal := field.Desc.Default()
switch field.Desc.Kind() {
@ -566,7 +579,7 @@ func genDefaultDecls(g *protogen.GeneratedFile, f *fileInfo, message *protogen.M
}
}
if len(consts) > 0 {
g.P("// Default values for ", message.GoIdent, " fields.")
g.P("// Default values for ", m.GoIdent, " fields.")
g.P("const (")
for _, s := range consts {
g.P(s)
@ -574,7 +587,7 @@ func genDefaultDecls(g *protogen.GeneratedFile, f *fileInfo, message *protogen.M
g.P(")")
}
if len(vars) > 0 {
g.P("// Default values for ", message.GoIdent, " fields.")
g.P("// Default values for ", m.GoIdent, " fields.")
g.P("var (")
for _, s := range vars {
g.P(s)
@ -584,40 +597,40 @@ func genDefaultDecls(g *protogen.GeneratedFile, f *fileInfo, message *protogen.M
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 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 genMessageBaseMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message) {
func genMessageBaseMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
// Reset method.
g.P("func (x *", message.GoIdent, ") Reset() {")
g.P("*x = ", message.GoIdent, "{}")
g.P("func (x *", m.GoIdent, ") Reset() {")
g.P("*x = ", m.GoIdent, "{}")
g.P("}")
g.P()
// String method.
g.P("func (x *", message.GoIdent, ") String() string {")
g.P("func (x *", m.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("func (*", m.GoIdent, ") ProtoMessage() {}")
g.P()
// ProtoReflect method.
genMessageReflectMethods(gen, g, f, message)
genMessageReflectMethods(gen, g, f, m)
// Descriptor method.
if generateRawDescMethods {
var indexes []string
for i := 1; i < len(message.Location.Path); i += 2 {
indexes = append(indexes, strconv.Itoa(int(message.Location.Path[i])))
for i := 1; i < len(m.Location.Path); i += 2 {
indexes = append(indexes, strconv.Itoa(int(m.Location.Path[i])))
}
g.P("// Deprecated: Use ", message.GoIdent, ".ProtoReflect.Descriptor instead.")
g.P("func (*", message.GoIdent, ") Descriptor() ([]byte, []int) {")
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()
@ -625,9 +638,9 @@ func genMessageBaseMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *f
// ExtensionRangeArray method.
if generateExtensionRangeMethods {
if extranges := message.Desc.ExtensionRanges(); extranges.Len() > 0 {
if extranges := m.Desc.ExtensionRanges(); extranges.Len() > 0 {
protoExtRange := protoifacePackage.Ident("ExtensionRangeV1")
extRangeVar := "extRange_" + message.GoIdent.GoName
extRangeVar := "extRange_" + m.GoIdent.GoName
g.P("var ", extRangeVar, " = []", protoExtRange, " {")
for i := 0; i < extranges.Len(); i++ {
r := extranges.Get(i)
@ -635,8 +648,8 @@ func genMessageBaseMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *f
}
g.P("}")
g.P()
g.P("// Deprecated: Use ", message.GoIdent, ".ProtoReflect.Descriptor.ExtensionRanges instead.")
g.P("func (*", message.GoIdent, ") ExtensionRangeArray() []", protoExtRange, " {")
g.P("// Deprecated: Use ", m.GoIdent, ".ProtoReflect.Descriptor.ExtensionRanges instead.")
g.P("func (*", m.GoIdent, ") ExtensionRangeArray() []", protoExtRange, " {")
g.P("return ", extRangeVar)
g.P("}")
g.P()
@ -644,12 +657,14 @@ func genMessageBaseMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *f
}
}
func genMessageGetterMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message) {
for _, field := range message.Fields {
func genMessageGetterMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
for _, field := range m.Fields {
genNoInterfacePragma(g, m.IsTracked)
// 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.Annotate(m.GoIdent.GoName+".Get"+oneof.GoName, oneof.Location)
g.P("func (m *", m.GoIdent.GoName, ") Get", oneof.GoName, "() ", oneofInterfaceName(oneof), " {")
g.P("if m != nil {")
g.P("return m.", oneof.GoName)
g.P("}")
@ -660,16 +675,16 @@ func genMessageGetterMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f
// Getter for message field.
goType, pointer := fieldGoType(g, f, field)
defaultValue := fieldDefaultValue(g, message, field)
g.Annotate(message.GoIdent.GoName+".Get"+field.GoName, field.Location)
defaultValue := fieldDefaultValue(g, m, field)
g.Annotate(m.GoIdent.GoName+".Get"+field.GoName, field.Location)
leadingComments := appendDeprecationSuffix("",
field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
switch {
case field.Desc.IsWeak():
g.P(leadingComments, "func (x *", message.GoIdent, ") Get", field.GoName, "() ", protoifacePackage.Ident("MessageV1"), "{")
g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", protoifacePackage.Ident("MessageV1"), "{")
g.P("if x != nil {")
g.P("v := x.XXX_weak[", field.Desc.Number(), "]")
g.P("_ = x.XXX_weak_" + field.GoName) // for field tracking
g.P("_ = x.XXX_weak_" + field.GoName) // for field-tracking
g.P("if v != nil {")
g.P("return v")
g.P("}")
@ -677,14 +692,14 @@ func genMessageGetterMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f
g.P("return ", protoimplPackage.Ident("X"), ".WeakNil(", strconv.Quote(string(field.Message.Desc.FullName())), ")")
g.P("}")
case field.Oneof != nil:
g.P(leadingComments, "func (x *", message.GoIdent, ") Get", field.GoName, "() ", goType, " {")
g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", goType, " {")
g.P("if x, ok := x.Get", field.Oneof.GoName, "().(*", field.GoIdent, "); ok {")
g.P("return x.", field.GoName)
g.P("}")
g.P("return ", defaultValue)
g.P("}")
default:
g.P(leadingComments, "func (x *", message.GoIdent, ") Get", field.GoName, "() ", goType, " {")
g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", goType, " {")
if field.Desc.Syntax() == protoreflect.Proto3 || defaultValue == "nil" {
g.P("if x != nil {")
} else {
@ -703,25 +718,29 @@ func genMessageGetterMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f
}
}
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)
leadingComments := appendDeprecationSuffix("",
field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
g.P(leadingComments, "func (x *", message.GoIdent, ") Set", field.GoName, "(v ", protoifacePackage.Ident("MessageV1"), ") {")
g.P("if x.XXX_weak == nil {")
g.P("x.XXX_weak = make(", protoimplPackage.Ident("WeakFields"), ")")
g.P("}")
g.P("if v == nil {")
g.P("delete(x.XXX_weak, ", field.Desc.Number(), ")")
g.P("} else {")
g.P("x.XXX_weak[", field.Desc.Number(), "] = v")
g.P("x.XXX_weak_"+field.GoName, " = struct{}{}") // for field tracking
g.P("}")
g.P("}")
g.P()
func genMessageSetterMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
for _, field := range m.Fields {
if !field.Desc.IsWeak() {
continue
}
genNoInterfacePragma(g, m.IsTracked)
g.Annotate(m.GoIdent.GoName+".Set"+field.GoName, field.Location)
leadingComments := appendDeprecationSuffix("",
field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
g.P(leadingComments, "func (x *", m.GoIdent, ") Set", field.GoName, "(v ", protoifacePackage.Ident("MessageV1"), ") {")
g.P("if x.XXX_weak == nil {")
g.P("x.XXX_weak = make(", protoimplPackage.Ident("WeakFields"), ")")
g.P("}")
g.P("if v == nil {")
g.P("delete(x.XXX_weak, ", field.Desc.Number(), ")")
g.P("} else {")
g.P("x.XXX_weak[", field.Desc.Number(), "] = v")
g.P("x.XXX_weak_"+field.GoName, " = struct{}{}") // for field-tracking
g.P("}")
g.P("}")
g.P()
}
}
@ -785,12 +804,12 @@ func fieldProtobufTagValue(field *protogen.Field) string {
return tag.Marshal(field.Desc, enumName)
}
func fieldDefaultValue(g *protogen.GeneratedFile, message *protogen.Message, field *protogen.Field) string {
func fieldDefaultValue(g *protogen.GeneratedFile, m *messageInfo, field *protogen.Field) string {
if field.Desc.IsList() {
return "nil"
}
if field.Desc.HasDefault() {
defVarName := "Default_" + message.GoIdent.GoName + "_" + field.GoName
defVarName := "Default_" + m.GoIdent.GoName + "_" + field.GoName
if field.Desc.Kind() == protoreflect.BytesKind {
return "append([]byte(nil), " + defVarName + "...)"
}
@ -886,10 +905,10 @@ func genExtensions(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo)
}
}
// genOneofWrapperTypes generates the oneof wrapper types and
// genMessageOneofWrapperTypes 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 {
func genMessageOneofWrapperTypes(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
for _, oneof := range m.Oneofs {
ifName := oneofInterfaceName(oneof)
g.P("type ", ifName, " interface {")
g.P(ifName, "()")
@ -903,6 +922,9 @@ func genOneofWrapperTypes(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fi
tags := structTags{
{"protobuf", fieldProtobufTagValue(field)},
}
if m.IsTracked {
tags = append(tags, gotrackTags...)
}
leadingComments := appendDeprecationSuffix(field.Comments.Leading,
field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
g.P(leadingComments,
@ -924,12 +946,24 @@ func oneofInterfaceName(oneof *protogen.Oneof) string {
return "is" + oneof.GoIdent.GoName
}
var jsonIgnoreTags = structTags{{"json", "-"}}
// genNoInterfacePragma generates a standalone "nointerface" pragma to
// decorate methods with field-tracking support.
func genNoInterfacePragma(g *protogen.GeneratedFile, tracked bool) {
if tracked {
g.P("//go:nointerface")
g.P()
}
}
var (
gotrackTags = structTags{{"go", "track"}}
jsonIgnoreTags = structTags{{"json", "-"}}
)
// structTags is a data structure for build idiomatic Go struct tags.
// Each [2]string is a key-value pair, where value is the unescaped string.
//
// Example: structTags{{"key", "value"}} -> `key:"value"`
// Example: structTags{{"key", "value"}}.String() -> `key:"value"`
type structTags [][2]string
func (tags structTags) String() string {

View File

@ -302,12 +302,12 @@ func genEnumReflectMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *f
g.P()
}
func genMessageReflectMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message) {
idx := f.allMessagesByPtr[message]
func genMessageReflectMethods(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
idx := f.allMessagesByPtr[m.Message]
typesVar := messageTypesVarName(f)
// ProtoReflect method.
g.P("func (x *", message.GoIdent, ") ProtoReflect() ", protoreflectPackage.Ident("Message"), " {")
g.P("func (x *", m.GoIdent, ") ProtoReflect() ", protoreflectPackage.Ident("Message"), " {")
g.P("mi := &", typesVar, "[", idx, "]")
if generateMessageStateFields {
g.P("if ", protoimplPackage.Ident("UnsafeEnabled"), " && x != nil {")

View File

@ -0,0 +1,106 @@
// 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.
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: annotation/annotation.proto
package annotation
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
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{
{
ExtendedType: (*descriptorpb.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 37383685,
Name: "go_annotation.track_field_use",
Tag: "varint,37383685,opt,name=track_field_use",
Filename: "annotation/annotation.proto",
},
}
// Extension fields to descriptorpb.MessageOptions.
var (
// Setting this on a message enables tracking of which fields in the message
// a specific binary might access. As a consequence, it also disables the use
// of the message accessor methods to satisfy interfaces: they can only be
// called directly.
//
// optional bool track_field_use = 37383685;
E_TrackFieldUse = &file_annotation_annotation_proto_extTypes[0]
)
var File_annotation_annotation_proto protoreflect.FileDescriptor
var file_annotation_annotation_proto_rawDesc = []byte{
0x0a, 0x1b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x61, 0x6e, 0x6e,
0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x67,
0x6f, 0x5f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x20, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3a, 0x4a,
0x0a, 0x0f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x75, 0x73,
0x65, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f,
0x6e, 0x73, 0x18, 0x85, 0xdc, 0xe9, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x74, 0x72, 0x61,
0x63, 0x6b, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x55, 0x73, 0x65, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x61, 0x6e, 0x6e,
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
}
var file_annotation_annotation_proto_depIdxs = []int32{
0, // 0: go_annotation.track_field_use:extendee -> google.protobuf.MessageOptions
1, // [1:1] is the sub-list for method output_type
1, // [1:1] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
0, // [0:1] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_annotation_annotation_proto_init() }
func file_annotation_annotation_proto_init() {
if File_annotation_annotation_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_annotation_annotation_proto_rawDesc,
NumEnums: 0,
NumMessages: 0,
NumExtensions: 1,
NumServices: 0,
},
GoTypes: file_annotation_annotation_proto_goTypes,
DependencyIndexes: file_annotation_annotation_proto_depIdxs,
ExtensionInfos: file_annotation_annotation_proto_extTypes,
}.Build()
File_annotation_annotation_proto = out.File
file_annotation_annotation_proto_rawDesc = nil
file_annotation_annotation_proto_goTypes = nil
file_annotation_annotation_proto_depIdxs = nil
}

View File

@ -0,0 +1,19 @@
// 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.
syntax = "proto2";
package go_annotation;
import "google/protobuf/descriptor.proto";
option go_package = "google.golang.org/protobuf/internal/testprotos/annotation";
extend google.protobuf.MessageOptions {
// Setting this on a message enables tracking of which fields in the message
// a specific binary might access. As a consequence, it also disables the use
// of the message accessor methods to satisfy interfaces: they can only be
// called directly.
optional bool track_field_use = 37383685;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,75 @@
// Copyright 2018 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.
syntax = "proto2";
package goproto.proto.test;
import "annotation/annotation.proto";
import "test/test.proto";
import weak "test/weak1/test_weak.proto";
import weak "test/weak2/test_weak.proto";
option go_package = "google.golang.org/protobuf/internal/testprotos/fieldtrack";
message TestFieldTrack {
option (go_annotation.track_field_use) = true;
optional int32 optional_int32 = 1;
optional int64 optional_int64 = 2;
optional uint32 optional_uint32 = 3;
optional uint64 optional_uint64 = 4;
optional sint32 optional_sint32 = 5;
optional sint64 optional_sint64 = 6;
optional fixed32 optional_fixed32 = 7;
optional fixed64 optional_fixed64 = 8;
optional sfixed32 optional_sfixed32 = 9;
optional sfixed64 optional_sfixed64 = 10;
optional float optional_float = 11;
optional double optional_double = 12;
optional bool optional_bool = 13;
optional string optional_string = 14;
optional bytes optional_bytes = 15;
optional goproto.proto.test.TestAllTypes.NestedEnum optional_enum = 16;
optional goproto.proto.test.TestAllTypes.NestedMessage optional_message = 17;
repeated int32 repeated_int32 = 21;
repeated int64 repeated_int64 = 22;
repeated uint32 repeated_uint32 = 23;
repeated uint64 repeated_uint64 = 24;
repeated sint32 repeated_sint32 = 25;
repeated sint64 repeated_sint64 = 26;
repeated fixed32 repeated_fixed32 = 27;
repeated fixed64 repeated_fixed64 = 28;
repeated sfixed32 repeated_sfixed32 = 29;
repeated sfixed64 repeated_sfixed64 = 30;
repeated float repeated_float = 31;
repeated double repeated_double = 32;
repeated bool repeated_bool = 33;
repeated string repeated_string = 34;
repeated bytes repeated_bytes = 35;
repeated goproto.proto.test.TestAllTypes.NestedEnum repeated_enum = 36;
repeated goproto.proto.test.TestAllTypes.NestedMessage repeated_message = 37;
map <string, int32> map_string_int32 = 41;
map <string, int64> map_string_int64 = 42;
map <string, uint32> map_string_uint32 = 43;
map <string, uint64> map_string_uint64 = 44;
map <string, sint32> map_string_sint32 = 45;
map <string, sint64> map_string_sint64 = 46;
map <string, fixed32> map_string_fixed32 = 47;
map <string, fixed64> map_string_fixed64 = 48;
map <string, sfixed32> map_string_sfixed32 = 49;
map <string, sfixed64> map_string_sfixed64 = 50;
map <string, float> map_string_float = 51;
map <string, double> map_string_double = 52;
map <string, bool> map_string_bool = 53;
map <string, string> map_string_string = 54;
map <string, bytes> map_string_bytes = 55;
map <string, goproto.proto.test.TestAllTypes.NestedEnum> map_string_enum = 56;
map <string, goproto.proto.test.TestAllTypes.NestedMessage> map_string_message = 57;
optional goproto.proto.test.weak.WeakImportMessage1 weak_message1 = 100 [weak=true];
optional goproto.proto.test.weak.WeakImportMessage2 weak_message2 = 101 [weak=true];
}