analyzer.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. package parser
  2. import (
  3. "fmt"
  4. "sort"
  5. "strings"
  6. "github.com/zeromicro/go-zero/core/lang"
  7. "github.com/zeromicro/go-zero/tools/goctl/api/spec"
  8. "github.com/zeromicro/go-zero/tools/goctl/pkg/parser/api/ast"
  9. "github.com/zeromicro/go-zero/tools/goctl/pkg/parser/api/importstack"
  10. "github.com/zeromicro/go-zero/tools/goctl/pkg/parser/api/placeholder"
  11. "github.com/zeromicro/go-zero/tools/goctl/pkg/parser/api/token"
  12. )
  13. // Analyzer analyzes the ast and converts it to spec.
  14. type Analyzer struct {
  15. api *API
  16. spec *spec.ApiSpec
  17. }
  18. func (a *Analyzer) astTypeToSpec(in ast.DataType) (spec.Type, error) {
  19. isLiteralType := func(dt ast.DataType) bool {
  20. if _, ok := dt.(*ast.BaseDataType); ok {
  21. return true
  22. }
  23. _, ok := dt.(*ast.AnyDataType)
  24. return ok
  25. }
  26. switch v := (in).(type) {
  27. case *ast.BaseDataType:
  28. raw := v.RawText()
  29. if IsBaseType(raw) {
  30. return spec.PrimitiveType{
  31. RawName: raw,
  32. }, nil
  33. }
  34. return spec.DefineStruct{RawName: raw}, nil
  35. case *ast.AnyDataType:
  36. return nil, ast.SyntaxError(v.Pos(), "unsupported any type")
  37. case *ast.StructDataType:
  38. // TODO(keson) feature: can be extended
  39. case *ast.InterfaceDataType:
  40. return spec.InterfaceType{RawName: v.RawText()}, nil
  41. case *ast.MapDataType:
  42. if !isLiteralType(v.Key) {
  43. return nil, ast.SyntaxError(v.Pos(), "expected literal type, got <%T>", v)
  44. }
  45. if !v.Key.CanEqual() {
  46. return nil, ast.SyntaxError(v.Pos(), "map key <%T> must be equal data type", v)
  47. }
  48. value, err := a.astTypeToSpec(v.Value)
  49. if err != nil {
  50. return nil, err
  51. }
  52. return spec.MapType{
  53. RawName: v.RawText(),
  54. Key: v.RawText(),
  55. Value: value,
  56. }, nil
  57. case *ast.PointerDataType:
  58. raw := v.DataType.RawText()
  59. if IsBaseType(raw) {
  60. return spec.PointerType{RawName: v.RawText(), Type: spec.PrimitiveType{RawName: raw}}, nil
  61. }
  62. value, err := a.astTypeToSpec(v.DataType)
  63. if err != nil {
  64. return nil, err
  65. }
  66. return spec.PointerType{
  67. RawName: v.RawText(),
  68. Type: value,
  69. }, nil
  70. case *ast.ArrayDataType:
  71. if v.Length.Token.Type == token.ELLIPSIS {
  72. return nil, ast.SyntaxError(v.Pos(), "Array: unsupported dynamic length")
  73. }
  74. value, err := a.astTypeToSpec(v.DataType)
  75. if err != nil {
  76. return nil, err
  77. }
  78. return spec.ArrayType{
  79. RawName: v.RawText(),
  80. Value: value,
  81. }, nil
  82. case *ast.SliceDataType:
  83. value, err := a.astTypeToSpec(v.DataType)
  84. if err != nil {
  85. return nil, err
  86. }
  87. return spec.ArrayType{
  88. RawName: v.RawText(),
  89. Value: value,
  90. }, nil
  91. }
  92. return nil, ast.SyntaxError(in.Pos(), "unsupported type <%T>", in)
  93. }
  94. func (a *Analyzer) convert2Spec() error {
  95. if err := a.fillTypes(); err != nil {
  96. return err
  97. }
  98. if err := a.fillService(); err != nil {
  99. return err
  100. }
  101. sort.SliceStable(a.spec.Types, func(i, j int) bool {
  102. return a.spec.Types[i].Name() < a.spec.Types[j].Name()
  103. })
  104. groups := make([]spec.Group, 0, len(a.spec.Service.Groups))
  105. for _, v := range a.spec.Service.Groups {
  106. sort.SliceStable(v.Routes, func(i, j int) bool {
  107. return v.Routes[i].Path < v.Routes[j].Path
  108. })
  109. groups = append(groups, v)
  110. }
  111. sort.SliceStable(groups, func(i, j int) bool {
  112. return groups[i].Annotation.Properties["group"] < groups[j].Annotation.Properties["group"]
  113. })
  114. a.spec.Service.Groups = groups
  115. return nil
  116. }
  117. func (a *Analyzer) convertAtDoc(atDoc ast.AtDocStmt) spec.AtDoc {
  118. var ret spec.AtDoc
  119. switch val := atDoc.(type) {
  120. case *ast.AtDocLiteralStmt:
  121. ret.Text = val.Value.Token.Text
  122. case *ast.AtDocGroupStmt:
  123. ret.Properties = a.convertKV(val.Values)
  124. }
  125. return ret
  126. }
  127. func (a *Analyzer) convertKV(kv []*ast.KVExpr) map[string]string {
  128. var ret = map[string]string{}
  129. for _, v := range kv {
  130. key := strings.TrimSuffix(v.Key.Token.Text, ":")
  131. ret[key] = v.Value.Token.Text
  132. }
  133. return ret
  134. }
  135. func (a *Analyzer) fieldToMember(field *ast.ElemExpr) (spec.Member, error) {
  136. var name []string
  137. for _, v := range field.Name {
  138. name = append(name, v.Token.Text)
  139. }
  140. tp, err := a.astTypeToSpec(field.DataType)
  141. if err != nil {
  142. return spec.Member{}, err
  143. }
  144. head, leading := field.CommentGroup()
  145. m := spec.Member{
  146. Name: strings.Join(name, ", "),
  147. Type: tp,
  148. Docs: head.List(),
  149. Comment: leading.String(),
  150. IsInline: field.IsAnonymous(),
  151. }
  152. if field.Tag != nil {
  153. m.Tag = field.Tag.Token.Text
  154. }
  155. return m, nil
  156. }
  157. func (a *Analyzer) fillRouteType(route *spec.Route) error {
  158. if route.RequestType != nil {
  159. switch route.RequestType.(type) {
  160. case spec.DefineStruct:
  161. tp, err := a.findDefinedType(route.RequestType.Name())
  162. if err != nil {
  163. return err
  164. }
  165. route.RequestType = tp
  166. }
  167. }
  168. if route.ResponseType != nil {
  169. switch route.ResponseType.(type) {
  170. case spec.DefineStruct:
  171. tp, err := a.findDefinedType(route.ResponseType.Name())
  172. if err != nil {
  173. return err
  174. }
  175. route.ResponseType = tp
  176. }
  177. }
  178. return nil
  179. }
  180. func (a *Analyzer) fillService() error {
  181. var groups []spec.Group
  182. for _, item := range a.api.ServiceStmts {
  183. var group spec.Group
  184. if item.AtServerStmt != nil {
  185. group.Annotation.Properties = a.convertKV(item.AtServerStmt.Values)
  186. }
  187. for _, astRoute := range item.Routes {
  188. head, leading := astRoute.CommentGroup()
  189. route := spec.Route{
  190. Method: astRoute.Route.Method.Token.Text,
  191. Path: astRoute.Route.Path.Format(""),
  192. Doc: head.List(),
  193. Comment: leading.List(),
  194. }
  195. if astRoute.AtDoc != nil {
  196. route.AtDoc = a.convertAtDoc(astRoute.AtDoc)
  197. }
  198. if astRoute.AtHandler != nil {
  199. route.AtDoc = a.convertAtDoc(astRoute.AtDoc)
  200. route.Handler = astRoute.AtHandler.Name.Token.Text
  201. head, leading := astRoute.AtHandler.CommentGroup()
  202. route.HandlerDoc = head.List()
  203. route.HandlerComment = leading.List()
  204. }
  205. if astRoute.Route.Request != nil && astRoute.Route.Request.Body != nil {
  206. requestType, err := a.getType(astRoute.Route.Request)
  207. if err != nil {
  208. return err
  209. }
  210. route.RequestType = requestType
  211. }
  212. if astRoute.Route.Response != nil && astRoute.Route.Response.Body != nil {
  213. responseType, err := a.getType(astRoute.Route.Response)
  214. if err != nil {
  215. return err
  216. }
  217. route.ResponseType = responseType
  218. }
  219. if err := a.fillRouteType(&route); err != nil {
  220. return err
  221. }
  222. group.Routes = append(group.Routes, route)
  223. name := item.Name.Format("")
  224. if len(a.spec.Service.Name) > 0 && a.spec.Service.Name != name {
  225. return ast.SyntaxError(item.Name.Pos(), "multiple service names defined <%s> and <%s>", name, a.spec.Service.Name)
  226. }
  227. a.spec.Service.Name = name
  228. }
  229. groups = append(groups, group)
  230. }
  231. a.spec.Service.Groups = groups
  232. return nil
  233. }
  234. func (a *Analyzer) fillTypes() error {
  235. for _, item := range a.api.TypeStmt {
  236. switch v := (item).(type) {
  237. case *ast.TypeLiteralStmt:
  238. if err := a.fillTypeExpr(v.Expr); err != nil {
  239. return err
  240. }
  241. case *ast.TypeGroupStmt:
  242. for _, expr := range v.ExprList {
  243. err := a.fillTypeExpr(expr)
  244. if err != nil {
  245. return err
  246. }
  247. }
  248. }
  249. }
  250. var types []spec.Type
  251. for _, item := range a.spec.Types {
  252. switch v := (item).(type) {
  253. case spec.DefineStruct:
  254. var members []spec.Member
  255. for _, member := range v.Members {
  256. switch v := member.Type.(type) {
  257. case spec.DefineStruct:
  258. tp, err := a.findDefinedType(v.RawName)
  259. if err != nil {
  260. return err
  261. }
  262. member.Type = tp
  263. }
  264. members = append(members, member)
  265. }
  266. v.Members = members
  267. types = append(types, v)
  268. default:
  269. return fmt.Errorf("unknown type %+v", v)
  270. }
  271. }
  272. a.spec.Types = types
  273. return nil
  274. }
  275. func (a *Analyzer) fillTypeExpr(expr *ast.TypeExpr) error {
  276. head, _ := expr.CommentGroup()
  277. switch val := expr.DataType.(type) {
  278. case *ast.StructDataType:
  279. var members []spec.Member
  280. for _, item := range val.Elements {
  281. m, err := a.fieldToMember(item)
  282. if err != nil {
  283. return err
  284. }
  285. members = append(members, m)
  286. }
  287. a.spec.Types = append(a.spec.Types, spec.DefineStruct{
  288. RawName: expr.Name.Token.Text,
  289. Members: members,
  290. Docs: head.List(),
  291. })
  292. return nil
  293. default:
  294. return ast.SyntaxError(expr.Pos(), "expected <struct> expr, got <%T>", expr.DataType)
  295. }
  296. }
  297. func (a *Analyzer) findDefinedType(name string) (spec.Type, error) {
  298. for _, item := range a.spec.Types {
  299. if _, ok := item.(spec.DefineStruct); ok {
  300. if item.Name() == name {
  301. return item, nil
  302. }
  303. }
  304. }
  305. return nil, fmt.Errorf("type %s not defined", name)
  306. }
  307. func (a *Analyzer) getType(expr *ast.BodyStmt) (spec.Type, error) {
  308. body := expr.Body
  309. var tp spec.Type
  310. var err error
  311. var rawText = body.Format("")
  312. if IsBaseType(body.Value.Token.Text) {
  313. tp = spec.PrimitiveType{RawName: body.Value.Token.Text}
  314. } else {
  315. tp, err = a.findDefinedType(body.Value.Token.Text)
  316. if err != nil {
  317. return nil, err
  318. }
  319. }
  320. if body.LBrack != nil {
  321. if body.Star != nil {
  322. return spec.PointerType{
  323. RawName: rawText,
  324. Type: tp,
  325. }, nil
  326. }
  327. return spec.ArrayType{
  328. RawName: rawText,
  329. Value: tp,
  330. }, nil
  331. }
  332. if body.Star != nil {
  333. return spec.PointerType{
  334. RawName: rawText,
  335. Type: tp,
  336. }, nil
  337. }
  338. return tp, nil
  339. }
  340. // Parse parses the given file and returns the parsed spec.
  341. func Parse(filename string, src interface{}) (*spec.ApiSpec, error) {
  342. p := New(filename, src)
  343. ast := p.Parse()
  344. if err := p.CheckErrors(); err != nil {
  345. return nil, err
  346. }
  347. is := importstack.New()
  348. err := is.Push(ast.Filename)
  349. if err != nil {
  350. return nil, err
  351. }
  352. importSet := map[string]lang.PlaceholderType{}
  353. api, err := convert2API(ast, importSet, is)
  354. if err != nil {
  355. return nil, err
  356. }
  357. var result = new(spec.ApiSpec)
  358. analyzer := Analyzer{
  359. api: api,
  360. spec: result,
  361. }
  362. err = analyzer.convert2Spec()
  363. if err != nil {
  364. return nil, err
  365. }
  366. return result, nil
  367. }
  368. var kind = map[string]placeholder.Type{
  369. "bool": placeholder.PlaceHolder,
  370. "int": placeholder.PlaceHolder,
  371. "int8": placeholder.PlaceHolder,
  372. "int16": placeholder.PlaceHolder,
  373. "int32": placeholder.PlaceHolder,
  374. "int64": placeholder.PlaceHolder,
  375. "uint": placeholder.PlaceHolder,
  376. "uint8": placeholder.PlaceHolder,
  377. "uint16": placeholder.PlaceHolder,
  378. "uint32": placeholder.PlaceHolder,
  379. "uint64": placeholder.PlaceHolder,
  380. "uintptr": placeholder.PlaceHolder,
  381. "float32": placeholder.PlaceHolder,
  382. "float64": placeholder.PlaceHolder,
  383. "complex64": placeholder.PlaceHolder,
  384. "complex128": placeholder.PlaceHolder,
  385. "string": placeholder.PlaceHolder,
  386. "byte": placeholder.PlaceHolder,
  387. "rune": placeholder.PlaceHolder,
  388. "any": placeholder.PlaceHolder,
  389. }
  390. // IsBaseType returns true if the given type is a base type.
  391. func IsBaseType(text string) bool {
  392. _, ok := kind[text]
  393. return ok
  394. }