util.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package parser
  2. import (
  3. "bufio"
  4. "errors"
  5. "strings"
  6. "github.com/tal-tech/go-zero/tools/goctl/api/spec"
  7. )
  8. var emptyType spec.Type
  9. type ApiStruct struct {
  10. Info string
  11. StructBody string
  12. Service string
  13. Imports string
  14. serviceBeginLine int
  15. }
  16. func GetType(api *spec.ApiSpec, t string) spec.Type {
  17. for _, tp := range api.Types {
  18. if tp.Name == t {
  19. return tp
  20. }
  21. }
  22. return emptyType
  23. }
  24. func isLetterDigit(r rune) bool {
  25. return (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || ('0' <= r && r <= '9')
  26. }
  27. func isSpace(r rune) bool {
  28. return r == ' ' || r == '\t'
  29. }
  30. func isSlash(r rune) bool {
  31. return r == '/'
  32. }
  33. func isNewline(r rune) bool {
  34. return r == '\n' || r == '\r'
  35. }
  36. func read(r *bufio.Reader) (rune, error) {
  37. ch, _, err := r.ReadRune()
  38. return ch, err
  39. }
  40. func readLine(r *bufio.Reader) (string, error) {
  41. line, _, err := r.ReadLine()
  42. if err != nil {
  43. return "", err
  44. } else {
  45. return string(line), nil
  46. }
  47. }
  48. func skipSpaces(r *bufio.Reader) error {
  49. for {
  50. next, err := read(r)
  51. if err != nil {
  52. return err
  53. }
  54. if !isSpace(next) {
  55. return unread(r)
  56. }
  57. }
  58. }
  59. func unread(r *bufio.Reader) error {
  60. return r.UnreadRune()
  61. }
  62. func ParseApi(api string) (*ApiStruct, error) {
  63. var result ApiStruct
  64. scanner := bufio.NewScanner(strings.NewReader(api))
  65. var parseInfo = false
  66. var parseImport = false
  67. var parseType = false
  68. var parseService = false
  69. var segment string
  70. for scanner.Scan() {
  71. line := strings.TrimSpace(scanner.Text())
  72. if line == "info(" {
  73. parseInfo = true
  74. }
  75. if line == ")" && parseInfo {
  76. parseInfo = false
  77. result.Info = segment + ")"
  78. segment = ""
  79. continue
  80. }
  81. if isImportBeginLine(line) {
  82. parseImport = true
  83. }
  84. if parseImport && (isTypeBeginLine(line) || isServiceBeginLine(line)) {
  85. parseImport = false
  86. result.Imports = segment
  87. segment = line + "\n"
  88. continue
  89. }
  90. if isTypeBeginLine(line) {
  91. parseType = true
  92. }
  93. if isServiceBeginLine(line) {
  94. parseService = true
  95. if parseType {
  96. parseType = false
  97. result.StructBody = segment
  98. segment = line + "\n"
  99. continue
  100. }
  101. }
  102. segment += scanner.Text() + "\n"
  103. }
  104. if !parseService {
  105. return nil, errors.New("no service defined")
  106. }
  107. result.Service = segment
  108. result.serviceBeginLine = lineBeginOfService(api)
  109. return &result, nil
  110. }
  111. func isImportBeginLine(line string) bool {
  112. return strings.HasPrefix(line, "import") && (strings.HasSuffix(line, ".api") || strings.HasSuffix(line, `.api"`))
  113. }
  114. func isTypeBeginLine(line string) bool {
  115. return strings.HasPrefix(line, "type")
  116. }
  117. func isServiceBeginLine(line string) bool {
  118. return strings.HasPrefix(line, "@server") || (strings.HasPrefix(line, "service") && strings.HasSuffix(line, "{"))
  119. }
  120. func lineBeginOfService(api string) int {
  121. scanner := bufio.NewScanner(strings.NewReader(api))
  122. var number = 0
  123. for scanner.Scan() {
  124. line := strings.TrimSpace(scanner.Text())
  125. if isServiceBeginLine(line) {
  126. break
  127. }
  128. number++
  129. }
  130. return number
  131. }