ast.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. package ast
  2. import (
  3. "fmt"
  4. "sort"
  5. "strings"
  6. "git.i2edu.net/i2/go-zero/tools/goctl/api/parser/g4/gen/api"
  7. "git.i2edu.net/i2/go-zero/tools/goctl/util/console"
  8. "github.com/zeromicro/antlr"
  9. )
  10. type (
  11. // TokenStream defines a token
  12. TokenStream interface {
  13. GetStart() antlr.Token
  14. GetStop() antlr.Token
  15. GetParser() antlr.Parser
  16. }
  17. // ApiVisitor wraps api.BaseApiParserVisitor to call methods which has prefix Visit to
  18. // visit node from the api syntax
  19. ApiVisitor struct {
  20. api.BaseApiParserVisitor
  21. debug bool
  22. log console.Console
  23. prefix string
  24. infoFlag bool
  25. }
  26. // VisitorOption defines a function with argument ApiVisitor
  27. VisitorOption func(v *ApiVisitor)
  28. // Spec describes api spec
  29. Spec interface {
  30. Doc() []Expr
  31. Comment() Expr
  32. Format() error
  33. Equal(v interface{}) bool
  34. }
  35. // Expr describes ast expression
  36. Expr interface {
  37. Prefix() string
  38. Line() int
  39. Column() int
  40. Text() string
  41. SetText(text string)
  42. Start() int
  43. Stop() int
  44. Equal(expr Expr) bool
  45. IsNotNil() bool
  46. }
  47. )
  48. // NewApiVisitor creates an instance for ApiVisitor
  49. func NewApiVisitor(options ...VisitorOption) *ApiVisitor {
  50. v := &ApiVisitor{
  51. log: console.NewColorConsole(),
  52. }
  53. for _, opt := range options {
  54. opt(v)
  55. }
  56. return v
  57. }
  58. func (v *ApiVisitor) panic(expr Expr, msg string) {
  59. errString := fmt.Sprintf("%s line %d:%d %s", v.prefix, expr.Line(), expr.Column(), msg)
  60. if v.debug {
  61. fmt.Println(errString)
  62. }
  63. panic(errString)
  64. }
  65. // WithVisitorPrefix returns a VisitorOption wrap with specified prefix
  66. func WithVisitorPrefix(prefix string) VisitorOption {
  67. return func(v *ApiVisitor) {
  68. v.prefix = prefix
  69. }
  70. }
  71. // WithVisitorDebug returns a debug VisitorOption
  72. func WithVisitorDebug() VisitorOption {
  73. return func(v *ApiVisitor) {
  74. v.debug = true
  75. }
  76. }
  77. type defaultExpr struct {
  78. prefix, v string
  79. line, column int
  80. start, stop int
  81. }
  82. // NewTextExpr creates a default instance for Expr
  83. func NewTextExpr(v string) *defaultExpr {
  84. return &defaultExpr{
  85. v: v,
  86. }
  87. }
  88. func (v *ApiVisitor) newExprWithTerminalNode(node antlr.TerminalNode) *defaultExpr {
  89. if node == nil {
  90. return nil
  91. }
  92. token := node.GetSymbol()
  93. return v.newExprWithToken(token)
  94. }
  95. func (v *ApiVisitor) newExprWithToken(token antlr.Token) *defaultExpr {
  96. if token == nil {
  97. return nil
  98. }
  99. instance := &defaultExpr{}
  100. instance.prefix = v.prefix
  101. instance.v = token.GetText()
  102. instance.line = token.GetLine()
  103. instance.column = token.GetColumn()
  104. instance.start = token.GetStart()
  105. instance.stop = token.GetStop()
  106. return instance
  107. }
  108. func (v *ApiVisitor) newExprWithText(text string, line, column, start, stop int) *defaultExpr {
  109. instance := &defaultExpr{}
  110. instance.prefix = v.prefix
  111. instance.v = text
  112. instance.line = line
  113. instance.column = column
  114. instance.start = start
  115. instance.stop = stop
  116. return instance
  117. }
  118. func (e *defaultExpr) Prefix() string {
  119. if e == nil {
  120. return ""
  121. }
  122. return e.prefix
  123. }
  124. func (e *defaultExpr) Line() int {
  125. if e == nil {
  126. return 0
  127. }
  128. return e.line
  129. }
  130. func (e *defaultExpr) Column() int {
  131. if e == nil {
  132. return 0
  133. }
  134. return e.column
  135. }
  136. func (e *defaultExpr) Text() string {
  137. if e == nil {
  138. return ""
  139. }
  140. return e.v
  141. }
  142. func (e *defaultExpr) SetText(text string) {
  143. if e == nil {
  144. return
  145. }
  146. e.v = text
  147. }
  148. func (e *defaultExpr) Start() int {
  149. if e == nil {
  150. return 0
  151. }
  152. return e.start
  153. }
  154. func (e *defaultExpr) Stop() int {
  155. if e == nil {
  156. return 0
  157. }
  158. return e.stop
  159. }
  160. func (e *defaultExpr) Equal(expr Expr) bool {
  161. if e == nil {
  162. if expr != nil {
  163. return false
  164. }
  165. return true
  166. }
  167. if expr == nil {
  168. return false
  169. }
  170. return e.v == expr.Text()
  171. }
  172. func (e *defaultExpr) IsNotNil() bool {
  173. return e != nil
  174. }
  175. // EqualDoc compares whether the element literals in two Spec are equal
  176. func EqualDoc(spec1, spec2 Spec) bool {
  177. if spec1 == nil {
  178. return spec2 == nil
  179. }
  180. if spec2 == nil {
  181. return false
  182. }
  183. var expectDoc, actualDoc []Expr
  184. expectDoc = append(expectDoc, spec2.Doc()...)
  185. actualDoc = append(actualDoc, spec1.Doc()...)
  186. sort.Slice(expectDoc, func(i, j int) bool {
  187. return expectDoc[i].Line() < expectDoc[j].Line()
  188. })
  189. for index, each := range actualDoc {
  190. if !each.Equal(actualDoc[index]) {
  191. return false
  192. }
  193. }
  194. if spec1.Comment() != nil {
  195. if spec2.Comment() == nil {
  196. return false
  197. }
  198. if !spec1.Comment().Equal(spec2.Comment()) {
  199. return false
  200. }
  201. } else {
  202. if spec2.Comment() != nil {
  203. return false
  204. }
  205. }
  206. return true
  207. }
  208. func (v *ApiVisitor) getDoc(t TokenStream) []Expr {
  209. list := v.getHiddenTokensToLeft(t, api.COMEMNTS, false)
  210. return list
  211. }
  212. func (v *ApiVisitor) getComment(t TokenStream) Expr {
  213. list := v.getHiddenTokensToRight(t, api.COMEMNTS)
  214. if len(list) == 0 {
  215. return nil
  216. }
  217. commentExpr := list[0]
  218. stop := t.GetStop()
  219. text := stop.GetText()
  220. nlCount := strings.Count(text, "\n")
  221. if commentExpr.Line() != stop.GetLine()+nlCount {
  222. return nil
  223. }
  224. return commentExpr
  225. }
  226. func (v *ApiVisitor) getHiddenTokensToLeft(t TokenStream, channel int, containsCommentOfDefaultChannel bool) []Expr {
  227. ct := t.GetParser().GetTokenStream().(*antlr.CommonTokenStream)
  228. tokens := ct.GetHiddenTokensToLeft(t.GetStart().GetTokenIndex(), channel)
  229. var tmp []antlr.Token
  230. for _, each := range tokens {
  231. tmp = append(tmp, each)
  232. }
  233. var list []Expr
  234. for _, each := range tmp {
  235. if !containsCommentOfDefaultChannel {
  236. index := each.GetTokenIndex() - 1
  237. if index > 0 {
  238. allTokens := ct.GetAllTokens()
  239. flag := false
  240. for i := index; i >= 0; i-- {
  241. tk := allTokens[i]
  242. if tk.GetChannel() == antlr.LexerDefaultTokenChannel {
  243. if tk.GetLine() == each.GetLine() {
  244. flag = true
  245. break
  246. }
  247. }
  248. }
  249. if flag {
  250. continue
  251. }
  252. }
  253. }
  254. list = append(list, v.newExprWithToken(each))
  255. }
  256. return list
  257. }
  258. func (v *ApiVisitor) getHiddenTokensToRight(t TokenStream, channel int) []Expr {
  259. ct := t.GetParser().GetTokenStream().(*antlr.CommonTokenStream)
  260. tokens := ct.GetHiddenTokensToRight(t.GetStop().GetTokenIndex(), channel)
  261. var list []Expr
  262. for _, each := range tokens {
  263. list = append(list, v.newExprWithToken(each))
  264. }
  265. return list
  266. }