api.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. package ast
  2. import (
  3. "fmt"
  4. "sort"
  5. "github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api"
  6. )
  7. // Api describes syntax for api
  8. type Api struct {
  9. LinePrefix string
  10. Syntax *SyntaxExpr
  11. Import []*ImportExpr
  12. importM map[string]PlaceHolder
  13. Info *InfoExpr
  14. Type []TypeExpr
  15. typeM map[string]PlaceHolder
  16. Service []*Service
  17. serviceM map[string]PlaceHolder
  18. handlerM map[string]PlaceHolder
  19. routeM map[string]PlaceHolder
  20. }
  21. // VisitApi implements from api.BaseApiParserVisitor
  22. func (v *ApiVisitor) VisitApi(ctx *api.ApiContext) interface{} {
  23. var final Api
  24. final.importM = map[string]PlaceHolder{}
  25. final.typeM = map[string]PlaceHolder{}
  26. final.serviceM = map[string]PlaceHolder{}
  27. final.handlerM = map[string]PlaceHolder{}
  28. final.routeM = map[string]PlaceHolder{}
  29. for _, each := range ctx.AllSpec() {
  30. root := each.Accept(v).(*Api)
  31. v.acceptSyntax(root, &final)
  32. v.accetpImport(root, &final)
  33. v.acceptInfo(root, &final)
  34. v.acceptType(root, &final)
  35. v.acceptService(root, &final)
  36. }
  37. return &final
  38. }
  39. func (v *ApiVisitor) acceptService(root *Api, final *Api) {
  40. for _, service := range root.Service {
  41. if _, ok := final.serviceM[service.ServiceApi.Name.Text()]; !ok && len(final.serviceM) > 0 {
  42. v.panic(service.ServiceApi.Name, fmt.Sprintf("mutiple service declaration"))
  43. }
  44. v.duplicateServerItemCheck(service)
  45. for _, route := range service.ServiceApi.ServiceRoute {
  46. uniqueRoute := fmt.Sprintf("%s %s", route.Route.Method.Text(), route.Route.Path.Text())
  47. if _, ok := final.routeM[uniqueRoute]; ok {
  48. v.panic(route.Route.Method, fmt.Sprintf("duplicate route '%s'", uniqueRoute))
  49. }
  50. final.routeM[uniqueRoute] = Holder
  51. var handlerExpr Expr
  52. if route.AtServer != nil {
  53. atServerM := map[string]PlaceHolder{}
  54. for _, kv := range route.AtServer.Kv {
  55. if _, ok := atServerM[kv.Key.Text()]; ok {
  56. v.panic(kv.Key, fmt.Sprintf("duplicate key '%s'", kv.Key.Text()))
  57. }
  58. atServerM[kv.Key.Text()] = Holder
  59. if kv.Key.Text() == "handler" {
  60. handlerExpr = kv.Value
  61. }
  62. }
  63. }
  64. if route.AtHandler != nil {
  65. handlerExpr = route.AtHandler.Name
  66. }
  67. if handlerExpr == nil {
  68. v.panic(route.Route.Method, fmt.Sprintf("mismtached handler"))
  69. }
  70. if handlerExpr.Text() == "" {
  71. v.panic(handlerExpr, fmt.Sprintf("mismtached handler"))
  72. }
  73. if _, ok := final.handlerM[handlerExpr.Text()]; ok {
  74. v.panic(handlerExpr, fmt.Sprintf("duplicate handler '%s'", handlerExpr.Text()))
  75. }
  76. final.handlerM[handlerExpr.Text()] = Holder
  77. }
  78. final.Service = append(final.Service, service)
  79. }
  80. }
  81. func (v *ApiVisitor) duplicateServerItemCheck(service *Service) {
  82. if service.AtServer != nil {
  83. atServerM := map[string]PlaceHolder{}
  84. for _, kv := range service.AtServer.Kv {
  85. if _, ok := atServerM[kv.Key.Text()]; ok {
  86. v.panic(kv.Key, fmt.Sprintf("duplicate key '%s'", kv.Key.Text()))
  87. }
  88. atServerM[kv.Key.Text()] = Holder
  89. }
  90. }
  91. }
  92. func (v *ApiVisitor) acceptType(root *Api, final *Api) {
  93. for _, tp := range root.Type {
  94. if _, ok := final.typeM[tp.NameExpr().Text()]; ok {
  95. v.panic(tp.NameExpr(), fmt.Sprintf("duplicate type '%s'", tp.NameExpr().Text()))
  96. }
  97. final.typeM[tp.NameExpr().Text()] = Holder
  98. final.Type = append(final.Type, tp)
  99. }
  100. }
  101. func (v *ApiVisitor) acceptInfo(root *Api, final *Api) {
  102. if root.Info != nil {
  103. infoM := map[string]PlaceHolder{}
  104. if final.Info != nil {
  105. v.panic(root.Info.Info, fmt.Sprintf("mutiple info declaration"))
  106. }
  107. for _, value := range root.Info.Kvs {
  108. if _, ok := infoM[value.Key.Text()]; ok {
  109. v.panic(value.Key, fmt.Sprintf("duplicate key '%s'", value.Key.Text()))
  110. }
  111. infoM[value.Key.Text()] = Holder
  112. }
  113. final.Info = root.Info
  114. }
  115. }
  116. func (v *ApiVisitor) accetpImport(root *Api, final *Api) {
  117. for _, imp := range root.Import {
  118. if _, ok := final.importM[imp.Value.Text()]; ok {
  119. v.panic(imp.Import, fmt.Sprintf("duplicate import '%s'", imp.Value.Text()))
  120. }
  121. final.importM[imp.Value.Text()] = Holder
  122. final.Import = append(final.Import, imp)
  123. }
  124. }
  125. func (v *ApiVisitor) acceptSyntax(root *Api, final *Api) {
  126. if root.Syntax != nil {
  127. if final.Syntax != nil {
  128. v.panic(root.Syntax.Syntax, fmt.Sprintf("mutiple syntax declaration"))
  129. }
  130. final.Syntax = root.Syntax
  131. }
  132. }
  133. // VisitSpec implements from api.BaseApiParserVisitor
  134. func (v *ApiVisitor) VisitSpec(ctx *api.SpecContext) interface{} {
  135. var root Api
  136. if ctx.SyntaxLit() != nil {
  137. root.Syntax = ctx.SyntaxLit().Accept(v).(*SyntaxExpr)
  138. }
  139. if ctx.ImportSpec() != nil {
  140. root.Import = ctx.ImportSpec().Accept(v).([]*ImportExpr)
  141. }
  142. if ctx.InfoSpec() != nil {
  143. root.Info = ctx.InfoSpec().Accept(v).(*InfoExpr)
  144. }
  145. if ctx.TypeSpec() != nil {
  146. tp := ctx.TypeSpec().Accept(v)
  147. root.Type = tp.([]TypeExpr)
  148. }
  149. if ctx.ServiceSpec() != nil {
  150. root.Service = []*Service{ctx.ServiceSpec().Accept(v).(*Service)}
  151. }
  152. return &root
  153. }
  154. // Format provides a formatter for api command, now nothing to do
  155. func (a *Api) Format() error {
  156. // todo
  157. return nil
  158. }
  159. // Equal compares whether the element literals in two Api are equal
  160. func (a *Api) Equal(v interface{}) bool {
  161. if v == nil {
  162. return false
  163. }
  164. root, ok := v.(*Api)
  165. if !ok {
  166. return false
  167. }
  168. if !a.Syntax.Equal(root.Syntax) {
  169. return false
  170. }
  171. if len(a.Import) != len(root.Import) {
  172. return false
  173. }
  174. var expectingImport, actualImport []*ImportExpr
  175. expectingImport = append(expectingImport, a.Import...)
  176. actualImport = append(actualImport, root.Import...)
  177. sort.Slice(expectingImport, func(i, j int) bool {
  178. return expectingImport[i].Value.Text() < expectingImport[j].Value.Text()
  179. })
  180. sort.Slice(actualImport, func(i, j int) bool {
  181. return actualImport[i].Value.Text() < actualImport[j].Value.Text()
  182. })
  183. for index, each := range expectingImport {
  184. ac := actualImport[index]
  185. if !each.Equal(ac) {
  186. return false
  187. }
  188. }
  189. if !a.Info.Equal(root.Info) {
  190. return false
  191. }
  192. if len(a.Type) != len(root.Type) {
  193. return false
  194. }
  195. var expectingType, actualType []TypeExpr
  196. expectingType = append(expectingType, a.Type...)
  197. actualType = append(actualType, root.Type...)
  198. sort.Slice(expectingType, func(i, j int) bool {
  199. return expectingType[i].NameExpr().Text() < expectingType[j].NameExpr().Text()
  200. })
  201. sort.Slice(actualType, func(i, j int) bool {
  202. return actualType[i].NameExpr().Text() < actualType[j].NameExpr().Text()
  203. })
  204. for index, each := range expectingType {
  205. ac := actualType[index]
  206. if !each.Equal(ac) {
  207. return false
  208. }
  209. }
  210. if len(a.Service) != len(root.Service) {
  211. return false
  212. }
  213. var expectingService, actualService []*Service
  214. expectingService = append(expectingService, a.Service...)
  215. actualService = append(actualService, root.Service...)
  216. for index, each := range expectingService {
  217. ac := actualService[index]
  218. if !each.Equal(ac) {
  219. return false
  220. }
  221. }
  222. return true
  223. }