genpb_controller.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. // Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. package genpb
  7. import (
  8. "context"
  9. "fmt"
  10. "strings"
  11. "github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
  12. "github.com/gogf/gf/v2/frame/g"
  13. "github.com/gogf/gf/v2/os/gfile"
  14. "github.com/gogf/gf/v2/text/gregex"
  15. "github.com/gogf/gf/v2/text/gstr"
  16. )
  17. type generateControllerInput struct {
  18. OutputApiPath string
  19. OutputCtrlPath string
  20. }
  21. type generateCtrl struct {
  22. Name string
  23. Package string
  24. Version string
  25. Methods []generateCtrlMethod
  26. }
  27. type generateCtrlMethod struct {
  28. Name string
  29. Definition string
  30. }
  31. const (
  32. controllerTemplate = `
  33. package {Package}
  34. type Controller struct {
  35. {Version}.Unimplemented{Name}Server
  36. }
  37. func Register(s *grpcx.GrpcServer) {
  38. {Version}.Register{Name}Server(s.Server, &Controller{})
  39. }
  40. `
  41. controllerMethodTemplate = `
  42. func (*Controller) {Definition} {
  43. return nil, gerror.NewCode(gcode.CodeNotImplemented)
  44. }
  45. `
  46. )
  47. func (c CGenPb) generateController(ctx context.Context, in generateControllerInput) (err error) {
  48. files, err := gfile.ScanDirFile(in.OutputApiPath, "*_grpc.pb.go", true)
  49. if err != nil {
  50. return err
  51. }
  52. var controllers []generateCtrl
  53. for _, file := range files {
  54. fileControllers, err := c.parseControllers(file)
  55. if err != nil {
  56. return err
  57. }
  58. controllers = append(controllers, fileControllers...)
  59. }
  60. if len(controllers) == 0 {
  61. return nil
  62. }
  63. // Generate controller files.
  64. err = c.doGenerateControllers(in, controllers)
  65. return
  66. }
  67. func (c CGenPb) parseControllers(filePath string) ([]generateCtrl, error) {
  68. var (
  69. controllers []generateCtrl
  70. content = gfile.GetContents(filePath)
  71. )
  72. _, err := gregex.ReplaceStringFuncMatch(
  73. `type (\w+)Server interface {([\s\S]+?)}`,
  74. content,
  75. func(match []string) string {
  76. ctrl := generateCtrl{
  77. Name: match[1],
  78. Package: strings.ReplaceAll(gfile.Basename(gfile.Dir(gfile.Dir(filePath))), "-", "_"),
  79. Version: gfile.Basename(gfile.Dir(filePath)),
  80. Methods: make([]generateCtrlMethod, 0),
  81. }
  82. lines := gstr.Split(match[2], "\n")
  83. for _, line := range lines {
  84. line = gstr.Trim(line)
  85. if line == "" || !gstr.IsLetterUpper(line[0]) {
  86. continue
  87. }
  88. // Comment.
  89. if gregex.IsMatchString(`^//.+`, line) {
  90. continue
  91. }
  92. line, _ = gregex.ReplaceStringFuncMatch(
  93. `^(\w+)\(context\.Context, \*(\w+)\) \(\*(\w+), error\)$`,
  94. line,
  95. func(match []string) string {
  96. return fmt.Sprintf(
  97. `%s(ctx context.Context, req *%s.%s) (res *%s.%s, err error)`,
  98. match[1], ctrl.Version, match[2], ctrl.Version, match[3],
  99. )
  100. },
  101. )
  102. ctrl.Methods = append(ctrl.Methods, generateCtrlMethod{
  103. Name: gstr.Split(line, "(")[0],
  104. Definition: line,
  105. })
  106. }
  107. if len(ctrl.Methods) > 0 {
  108. controllers = append(controllers, ctrl)
  109. }
  110. return match[0]
  111. },
  112. )
  113. return controllers, err
  114. }
  115. func (c CGenPb) doGenerateControllers(in generateControllerInput, controllers []generateCtrl) (err error) {
  116. for _, controller := range controllers {
  117. err = c.doGenerateController(in, controller)
  118. if err != nil {
  119. return err
  120. }
  121. }
  122. err = utils.ReplaceGeneratedContentGFV2(in.OutputCtrlPath)
  123. return nil
  124. }
  125. func (c CGenPb) doGenerateController(in generateControllerInput, controller generateCtrl) (err error) {
  126. var (
  127. folderPath = gfile.Join(in.OutputCtrlPath, controller.Package)
  128. filePath = gfile.Join(folderPath, controller.Package+".go")
  129. isDirty bool
  130. )
  131. if !gfile.Exists(folderPath) {
  132. if err = gfile.Mkdir(folderPath); err != nil {
  133. return err
  134. }
  135. }
  136. if !gfile.Exists(filePath) {
  137. templateContent := gstr.ReplaceByMap(controllerTemplate, g.MapStrStr{
  138. "{Name}": controller.Name,
  139. "{Version}": controller.Version,
  140. "{Package}": controller.Package,
  141. })
  142. if err = gfile.PutContents(filePath, templateContent); err != nil {
  143. return err
  144. }
  145. isDirty = true
  146. }
  147. // Exist controller content.
  148. var ctrlContent string
  149. files, err := gfile.ScanDirFile(folderPath, "*.go", false)
  150. if err != nil {
  151. return err
  152. }
  153. for _, file := range files {
  154. if ctrlContent != "" {
  155. ctrlContent += "\n"
  156. }
  157. ctrlContent += gfile.GetContents(file)
  158. }
  159. // Generate method content.
  160. var generatedContent string
  161. for _, method := range controller.Methods {
  162. if gstr.Contains(ctrlContent, fmt.Sprintf(`%s(`, method.Name)) {
  163. continue
  164. }
  165. if generatedContent != "" {
  166. generatedContent += "\n"
  167. }
  168. generatedContent += gstr.ReplaceByMap(controllerMethodTemplate, g.MapStrStr{
  169. "{Definition}": method.Definition,
  170. })
  171. }
  172. if generatedContent != "" {
  173. err = gfile.PutContentsAppend(filePath, generatedContent)
  174. if err != nil {
  175. return err
  176. }
  177. isDirty = true
  178. }
  179. if isDirty {
  180. utils.GoFmt(filePath)
  181. }
  182. return nil
  183. }