|
@@ -13,6 +13,7 @@ import (
|
|
|
"encoding/hex"
|
|
"encoding/hex"
|
|
|
"fmt"
|
|
"fmt"
|
|
|
"strconv"
|
|
"strconv"
|
|
|
|
|
+ "strings"
|
|
|
|
|
|
|
|
"github.com/golang/protobuf/proto"
|
|
"github.com/golang/protobuf/proto"
|
|
|
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
|
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
|
@@ -31,22 +32,39 @@ func main() {
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func genFile(gen *protogen.Plugin, f *protogen.File) {
|
|
|
|
|
|
|
+type File struct {
|
|
|
|
|
+ *protogen.File
|
|
|
|
|
+ locationMap map[string][]*descpb.SourceCodeInfo_Location
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func genFile(gen *protogen.Plugin, file *protogen.File) {
|
|
|
|
|
+ f := &File{
|
|
|
|
|
+ File: file,
|
|
|
|
|
+ locationMap: make(map[string][]*descpb.SourceCodeInfo_Location),
|
|
|
|
|
+ }
|
|
|
|
|
+ for _, loc := range file.Proto.GetSourceCodeInfo().GetLocation() {
|
|
|
|
|
+ key := pathKey(loc.Path)
|
|
|
|
|
+ f.locationMap[key] = append(f.locationMap[key], loc)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
g := gen.NewGeneratedFile(f.GeneratedFilenamePrefix+".pb.go", f.GoImportPath)
|
|
g := gen.NewGeneratedFile(f.GeneratedFilenamePrefix+".pb.go", f.GoImportPath)
|
|
|
g.P("// Code generated by protoc-gen-go. DO NOT EDIT.")
|
|
g.P("// Code generated by protoc-gen-go. DO NOT EDIT.")
|
|
|
g.P("// source: ", f.Desc.Path())
|
|
g.P("// source: ", f.Desc.Path())
|
|
|
g.P()
|
|
g.P()
|
|
|
|
|
+ const filePackageField = 2 // FileDescriptorProto.package
|
|
|
|
|
+ genComment(g, f, []int32{filePackageField})
|
|
|
|
|
+ g.P()
|
|
|
g.P("package ", f.GoPackageName)
|
|
g.P("package ", f.GoPackageName)
|
|
|
g.P()
|
|
g.P()
|
|
|
|
|
|
|
|
- for _, m := range f.Messages {
|
|
|
|
|
- genMessage(gen, g, m)
|
|
|
|
|
|
|
+ for _, message := range f.Messages {
|
|
|
|
|
+ genMessage(gen, g, f, message)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
genFileDescriptor(gen, g, f)
|
|
genFileDescriptor(gen, g, f)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func genFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f *protogen.File) {
|
|
|
|
|
|
|
+func genFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f *File) {
|
|
|
// Determine the name of the var holding the file descriptor:
|
|
// Determine the name of the var holding the file descriptor:
|
|
|
//
|
|
//
|
|
|
// fileDescriptor_<hash of filename>
|
|
// fileDescriptor_<hash of filename>
|
|
@@ -90,12 +108,37 @@ func genFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f *proto
|
|
|
g.P()
|
|
g.P()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, m *protogen.Message) {
|
|
|
|
|
- g.P("type ", m.GoIdent, " struct {")
|
|
|
|
|
|
|
+func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *File, message *protogen.Message) {
|
|
|
|
|
+ genComment(g, f, message.Path)
|
|
|
|
|
+ g.P("type ", message.GoIdent, " struct {")
|
|
|
g.P("}")
|
|
g.P("}")
|
|
|
g.P()
|
|
g.P()
|
|
|
|
|
|
|
|
- for _, nested := range m.Messages {
|
|
|
|
|
- genMessage(gen, g, nested)
|
|
|
|
|
|
|
+ for _, nested := range message.Messages {
|
|
|
|
|
+ genMessage(gen, g, f, nested)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func genComment(g *protogen.GeneratedFile, f *File, path []int32) {
|
|
|
|
|
+ for _, loc := range f.locationMap[pathKey(path)] {
|
|
|
|
|
+ if loc.LeadingComments == nil {
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+ for _, line := range strings.Split(strings.TrimSuffix(loc.GetLeadingComments(), "\n"), "\n") {
|
|
|
|
|
+ g.P("//", line)
|
|
|
|
|
+ }
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// pathKey converts a location path to a string suitable for use as a map key.
|
|
|
|
|
+func pathKey(path []int32) string {
|
|
|
|
|
+ var buf []byte
|
|
|
|
|
+ for i, x := range path {
|
|
|
|
|
+ if i != 0 {
|
|
|
|
|
+ buf = append(buf, ',')
|
|
|
|
|
+ }
|
|
|
|
|
+ buf = strconv.AppendInt(buf, int64(x), 10)
|
|
|
}
|
|
}
|
|
|
|
|
+ return string(buf)
|
|
|
}
|
|
}
|