genbm.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package genbm
  2. import (
  3. "bytes"
  4. "go/format"
  5. "os"
  6. "path/filepath"
  7. "strings"
  8. "github.com/golang/glog"
  9. "github.com/golang/protobuf/protoc-gen-go/descriptor"
  10. plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
  11. "go-common/app/tool/protoc-gen-bm/generator"
  12. )
  13. // New blademaster server code generator
  14. func New(jsonpb bool) generator.Generator {
  15. return &genbm{jsonpb: jsonpb}
  16. }
  17. type genbm struct {
  18. jsonpb bool
  19. }
  20. func (g *genbm) Generate(req *plugin.CodeGeneratorRequest) ([]*plugin.CodeGeneratorResponse_File, error) {
  21. var resp []*plugin.CodeGeneratorResponse_File
  22. files := req.GetProtoFile()
  23. for _, file := range files {
  24. respFile, ok, err := g.generateFile(file)
  25. if err != nil {
  26. return resp, err
  27. }
  28. if ok {
  29. resp = append(resp, respFile)
  30. }
  31. }
  32. return resp, nil
  33. }
  34. func (g *genbm) generateFile(file *descriptor.FileDescriptorProto) (*plugin.CodeGeneratorResponse_File, bool, error) {
  35. glog.V(1).Infof("process proto file %s", file.GetName())
  36. services := file.GetService()
  37. if len(services) == 0 {
  38. glog.V(5).Infof("proto file %s not included service descriptor", file.GetName())
  39. return nil, false, nil
  40. }
  41. var descs []*BMServerDescriptor
  42. for _, service := range services {
  43. server, err := ParseBMServer(service)
  44. if err != nil {
  45. return nil, false, err
  46. }
  47. descs = append(descs, server)
  48. }
  49. buf := new(bytes.Buffer)
  50. goPackageName := GetGoPackageName(file)
  51. gen := NewBMGenerate(goPackageName, descs, g.jsonpb)
  52. if err := gen.Generate(buf); err != nil {
  53. return nil, false, err
  54. }
  55. // format code
  56. data, err := format.Source(buf.Bytes())
  57. if err != nil {
  58. return nil, false, err
  59. }
  60. content := string(data)
  61. // no content
  62. if len(content) == 0 {
  63. return nil, false, nil
  64. }
  65. target := TargetFilePath(file)
  66. glog.V(1).Infof("generate code to %s", target)
  67. return &plugin.CodeGeneratorResponse_File{
  68. Content: &content,
  69. Name: &target,
  70. }, true, nil
  71. }
  72. // TargetFilePath find target file path
  73. func TargetFilePath(file *descriptor.FileDescriptorProto) string {
  74. fpath := file.GetName()
  75. protoDir := filepath.Dir(fpath)
  76. noExt := filepath.Base(fpath)
  77. for i := len(noExt) - 1; i >= 0 && !os.IsPathSeparator(noExt[i]); i-- {
  78. if noExt[i] == '.' {
  79. noExt = noExt[:i]
  80. }
  81. }
  82. target := noExt + ".pb.bm.go"
  83. options := file.GetOptions()
  84. if options != nil {
  85. goPackage := options.GetGoPackage()
  86. if goPackage != "" {
  87. goPackage = strings.Split(goPackage, ";")[0]
  88. if strings.Contains(goPackage, "/") {
  89. return filepath.Join(goPackage, target)
  90. }
  91. }
  92. }
  93. return filepath.Join(protoDir, target)
  94. }
  95. // GetGoPackageName last element from proto package name or go_package option
  96. func GetGoPackageName(file *descriptor.FileDescriptorProto) string {
  97. var goPackageName string
  98. protoPackage := file.GetPackage()
  99. goPackageName = splitLastElem(protoPackage, ".")
  100. options := file.GetOptions()
  101. if options == nil {
  102. return goPackageName
  103. }
  104. if goPackage := options.GetGoPackage(); goPackage != "" {
  105. if strings.Contains(goPackage, ";") {
  106. goPackageName = splitLastElem(goPackage, ";")
  107. } else {
  108. goPackageName = splitLastElem(goPackage, "/")
  109. }
  110. }
  111. return goPackageName
  112. }
  113. func splitLastElem(s string, seq string) string {
  114. seqs := strings.Split(s, seq)
  115. return seqs[len(seqs)-1]
  116. }