| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- package ams_ast
- import (
- "bytes"
- "fmt"
- "github.com/pkg/errors"
- "go/ast"
- "go/parser"
- "go/printer"
- "go/token"
- "os"
- "path/filepath"
- "text/template"
- )
- // 模版自路由入口文件路径
- func TemplateSubRouterEnterFile() string {
- return filepath.Join(template_root, "router/module/enter.go.tpl")
- }
- // 模版自路由文件路径
- func TemplateSubRouterRegisterFile() string {
- return filepath.Join(template_root, "router/module/model.go.tpl")
- }
- // 通过模块名获取子路由入口文件
- func ServerSubRouterEnterFile(module string) string {
- return filepath.Join(serverRootRouterPath, module, server_enter)
- }
- // 通过模块+模型名获取 子路由注册文件
- func ServerSubRouterRegisterFile(module, model string) string {
- return filepath.Join(serverRootRouterPath, module, snakeString(model)+".go")
- }
- // 子路由注册器
- type SubRouterRegister struct {
- TemplateEnterFile string // `json:"templateEnterFile"` // 子路由入口文件
- TemplateModelFile string // `json:"templateModelFile"` // 子路由模型文件
- TargetModuleEnterFile string // `json:"targetModuleFile"` // 模块路由文件
- TargetModelFile string // `json:"targetModelFile"` // 模型路由文件
- Server string // server mod 名 go_server
- Module string // `json:"module" example:"保持与alias一致"`
- ModuleUpper string // `json:"moduleUpper" example:"模块名大写首字母"`
- Model string // `json:"model" example:"模型名"` xx_yy
- ModelUpper string // `json:"modelUpper" example:"模型名大写首字母"`
- RouterServiceName string // xxYyXxYyService
- ValKey string `json:"valKey"` // 默认值 priRouters
- BaseAst
- }
- func BuildSubRouterRegister(alias, model string) *SubRouterRegister {
- // aaBbAabb
- routerServiceName := fmt.Sprintf("%s%s", CapitalizeOrLower(toCamelCase(alias), false), CapitalizeOrLower(toCamelCase(model)))
- return &SubRouterRegister{
- TemplateEnterFile: TemplateSubRouterEnterFile(), // 入口模版文件
- TemplateModelFile: TemplateSubRouterRegisterFile(), // 模型模版文件
- TargetModuleEnterFile: ServerSubRouterEnterFile(alias), // 目标模板文件
- TargetModelFile: ServerSubRouterRegisterFile(alias, model), // 目标模型文件
- Server: server_mod, // app服务模块
- Module: alias, // 保持别名不变 // xx_yy
- ModuleUpper: CapitalizeOrLower(toCamelCase(alias)), // 改为首字母大写 驼峰结构 AaBb // XxYy
- Model: snakeString(model), // xx_yy
- ModelUpper: CapitalizeOrLower(toCamelCase(model)), // XxYy
- RouterServiceName: routerServiceName, // 路由服务名称 aaBbAabb
- ValKey: "allRouters",
- BaseAst: BaseAst{},
- }
- }
- func (s *SubRouterRegister) Inspect() error {
- var err error
- // 模版文件检查
- if !FileExists(s.TemplateEnterFile) {
- return errors.New("sub router enter template file is not exists")
- }
- if !FileExists(s.TemplateModelFile) {
- return errors.New("sub router model template file is not exists")
- }
- // 入口文件 -- 如果不存在则创建
- if !FileExists(s.TargetModuleEnterFile) {
- err = s.createEnterRouter()
- if err != nil {
- return err
- }
- }
- // 模型路由文件(仅支持创建与删除 不支持回滚)
- if !FileExists(s.TargetModelFile) {
- err = s.createModel()
- if err != nil {
- return err
- }
- }
- // 注入路由代码
- err = s.inspectRouter()
- if err != nil {
- return err
- }
- return nil
- }
- func (s *SubRouterRegister) Rollback() error {
- // 删除模型文件
- // 模型路由文件(仅支持创建与删除 不支持回滚)
- if FileExists(s.TargetModelFile) {
- err := os.Remove(s.TargetModelFile)
- if err != nil {
- return err
- }
- }
- // 子路由回滚
- err := s.rollbackRouter()
- if err != nil {
- return err
- }
- return nil
- }
- // 创建子路由入口文件
- func (s *SubRouterRegister) createEnterRouter() error {
- var files *template.Template
- files, err := template.ParseFiles(s.TemplateEnterFile)
- if err != nil {
- return err
- }
- err = os.MkdirAll(filepath.Dir(s.TargetModuleEnterFile), os.ModePerm)
- if err != nil {
- return err
- }
- var file *os.File
- file, err = os.Create(s.TargetModuleEnterFile)
- if err != nil {
- return err
- }
- err = files.Execute(file, s)
- _ = file.Close()
- if err != nil {
- return err
- }
- return nil
- }
- // 创建模型文件
- func (s *SubRouterRegister) createModel() error {
- var files *template.Template
- files, err := template.ParseFiles(s.TemplateModelFile)
- if err != nil {
- return err
- }
- //core.Log.Infof("子路由模板文件:%s", s.TemplateModelFile)
- err = os.MkdirAll(filepath.Dir(s.TargetModelFile), os.ModePerm)
- if err != nil {
- return err
- }
- //core.Log.Infof("子路由生成目标文件:%s", s.TargetModelFile)
- var file *os.File
- file, err = os.Create(s.TargetModelFile)
- if err != nil {
- return err
- }
- err = files.Execute(file, s)
- _ = file.Close()
- if err != nil {
- return err
- }
- return nil
- }
- // todo:子路由注入
- func (s *SubRouterRegister) inspectRouter() error {
- //core.Log.Infof("开始注入子路由")
- //core.Log.Infof("子路由Model文件:%s", s.TargetModelFile)
- //core.Log.Infof("子路由入口文件:%s", s.TargetModuleEnterFile)
- // 创建 FileSet 用于跟踪文件位置信息
- fSet := token.NewFileSet()
- // 解析源代码为 AST
- node, err := parser.ParseFile(fSet, s.TargetModuleEnterFile, nil, parser.ParseComments)
- if err != nil {
- return err
- }
- // 检查是否已注入
- inspectIsExists := s.IsContainsSubRouter(node, "allRouters", fmt.Sprintf("%sRouter", s.ModelUpper))
- if inspectIsExists {
- //core.Log.Infof("子路由%s已注入:allRouters", s.ModelUpper)
- return nil
- }
- s.inspectRouterToVars(node, "allRouters", fmt.Sprintf("%sRouter", s.ModelUpper))
- var out []byte
- bf := bytes.NewBuffer(out)
- err = printer.Fprint(bf, fSet, node)
- if err != nil {
- return err
- }
- err = os.WriteFile(s.TargetModuleEnterFile, bf.Bytes(), 0666)
- if err != nil {
- return err
- }
- //core.Log.Infof("成功添加 %s{} 到 allRouters", s.ModelUpper)
- return nil
- }
- // todo: 子路由回滚
- func (s *SubRouterRegister) rollbackRouter() error {
- // 创建 FileSet 用于跟踪文件位置信息
- fSet := token.NewFileSet()
- // 解析源代码为 AST
- node, err := parser.ParseFile(fSet, s.TargetModuleEnterFile, nil, parser.ParseComments)
- if err != nil {
- return err
- }
- // 检查是否已注入
- inspectIsExists := s.IsContainsSubRouter(node, "allRouters", fmt.Sprintf("%sRouter", s.ModelUpper))
- if !inspectIsExists {
- //core.Log.Infof("子路由%s已回滚:allRouters", s.ModelUpper)
- return nil
- }
- s.rollbackRouterFromVars(node, "allRouters", fmt.Sprintf("%sRouter", s.ModelUpper))
- var out []byte
- bf := bytes.NewBuffer(out)
- err = printer.Fprint(bf, fSet, node)
- if err != nil {
- return err
- }
- err = os.WriteFile(s.TargetModuleEnterFile, bf.Bytes(), 0666)
- if err != nil {
- return err
- }
- //core.Log.Infof("成功添从 allRouters 移除 %s{} ", fmt.Sprintf("%sRouter", s.ModelUpper))
- return nil
- }
- // 检查元素列表中是否已注入指定结果体
- // 检查变了列表 allRouters 中是否存在 XxYyRouterGroup{}
- // routerVal:allRouters
- func (s *SubRouterRegister) IsContainsSubRouter(node ast.Node, routerVal, subRouterName string) bool {
- // 2. 检查 UserRouter{} 是否存在
- routerExists := false
- ast.Inspect(node, func(n ast.Node) bool {
- // 查找 allRouters 变量声明
- if valueSpec, ok := n.(*ast.ValueSpec); ok && len(valueSpec.Names) > 0 && valueSpec.Names[0].Name == routerVal {
- if compLit, ok := valueSpec.Values[0].(*ast.CompositeLit); ok {
- for _, elt := range compLit.Elts {
- switch expr := elt.(type) {
- case *ast.CompositeLit:
- // 处理 AssetRouter{} 情况
- if selExpr, ok := expr.Type.(*ast.SelectorExpr); ok {
- if ident, ok := selExpr.X.(*ast.Ident); ok && ident.Name == subRouterName {
- routerExists = true
- return false
- }
- } else if ident, ok := expr.Type.(*ast.Ident); ok && ident.Name == subRouterName {
- routerExists = true
- return false
- }
- case *ast.SelectorExpr:
- // 处理 AssetRouter 情况 (没有花括号)
- if ident, ok := expr.X.(*ast.Ident); ok && ident.Name == subRouterName {
- routerExists = true
- return false
- }
- case *ast.Ident:
- // 处理 AssetRouter 情况 (单独标识符)
- if expr.Name == subRouterName {
- routerExists = true
- return false
- }
- }
- }
- }
- }
- return true
- })
- return routerExists
- }
- // 注入元素到列表
- func (s *SubRouterRegister) inspectRouterToVars(node ast.Node, routerVal, subRouterName string) {
- ast.Inspect(node, func(n ast.Node) bool {
- if valueSpec, ok := n.(*ast.ValueSpec); ok && len(valueSpec.Names) > 0 && valueSpec.Names[0].Name == routerVal {
- if compLit, ok := valueSpec.Values[0].(*ast.CompositeLit); ok {
- // 创建新的 AssetRouter{} 元素
- newElement := &ast.CompositeLit{
- Type: &ast.Ident{Name: subRouterName},
- }
- // 添加到切片中
- compLit.Elts = append(compLit.Elts, newElement)
- return false
- }
- }
- return true
- })
- }
- // 从列表移除元素
- func (s *SubRouterRegister) rollbackRouterFromVars(node ast.Node, routerVal, subRouterName string) {
- ast.Inspect(node, func(n ast.Node) bool {
- if valueSpec, ok := n.(*ast.ValueSpec); ok && len(valueSpec.Names) > 0 && valueSpec.Names[0].Name == routerVal {
- if compLit, ok := valueSpec.Values[0].(*ast.CompositeLit); ok {
- // Filter out elements with the specified subRouterName
- filteredEls := make([]ast.Expr, 0, len(compLit.Elts))
- for _, elt := range compLit.Elts {
- if cl, ok := elt.(*ast.CompositeLit); ok {
- if ident, ok := cl.Type.(*ast.Ident); ok {
- //core.Log.Infof("ident.name:%s", ident.Name)
- //core.Log.Infof("subRouterName:%s", subRouterName)
- if ident.Name == subRouterName {
- continue
- }
- // Skip this element (remove it)
- }
- }
- filteredEls = append(filteredEls, elt)
- }
- // Update the elements if any were removed
- if len(filteredEls) < len(compLit.Elts) {
- compLit.Elts = filteredEls
- }
- return false
- }
- }
- return true
- })
- }
|