api.go 7.0 KB

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