entity.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. package parser
  2. import (
  3. "errors"
  4. "fmt"
  5. "strings"
  6. "github.com/tal-tech/go-zero/tools/goctl/api/spec"
  7. )
  8. type (
  9. entity struct {
  10. state *baseState
  11. api *spec.ApiSpec
  12. parser entityParser
  13. }
  14. entityParser interface {
  15. parseLine(line string, api *spec.ApiSpec, annos []spec.Annotation) error
  16. setEntityName(name string)
  17. }
  18. )
  19. func newEntity(state *baseState, api *spec.ApiSpec, parser entityParser) entity {
  20. return entity{
  21. state: state,
  22. api: api,
  23. parser: parser,
  24. }
  25. }
  26. func (s *entity) process() error {
  27. line, err := s.state.readLineSkipComment()
  28. if err != nil {
  29. return err
  30. }
  31. fields := strings.Fields(line)
  32. if len(fields) < 2 {
  33. return fmt.Errorf("invalid type definition for %q",
  34. strings.TrimSpace(strings.Trim(string(line), "{")))
  35. }
  36. if len(fields) == 2 {
  37. if fields[1] != leftBrace {
  38. return fmt.Errorf("bad string %q after type", fields[1])
  39. }
  40. } else if len(fields) == 3 {
  41. if fields[1] != typeStruct {
  42. return fmt.Errorf("bad string %q after type", fields[1])
  43. }
  44. if fields[2] != leftBrace {
  45. return fmt.Errorf("bad string %q after type", fields[2])
  46. }
  47. }
  48. s.parser.setEntityName(fields[0])
  49. var annos []spec.Annotation
  50. memberLoop:
  51. for {
  52. ch, err := s.state.readSkipComment()
  53. if err != nil {
  54. return err
  55. }
  56. var annoName string
  57. var builder strings.Builder
  58. switch {
  59. case ch == at:
  60. annotationLoop:
  61. for {
  62. next, err := s.state.readSkipComment()
  63. if err != nil {
  64. return err
  65. }
  66. switch {
  67. case isSpace(next):
  68. if builder.Len() > 0 && annoName == "" {
  69. annoName = builder.String()
  70. builder.Reset()
  71. }
  72. case isNewline(next):
  73. if builder.Len() == 0 {
  74. return errors.New("invalid annotation format")
  75. }
  76. if len(annoName) > 0 {
  77. value := builder.String()
  78. if value != string(leftParenthesis) {
  79. builder.Reset()
  80. annos = append(annos, spec.Annotation{
  81. Name: annoName,
  82. Value: value,
  83. })
  84. annoName = ""
  85. break annotationLoop
  86. }
  87. }
  88. case next == leftParenthesis:
  89. if builder.Len() == 0 {
  90. return errors.New("invalid annotation format")
  91. }
  92. annoName = builder.String()
  93. builder.Reset()
  94. if err := s.state.unread(); err != nil {
  95. return err
  96. }
  97. attrs, err := s.state.parseProperties()
  98. if err != nil {
  99. return err
  100. }
  101. annos = append(annos, spec.Annotation{
  102. Name: annoName,
  103. Properties: attrs,
  104. })
  105. annoName = ""
  106. break annotationLoop
  107. default:
  108. builder.WriteRune(next)
  109. }
  110. }
  111. case ch == rightBrace:
  112. break memberLoop
  113. case isLetterDigit(ch):
  114. if err := s.state.unread(); err != nil {
  115. return err
  116. }
  117. var line string
  118. line, err = s.state.readLineSkipComment()
  119. if err != nil {
  120. return err
  121. }
  122. line = strings.TrimSpace(line)
  123. if err := s.parser.parseLine(line, s.api, annos); err != nil {
  124. return err
  125. }
  126. annos = nil
  127. }
  128. }
  129. return nil
  130. }