ast_gorm.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package ast
  2. import (
  3. "bytes"
  4. "fmt"
  5. "go/ast"
  6. "go/parser"
  7. "go/printer"
  8. "go/token"
  9. "os"
  10. )
  11. // 自动为 gorm.go 注册一个自动迁移
  12. func AddRegisterTablesAst(path, funcName, pk, varName, dbName, model string) {
  13. modelPk := fmt.Sprintf("server/model/%s", pk)
  14. src, err := os.ReadFile(path)
  15. if err != nil {
  16. fmt.Println(err)
  17. }
  18. fileSet := token.NewFileSet()
  19. astFile, err := parser.ParseFile(fileSet, "", src, 0)
  20. if err != nil {
  21. fmt.Println(err)
  22. }
  23. AddImport(astFile, modelPk)
  24. FuncNode := FindFunction(astFile, funcName)
  25. if FuncNode != nil {
  26. ast.Print(fileSet, FuncNode)
  27. }
  28. addDBVar(FuncNode.Body, varName, dbName)
  29. addAutoMigrate(FuncNode.Body, varName, pk, model)
  30. var out []byte
  31. bf := bytes.NewBuffer(out)
  32. printer.Fprint(bf, fileSet, astFile)
  33. os.WriteFile(path, bf.Bytes(), 0666)
  34. }
  35. // 增加一个 db库变量
  36. func addDBVar(astBody *ast.BlockStmt, varName, dbName string) {
  37. if dbName == "" {
  38. return
  39. }
  40. dbStr := fmt.Sprintf("\"%s\"", dbName)
  41. for i := range astBody.List {
  42. if assignStmt, ok := astBody.List[i].(*ast.AssignStmt); ok {
  43. if ident, ok := assignStmt.Lhs[0].(*ast.Ident); ok {
  44. if ident.Name == varName {
  45. return
  46. }
  47. }
  48. }
  49. }
  50. assignNode := &ast.AssignStmt{
  51. Lhs: []ast.Expr{
  52. &ast.Ident{
  53. Name: varName,
  54. },
  55. },
  56. Tok: token.DEFINE,
  57. Rhs: []ast.Expr{
  58. &ast.CallExpr{
  59. Fun: &ast.SelectorExpr{
  60. X: &ast.Ident{
  61. Name: "global",
  62. },
  63. Sel: &ast.Ident{
  64. Name: "GetGlobalDBByDBName",
  65. },
  66. },
  67. Args: []ast.Expr{
  68. &ast.BasicLit{
  69. Kind: token.STRING,
  70. Value: dbStr,
  71. },
  72. },
  73. },
  74. },
  75. }
  76. astBody.List = append([]ast.Stmt{assignNode}, astBody.List...)
  77. }
  78. // 为db库变量增加 AutoMigrate 方法
  79. func addAutoMigrate(astBody *ast.BlockStmt, dbname string, pk string, model string) {
  80. if dbname == "" {
  81. dbname = "db"
  82. }
  83. flag := true
  84. ast.Inspect(astBody, func(node ast.Node) bool {
  85. // 首先判断需要加入的方法调用语句是否存在 不存在则直接走到下方逻辑
  86. switch n := node.(type) {
  87. case *ast.CallExpr:
  88. // 判断是否找到了AutoMigrate语句
  89. if s, ok := n.Fun.(*ast.SelectorExpr); ok {
  90. if x, ok := s.X.(*ast.Ident); ok {
  91. if s.Sel.Name == "AutoMigrate" && x.Name == dbname {
  92. flag = false
  93. if !NeedAppendModel(n, pk, model) {
  94. return false
  95. }
  96. // 判断已经找到了AutoMigrate语句
  97. n.Args = append(n.Args, &ast.CompositeLit{
  98. Type: &ast.SelectorExpr{
  99. X: &ast.Ident{
  100. Name: pk,
  101. },
  102. Sel: &ast.Ident{
  103. Name: model,
  104. },
  105. },
  106. })
  107. return false
  108. }
  109. }
  110. }
  111. }
  112. return true
  113. //然后判断 pk.model是否存在 如果存在直接跳出 如果不存在 则向已经找到的方法调用语句的node里面push一条
  114. })
  115. if flag {
  116. exprStmt := &ast.ExprStmt{
  117. X: &ast.CallExpr{
  118. Fun: &ast.SelectorExpr{
  119. X: &ast.Ident{
  120. Name: dbname,
  121. },
  122. Sel: &ast.Ident{
  123. Name: "AutoMigrate",
  124. },
  125. },
  126. Args: []ast.Expr{
  127. &ast.CompositeLit{
  128. Type: &ast.SelectorExpr{
  129. X: &ast.Ident{
  130. Name: pk,
  131. },
  132. Sel: &ast.Ident{
  133. Name: model,
  134. },
  135. },
  136. },
  137. },
  138. }}
  139. astBody.List = append(astBody.List, exprStmt)
  140. }
  141. }
  142. // 为automigrate增加实参
  143. func NeedAppendModel(callNode ast.Node, pk string, model string) bool {
  144. flag := true
  145. ast.Inspect(callNode, func(node ast.Node) bool {
  146. switch n := node.(type) {
  147. case *ast.SelectorExpr:
  148. if x, ok := n.X.(*ast.Ident); ok {
  149. if n.Sel.Name == model && x.Name == pk {
  150. flag = false
  151. return false
  152. }
  153. }
  154. }
  155. return true
  156. })
  157. return flag
  158. }