21cb8ea4 by astaxie

beego:AST code

1 parent 6c8a7f13
...@@ -35,7 +35,7 @@ const ( ...@@ -35,7 +35,7 @@ const (
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 { 31
32 func init() {
33 genInfoList = make(map[string][]ControllerComments)
34 }
35
36 func parserPkg(pkgRealpath, pkgpath string) error {
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)
42
26 if err != nil { 43 if err != nil {
27 Error("error scan app Controller source:", err)
28 return err 44 return err
29 } 45 }
30 //if is normal file or name is temp skip 46 for _, pkg := range astPkgs {
31 //directory is needed 47 for _, fl := range pkg.Files {
32 if !info.IsDir() || info.Name() == "tmp" { 48 for _, d := range fl.Decls {
33 return nil 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)
34 } 52 }
53 }
54 }
55 }
56 genRouterCode()
57 return nil
58 }
35 59
36 //fileSet := token.NewFileSet() 60 func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpath string) error {
37 //astPkgs, err := parser.ParseDir(fileSet, path, func(info os.FileInfo) bool { 61 if comments != nil && comments.List != nil {
38 // name := info.Name() 62 for _, c := range comments.List {
39 // return !info.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") 63 t := strings.TrimSpace(strings.TrimLeft(c.Text, "//"))
40 //}, parser.ParseComments) 64 if strings.HasPrefix(t, "@router") {
41 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 }
42 return nil 95 return nil
43 }) 96 }
44 97
45 return err 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 }
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!