protogen: generate .meta file with code annotations
When the generator parameter 'annotate_code' is provided, generate a .meta
file containing a GeneratedCodeInfo message describing the generated code's
relation to the source .proto file.
Annotations are added with (*protogen.GeneratedFile).Annotate, which takes the
name of a Go identifier (e.g., "SomeMessage" or "SomeMessage.GetField") and an
associated source location. The generator examines the generated AST to
determine source offsets for the symbols.
Change the []int32 "Path" in protogen types to a "Location", which also captures
the source file name.
Change-Id: Icd2340875831f40a1f91d495e3bd7ea381475c77
Reviewed-on: https://go-review.googlesource.com/c/139759
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/cmd/protoc-gen-go/internal_gengo/main.go b/cmd/protoc-gen-go/internal_gengo/main.go
index a0a65cb..c3154f5 100644
--- a/cmd/protoc-gen-go/internal_gengo/main.go
+++ b/cmd/protoc-gen-go/internal_gengo/main.go
@@ -76,7 +76,7 @@
}
g.P()
const filePackageField = 2 // FileDescriptorProto.package
- genComment(g, f, []int32{filePackageField})
+ genComment(g, f, protogen.Location{Path: []int32{filePackageField}})
g.P()
g.P("package ", f.GoPackageName)
g.P()
@@ -237,12 +237,14 @@
}
func genEnum(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, enum *protogen.Enum) {
- genComment(g, f, enum.Path)
+ genComment(g, f, enum.Location)
+ g.Annotate(enum.GoIdent.GoName, enum.Location)
g.P("type ", enum.GoIdent, " int32",
deprecationComment(enumOptions(gen, enum).GetDeprecated()))
g.P("const (")
for _, value := range enum.Values {
- genComment(g, f, value.Path)
+ genComment(g, f, value.Location)
+ g.Annotate(value.GoIdent.GoName, value.Location)
g.P(value.GoIdent, " ", enum.GoIdent, " = ", value.Desc.Number(),
deprecationComment(enumValueOptions(gen, value).GetDeprecated()))
}
@@ -294,8 +296,8 @@
}
var indexes []string
- for i := 1; i < len(enum.Path); i += 2 {
- indexes = append(indexes, strconv.Itoa(int(enum.Path[i])))
+ for i := 1; i < len(enum.Location.Path); i += 2 {
+ indexes = append(indexes, strconv.Itoa(int(enum.Location.Path[i])))
}
g.P("func (", enum.GoIdent, ") EnumDescriptor() ([]byte, []int) {")
g.P("return ", f.descriptorVar, ", []int{", strings.Join(indexes, ","), "}")
@@ -333,13 +335,14 @@
return
}
- hasComment := genComment(g, f, message.Path)
+ hasComment := genComment(g, f, message.Location)
if messageOptions(gen, message).GetDeprecated() {
if hasComment {
g.P("//")
}
g.P(deprecationComment(true))
}
+ g.Annotate(message.GoIdent.GoName, message.Location)
g.P("type ", message.GoIdent, " struct {")
for _, field := range message.Fields {
if field.OneofType != nil {
@@ -352,7 +355,7 @@
}
continue
}
- genComment(g, f, field.Path)
+ genComment(g, f, field.Location)
goType, pointer := fieldGoType(g, field)
if pointer {
goType = "*" + goType
@@ -369,6 +372,7 @@
fmt.Sprintf("protobuf_val:%q", fieldProtobufTag(val)),
)
}
+ g.Annotate(message.GoIdent.GoName+"."+field.GoName, field.Location)
g.P(field.GoName, " ", goType, " `", strings.Join(tags, " "), "`",
deprecationComment(fieldOptions(gen, field).GetDeprecated()))
}
@@ -402,8 +406,8 @@
g.P("func (*", message.GoIdent, ") ProtoMessage() {}")
// Descriptor
var indexes []string
- for i := 1; i < len(message.Path); i += 2 {
- indexes = append(indexes, strconv.Itoa(int(message.Path[i])))
+ for i := 1; i < len(message.Location.Path); i += 2 {
+ indexes = append(indexes, strconv.Itoa(int(message.Location.Path[i])))
}
g.P("func (*", message.GoIdent, ") Descriptor() ([]byte, []int) {")
g.P("return ", f.descriptorVar, ", []int{", strings.Join(indexes, ","), "}")
@@ -547,6 +551,7 @@
if fieldOptions(gen, field).GetDeprecated() {
g.P(deprecationComment(true))
}
+ g.Annotate(message.GoIdent.GoName+".Get"+field.GoName, field.Location)
g.P("func (m *", message.GoIdent, ") Get", field.GoName, "() ", goType, " {")
if field.OneofType != nil {
g.P("if x, ok := m.Get", field.OneofType.GoName, "().(*", fieldOneofType(field), "); ok {")
@@ -897,8 +902,8 @@
}
}
-func genComment(g *protogen.GeneratedFile, f *fileInfo, path []int32) (hasComment bool) {
- for _, loc := range f.locationMap[pathKey(path)] {
+func genComment(g *protogen.GeneratedFile, f *fileInfo, loc protogen.Location) (hasComment bool) {
+ for _, loc := range f.locationMap[pathKey(loc.Path)] {
if loc.LeadingComments == nil {
continue
}