beego:AST code
Showing
3 changed files
with
114 additions
and
25 deletions
| ... | @@ -34,8 +34,8 @@ const ( | ... | @@ -34,8 +34,8 @@ const ( |
| 34 | 34 | ||
| 35 | var ( | 35 | var ( |
| 36 | // custom error when user stop request handler manually. | 36 | // custom error when user stop request handler manually. |
| 37 | USERSTOPRUN = errors.New("User stop run") | 37 | USERSTOPRUN = errors.New("User stop run") |
| 38 | GlobalControllerRouter map[string]*ControllerComments //pkgpath+controller:comments | 38 | GlobalControllerRouter map[string][]ControllerComments = make(map[string][]ControllerComments) //pkgpath+controller:comments |
| 39 | ) | 39 | ) |
| 40 | 40 | ||
| 41 | // store the comment for the controller method | 41 | // store the comment for the controller method |
| ... | @@ -43,6 +43,7 @@ type ControllerComments struct { | ... | @@ -43,6 +43,7 @@ type ControllerComments struct { |
| 43 | method string | 43 | method string |
| 44 | router string | 44 | router string |
| 45 | allowHTTPMethods []string | 45 | allowHTTPMethods []string |
| 46 | params []map[string]string | ||
| 46 | } | 47 | } |
| 47 | 48 | ||
| 48 | // Controller defines some basic http request handler operations, such as | 49 | // Controller defines some basic http request handler operations, such as | ... | ... |
| ... | @@ -6,11 +6,17 @@ | ... | @@ -6,11 +6,17 @@ |
| 6 | package beego | 6 | package beego |
| 7 | 7 | ||
| 8 | import ( | 8 | import ( |
| 9 | "errors" | ||
| 10 | "fmt" | ||
| 11 | "go/ast" | ||
| 12 | "go/parser" | ||
| 13 | "go/token" | ||
| 9 | "os" | 14 | "os" |
| 10 | "path/filepath" | 15 | "path" |
| 16 | "strings" | ||
| 11 | ) | 17 | ) |
| 12 | 18 | ||
| 13 | var globalControllerRouter = `package routers | 19 | var globalRouterTemplate = `package routers |
| 14 | 20 | ||
| 15 | import ( | 21 | import ( |
| 16 | "github.com/astaxie/beego" | 22 | "github.com/astaxie/beego" |
| ... | @@ -21,26 +27,106 @@ func init() { | ... | @@ -21,26 +27,106 @@ func init() { |
| 21 | } | 27 | } |
| 22 | ` | 28 | ` |
| 23 | 29 | ||
| 24 | func parserPkg(pkgpath string) error { | 30 | var genInfoList map[string][]ControllerComments |
| 25 | err := filepath.Walk(pkgpath, func(path string, info os.FileInfo, err error) error { | ||
| 26 | if err != nil { | ||
| 27 | Error("error scan app Controller source:", err) | ||
| 28 | return err | ||
| 29 | } | ||
| 30 | //if is normal file or name is temp skip | ||
| 31 | //directory is needed | ||
| 32 | if !info.IsDir() || info.Name() == "tmp" { | ||
| 33 | return nil | ||
| 34 | } | ||
| 35 | 31 | ||
| 36 | //fileSet := token.NewFileSet() | 32 | func init() { |
| 37 | //astPkgs, err := parser.ParseDir(fileSet, path, func(info os.FileInfo) bool { | 33 | genInfoList = make(map[string][]ControllerComments) |
| 38 | // name := info.Name() | 34 | } |
| 39 | // return !info.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") | ||
| 40 | //}, parser.ParseComments) | ||
| 41 | 35 | ||
| 42 | return nil | 36 | func parserPkg(pkgRealpath, pkgpath string) error { |
| 43 | }) | 37 | fileSet := token.NewFileSet() |
| 38 | astPkgs, err := parser.ParseDir(fileSet, pkgRealpath, func(info os.FileInfo) bool { | ||
| 39 | name := info.Name() | ||
| 40 | return !info.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") | ||
| 41 | }, parser.ParseComments) | ||
| 44 | 42 | ||
| 45 | return err | 43 | if err != nil { |
| 44 | return err | ||
| 45 | } | ||
| 46 | for _, pkg := range astPkgs { | ||
| 47 | for _, fl := range pkg.Files { | ||
| 48 | for _, d := range fl.Decls { | ||
| 49 | switch specDecl := d.(type) { | ||
| 50 | case *ast.FuncDecl: | ||
| 51 | parserComments(specDecl.Doc, specDecl.Name.String(), fmt.Sprint(specDecl.Recv.List[0].Type.(*ast.StarExpr).X), pkgpath) | ||
| 52 | } | ||
| 53 | } | ||
| 54 | } | ||
| 55 | } | ||
| 56 | genRouterCode() | ||
| 57 | return nil | ||
| 58 | } | ||
| 59 | |||
| 60 | func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpath string) error { | ||
| 61 | if comments != nil && comments.List != nil { | ||
| 62 | for _, c := range comments.List { | ||
| 63 | t := strings.TrimSpace(strings.TrimLeft(c.Text, "//")) | ||
| 64 | if strings.HasPrefix(t, "@router") { | ||
| 65 | elements := strings.TrimLeft(t, "@router ") | ||
| 66 | e1 := strings.SplitN(elements, " ", 2) | ||
| 67 | if len(e1) < 1 { | ||
| 68 | return errors.New("you should has router infomation") | ||
| 69 | } | ||
| 70 | key := pkgpath + ":" + controllerName | ||
| 71 | cc := ControllerComments{} | ||
| 72 | cc.method = funcName | ||
| 73 | cc.router = e1[0] | ||
| 74 | if len(e1) == 2 && e1[1] != "" { | ||
| 75 | e1 = strings.SplitN(e1[1], " ", 2) | ||
| 76 | if len(e1) >= 1 { | ||
| 77 | cc.allowHTTPMethods = strings.Split(strings.Trim(e1[0], "[]"), ",") | ||
| 78 | } else { | ||
| 79 | cc.allowHTTPMethods = append(cc.allowHTTPMethods, "get") | ||
| 80 | } | ||
| 81 | } else { | ||
| 82 | cc.allowHTTPMethods = append(cc.allowHTTPMethods, "get") | ||
| 83 | } | ||
| 84 | if len(e1) == 2 && e1[1] != "" { | ||
| 85 | keyval := strings.Split(strings.Trim(e1[1], "[]"), " ") | ||
| 86 | for _, kv := range keyval { | ||
| 87 | kk := strings.Split(kv, ":") | ||
| 88 | cc.params = append(cc.params, map[string]string{strings.Join(kk[:len(kk)-1], ":"): kk[len(kk)-1]}) | ||
| 89 | } | ||
| 90 | } | ||
| 91 | genInfoList[key] = append(genInfoList[key], cc) | ||
| 92 | } | ||
| 93 | } | ||
| 94 | } | ||
| 95 | return nil | ||
| 96 | } | ||
| 97 | |||
| 98 | func genRouterCode() { | ||
| 99 | os.Mkdir(path.Join(AppPath, "routers"), 0755) | ||
| 100 | Info("generate router from comments") | ||
| 101 | f, err := os.Create(path.Join(AppPath, "routers", "commentsRouter.go")) | ||
| 102 | if err != nil { | ||
| 103 | panic(err) | ||
| 104 | } | ||
| 105 | defer f.Close() | ||
| 106 | var globalinfo string | ||
| 107 | for k, cList := range genInfoList { | ||
| 108 | for _, c := range cList { | ||
| 109 | allmethod := "nil" | ||
| 110 | if len(c.allowHTTPMethods) > 0 { | ||
| 111 | allmethod = "[]string{" | ||
| 112 | for _, m := range c.allowHTTPMethods { | ||
| 113 | allmethod += `"` + m + `",` | ||
| 114 | } | ||
| 115 | allmethod = strings.TrimRight(allmethod, ",") + "}" | ||
| 116 | } | ||
| 117 | params := "nil" | ||
| 118 | if len(c.params) > 0 { | ||
| 119 | params = "[]map[string]string{" | ||
| 120 | for _, p := range c.params { | ||
| 121 | for k, v := range p { | ||
| 122 | params = params + `map[string]string{` + k + `:"` + v + `"},` | ||
| 123 | } | ||
| 124 | } | ||
| 125 | params = strings.TrimRight(params, ",") + "}" | ||
| 126 | } | ||
| 127 | globalinfo = globalinfo + fmt.Sprintln(`beego.GlobalControllerRouter["`+k+`"] = &ControllerComments{"`+ | ||
| 128 | strings.TrimSpace(c.method)+`", "`+c.router+`", `+allmethod+", "+params+"}") | ||
| 129 | } | ||
| 130 | } | ||
| 131 | f.WriteString(strings.Replace(globalRouterTemplate, "{{.globalinfo}}", globalinfo, -1)) | ||
| 46 | } | 132 | } | ... | ... |
| ... | @@ -174,7 +174,7 @@ func (p *ControllerRegistor) Include(cList ...ControllerInterface) { | ... | @@ -174,7 +174,7 @@ func (p *ControllerRegistor) Include(cList ...ControllerInterface) { |
| 174 | if pkgpath != "" { | 174 | if pkgpath != "" { |
| 175 | if _, ok := skip[pkgpath]; !ok { | 175 | if _, ok := skip[pkgpath]; !ok { |
| 176 | skip[pkgpath] = true | 176 | skip[pkgpath] = true |
| 177 | parserPkg(pkgpath) | 177 | parserPkg(pkgpath, t.PkgPath()) |
| 178 | } | 178 | } |
| 179 | } | 179 | } |
| 180 | } | 180 | } |
| ... | @@ -184,7 +184,9 @@ func (p *ControllerRegistor) Include(cList ...ControllerInterface) { | ... | @@ -184,7 +184,9 @@ func (p *ControllerRegistor) Include(cList ...ControllerInterface) { |
| 184 | t := reflect.Indirect(reflectVal).Type() | 184 | t := reflect.Indirect(reflectVal).Type() |
| 185 | key := t.PkgPath() + ":" + t.Name() | 185 | key := t.PkgPath() + ":" + t.Name() |
| 186 | if comm, ok := GlobalControllerRouter[key]; ok { | 186 | if comm, ok := GlobalControllerRouter[key]; ok { |
| 187 | p.Add(comm.router, c, strings.Join(comm.allowHTTPMethods, ",")+":"+comm.method) | 187 | for _, a := range comm { |
| 188 | p.Add(a.router, c, strings.Join(a.allowHTTPMethods, ",")+":"+a.method) | ||
| 189 | } | ||
| 188 | } | 190 | } |
| 189 | } | 191 | } |
| 190 | } | 192 | } | ... | ... |
-
Please register or sign in to post a comment