ast_router_sub_enter.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. package ams_ast
  2. import (
  3. "bytes"
  4. "fmt"
  5. "github.com/pkg/errors"
  6. "go/ast"
  7. "go/parser"
  8. "go/printer"
  9. "go/token"
  10. "os"
  11. "path/filepath"
  12. "text/template"
  13. )
  14. // 模版自路由入口文件路径
  15. func TemplateSubRouterEnterFile() string {
  16. return filepath.Join(template_root, "router/module/enter.go.tpl")
  17. }
  18. // 模版自路由文件路径
  19. func TemplateSubRouterRegisterFile() string {
  20. return filepath.Join(template_root, "router/module/model.go.tpl")
  21. }
  22. // 通过模块名获取子路由入口文件
  23. func ServerSubRouterEnterFile(module string) string {
  24. return filepath.Join(serverRootRouterPath, module, server_enter)
  25. }
  26. // 通过模块+模型名获取 子路由注册文件
  27. func ServerSubRouterRegisterFile(module, model string) string {
  28. return filepath.Join(serverRootRouterPath, module, snakeString(model)+".go")
  29. }
  30. // 子路由注册器
  31. type SubRouterRegister struct {
  32. TemplateEnterFile string // `json:"templateEnterFile"` // 子路由入口文件
  33. TemplateModelFile string // `json:"templateModelFile"` // 子路由模型文件
  34. TargetModuleEnterFile string // `json:"targetModuleFile"` // 模块路由文件
  35. TargetModelFile string // `json:"targetModelFile"` // 模型路由文件
  36. Server string // server mod 名 go_server
  37. Module string // `json:"module" example:"保持与alias一致"`
  38. ModuleUpper string // `json:"moduleUpper" example:"模块名大写首字母"`
  39. Model string // `json:"model" example:"模型名"` xx_yy
  40. ModelUpper string // `json:"modelUpper" example:"模型名大写首字母"`
  41. RouterServiceName string // xxYyXxYyService
  42. ValKey string `json:"valKey"` // 默认值 priRouters
  43. BaseAst
  44. }
  45. func BuildSubRouterRegister(alias, model string) *SubRouterRegister {
  46. // aaBbAabb
  47. routerServiceName := fmt.Sprintf("%s%s", CapitalizeOrLower(toCamelCase(alias), false), CapitalizeOrLower(toCamelCase(model)))
  48. return &SubRouterRegister{
  49. TemplateEnterFile: TemplateSubRouterEnterFile(), // 入口模版文件
  50. TemplateModelFile: TemplateSubRouterRegisterFile(), // 模型模版文件
  51. TargetModuleEnterFile: ServerSubRouterEnterFile(alias), // 目标模板文件
  52. TargetModelFile: ServerSubRouterRegisterFile(alias, model), // 目标模型文件
  53. Server: server_mod, // app服务模块
  54. Module: alias, // 保持别名不变 // xx_yy
  55. ModuleUpper: CapitalizeOrLower(toCamelCase(alias)), // 改为首字母大写 驼峰结构 AaBb // XxYy
  56. Model: snakeString(model), // xx_yy
  57. ModelUpper: CapitalizeOrLower(toCamelCase(model)), // XxYy
  58. RouterServiceName: routerServiceName, // 路由服务名称 aaBbAabb
  59. ValKey: "allRouters",
  60. BaseAst: BaseAst{},
  61. }
  62. }
  63. func (s *SubRouterRegister) Inspect() error {
  64. var err error
  65. // 模版文件检查
  66. if !FileExists(s.TemplateEnterFile) {
  67. return errors.New("sub router enter template file is not exists")
  68. }
  69. if !FileExists(s.TemplateModelFile) {
  70. return errors.New("sub router model template file is not exists")
  71. }
  72. // 入口文件 -- 如果不存在则创建
  73. if !FileExists(s.TargetModuleEnterFile) {
  74. err = s.createEnterRouter()
  75. if err != nil {
  76. return err
  77. }
  78. }
  79. // 模型路由文件(仅支持创建与删除 不支持回滚)
  80. if !FileExists(s.TargetModelFile) {
  81. err = s.createModel()
  82. if err != nil {
  83. return err
  84. }
  85. }
  86. // 注入路由代码
  87. err = s.inspectRouter()
  88. if err != nil {
  89. return err
  90. }
  91. return nil
  92. }
  93. func (s *SubRouterRegister) Rollback() error {
  94. // 删除模型文件
  95. // 模型路由文件(仅支持创建与删除 不支持回滚)
  96. if FileExists(s.TargetModelFile) {
  97. err := os.Remove(s.TargetModelFile)
  98. if err != nil {
  99. return err
  100. }
  101. }
  102. // 子路由回滚
  103. err := s.rollbackRouter()
  104. if err != nil {
  105. return err
  106. }
  107. return nil
  108. }
  109. // 创建子路由入口文件
  110. func (s *SubRouterRegister) createEnterRouter() error {
  111. var files *template.Template
  112. files, err := template.ParseFiles(s.TemplateEnterFile)
  113. if err != nil {
  114. return err
  115. }
  116. err = os.MkdirAll(filepath.Dir(s.TargetModuleEnterFile), os.ModePerm)
  117. if err != nil {
  118. return err
  119. }
  120. var file *os.File
  121. file, err = os.Create(s.TargetModuleEnterFile)
  122. if err != nil {
  123. return err
  124. }
  125. err = files.Execute(file, s)
  126. _ = file.Close()
  127. if err != nil {
  128. return err
  129. }
  130. return nil
  131. }
  132. // 创建模型文件
  133. func (s *SubRouterRegister) createModel() error {
  134. var files *template.Template
  135. files, err := template.ParseFiles(s.TemplateModelFile)
  136. if err != nil {
  137. return err
  138. }
  139. //core.Log.Infof("子路由模板文件:%s", s.TemplateModelFile)
  140. err = os.MkdirAll(filepath.Dir(s.TargetModelFile), os.ModePerm)
  141. if err != nil {
  142. return err
  143. }
  144. //core.Log.Infof("子路由生成目标文件:%s", s.TargetModelFile)
  145. var file *os.File
  146. file, err = os.Create(s.TargetModelFile)
  147. if err != nil {
  148. return err
  149. }
  150. err = files.Execute(file, s)
  151. _ = file.Close()
  152. if err != nil {
  153. return err
  154. }
  155. return nil
  156. }
  157. // todo:子路由注入
  158. func (s *SubRouterRegister) inspectRouter() error {
  159. //core.Log.Infof("开始注入子路由")
  160. //core.Log.Infof("子路由Model文件:%s", s.TargetModelFile)
  161. //core.Log.Infof("子路由入口文件:%s", s.TargetModuleEnterFile)
  162. // 创建 FileSet 用于跟踪文件位置信息
  163. fSet := token.NewFileSet()
  164. // 解析源代码为 AST
  165. node, err := parser.ParseFile(fSet, s.TargetModuleEnterFile, nil, parser.ParseComments)
  166. if err != nil {
  167. return err
  168. }
  169. // 检查是否已注入
  170. inspectIsExists := s.IsContainsSubRouter(node, "allRouters", fmt.Sprintf("%sRouter", s.ModelUpper))
  171. if inspectIsExists {
  172. //core.Log.Infof("子路由%s已注入:allRouters", s.ModelUpper)
  173. return nil
  174. }
  175. s.inspectRouterToVars(node, "allRouters", fmt.Sprintf("%sRouter", s.ModelUpper))
  176. var out []byte
  177. bf := bytes.NewBuffer(out)
  178. err = printer.Fprint(bf, fSet, node)
  179. if err != nil {
  180. return err
  181. }
  182. err = os.WriteFile(s.TargetModuleEnterFile, bf.Bytes(), 0666)
  183. if err != nil {
  184. return err
  185. }
  186. //core.Log.Infof("成功添加 %s{} 到 allRouters", s.ModelUpper)
  187. return nil
  188. }
  189. // todo: 子路由回滚
  190. func (s *SubRouterRegister) rollbackRouter() error {
  191. // 创建 FileSet 用于跟踪文件位置信息
  192. fSet := token.NewFileSet()
  193. // 解析源代码为 AST
  194. node, err := parser.ParseFile(fSet, s.TargetModuleEnterFile, nil, parser.ParseComments)
  195. if err != nil {
  196. return err
  197. }
  198. // 检查是否已注入
  199. inspectIsExists := s.IsContainsSubRouter(node, "allRouters", fmt.Sprintf("%sRouter", s.ModelUpper))
  200. if !inspectIsExists {
  201. //core.Log.Infof("子路由%s已回滚:allRouters", s.ModelUpper)
  202. return nil
  203. }
  204. s.rollbackRouterFromVars(node, "allRouters", fmt.Sprintf("%sRouter", s.ModelUpper))
  205. var out []byte
  206. bf := bytes.NewBuffer(out)
  207. err = printer.Fprint(bf, fSet, node)
  208. if err != nil {
  209. return err
  210. }
  211. err = os.WriteFile(s.TargetModuleEnterFile, bf.Bytes(), 0666)
  212. if err != nil {
  213. return err
  214. }
  215. //core.Log.Infof("成功添从 allRouters 移除 %s{} ", fmt.Sprintf("%sRouter", s.ModelUpper))
  216. return nil
  217. }
  218. // 检查元素列表中是否已注入指定结果体
  219. // 检查变了列表 allRouters 中是否存在 XxYyRouterGroup{}
  220. // routerVal:allRouters
  221. func (s *SubRouterRegister) IsContainsSubRouter(node ast.Node, routerVal, subRouterName string) bool {
  222. // 2. 检查 UserRouter{} 是否存在
  223. routerExists := false
  224. ast.Inspect(node, func(n ast.Node) bool {
  225. // 查找 allRouters 变量声明
  226. if valueSpec, ok := n.(*ast.ValueSpec); ok && len(valueSpec.Names) > 0 && valueSpec.Names[0].Name == routerVal {
  227. if compLit, ok := valueSpec.Values[0].(*ast.CompositeLit); ok {
  228. for _, elt := range compLit.Elts {
  229. switch expr := elt.(type) {
  230. case *ast.CompositeLit:
  231. // 处理 AssetRouter{} 情况
  232. if selExpr, ok := expr.Type.(*ast.SelectorExpr); ok {
  233. if ident, ok := selExpr.X.(*ast.Ident); ok && ident.Name == subRouterName {
  234. routerExists = true
  235. return false
  236. }
  237. } else if ident, ok := expr.Type.(*ast.Ident); ok && ident.Name == subRouterName {
  238. routerExists = true
  239. return false
  240. }
  241. case *ast.SelectorExpr:
  242. // 处理 AssetRouter 情况 (没有花括号)
  243. if ident, ok := expr.X.(*ast.Ident); ok && ident.Name == subRouterName {
  244. routerExists = true
  245. return false
  246. }
  247. case *ast.Ident:
  248. // 处理 AssetRouter 情况 (单独标识符)
  249. if expr.Name == subRouterName {
  250. routerExists = true
  251. return false
  252. }
  253. }
  254. }
  255. }
  256. }
  257. return true
  258. })
  259. return routerExists
  260. }
  261. // 注入元素到列表
  262. func (s *SubRouterRegister) inspectRouterToVars(node ast.Node, routerVal, subRouterName string) {
  263. ast.Inspect(node, func(n ast.Node) bool {
  264. if valueSpec, ok := n.(*ast.ValueSpec); ok && len(valueSpec.Names) > 0 && valueSpec.Names[0].Name == routerVal {
  265. if compLit, ok := valueSpec.Values[0].(*ast.CompositeLit); ok {
  266. // 创建新的 AssetRouter{} 元素
  267. newElement := &ast.CompositeLit{
  268. Type: &ast.Ident{Name: subRouterName},
  269. }
  270. // 添加到切片中
  271. compLit.Elts = append(compLit.Elts, newElement)
  272. return false
  273. }
  274. }
  275. return true
  276. })
  277. }
  278. // 从列表移除元素
  279. func (s *SubRouterRegister) rollbackRouterFromVars(node ast.Node, routerVal, subRouterName string) {
  280. ast.Inspect(node, func(n ast.Node) bool {
  281. if valueSpec, ok := n.(*ast.ValueSpec); ok && len(valueSpec.Names) > 0 && valueSpec.Names[0].Name == routerVal {
  282. if compLit, ok := valueSpec.Values[0].(*ast.CompositeLit); ok {
  283. // Filter out elements with the specified subRouterName
  284. filteredEls := make([]ast.Expr, 0, len(compLit.Elts))
  285. for _, elt := range compLit.Elts {
  286. if cl, ok := elt.(*ast.CompositeLit); ok {
  287. if ident, ok := cl.Type.(*ast.Ident); ok {
  288. //core.Log.Infof("ident.name:%s", ident.Name)
  289. //core.Log.Infof("subRouterName:%s", subRouterName)
  290. if ident.Name == subRouterName {
  291. continue
  292. }
  293. // Skip this element (remove it)
  294. }
  295. }
  296. filteredEls = append(filteredEls, elt)
  297. }
  298. // Update the elements if any were removed
  299. if len(filteredEls) < len(compLit.Elts) {
  300. compLit.Elts = filteredEls
  301. }
  302. return false
  303. }
  304. }
  305. return true
  306. })
  307. }