Commit 21cb8ea4 authored by astaxie's avatar astaxie

beego:AST code

parent 6c8a7f13
...@@ -34,8 +34,8 @@ const ( ...@@ -34,8 +34,8 @@ const (
var ( var (
// custom error when user stop request handler manually. // custom error when user stop request handler manually.
USERSTOPRUN = errors.New("User stop run") USERSTOPRUN = errors.New("User stop run")
GlobalControllerRouter map[string]*ControllerComments //pkgpath+controller:comments GlobalControllerRouter map[string][]ControllerComments = make(map[string][]ControllerComments) //pkgpath+controller:comments
) )
// store the comment for the controller method // store the comment for the controller method
...@@ -43,6 +43,7 @@ type ControllerComments struct { ...@@ -43,6 +43,7 @@ type ControllerComments struct {
method string method string
router string router string
allowHTTPMethods []string allowHTTPMethods []string
params []map[string]string
} }
// Controller defines some basic http request handler operations, such as // Controller defines some basic http request handler operations, such as
......
...@@ -6,11 +6,17 @@ ...@@ -6,11 +6,17 @@
package beego package beego
import ( import (
"errors"
"fmt"
"go/ast"
"go/parser"
"go/token"
"os" "os"
"path/filepath" "path"
"strings"
) )
var globalControllerRouter = `package routers var globalRouterTemplate = `package routers
import ( import (
"github.com/astaxie/beego" "github.com/astaxie/beego"
...@@ -21,26 +27,106 @@ func init() { ...@@ -21,26 +27,106 @@ func init() {
} }
` `
func parserPkg(pkgpath string) error { var genInfoList map[string][]ControllerComments
err := filepath.Walk(pkgpath, func(path string, info os.FileInfo, err error) error {
if err != nil {
Error("error scan app Controller source:", err)
return err
}
//if is normal file or name is temp skip
//directory is needed
if !info.IsDir() || info.Name() == "tmp" {
return nil
}
//fileSet := token.NewFileSet() func init() {
//astPkgs, err := parser.ParseDir(fileSet, path, func(info os.FileInfo) bool { genInfoList = make(map[string][]ControllerComments)
// name := info.Name() }
// return !info.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
//}, parser.ParseComments)
return nil func parserPkg(pkgRealpath, pkgpath string) error {
}) fileSet := token.NewFileSet()
astPkgs, err := parser.ParseDir(fileSet, pkgRealpath, func(info os.FileInfo) bool {
name := info.Name()
return !info.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
}, parser.ParseComments)
return err if err != nil {
return err
}
for _, pkg := range astPkgs {
for _, fl := range pkg.Files {
for _, d := range fl.Decls {
switch specDecl := d.(type) {
case *ast.FuncDecl:
parserComments(specDecl.Doc, specDecl.Name.String(), fmt.Sprint(specDecl.Recv.List[0].Type.(*ast.StarExpr).X), pkgpath)
}
}
}
}
genRouterCode()
return nil
}
func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpath string) error {
if comments != nil && comments.List != nil {
for _, c := range comments.List {
t := strings.TrimSpace(strings.TrimLeft(c.Text, "//"))
if strings.HasPrefix(t, "@router") {
elements := strings.TrimLeft(t, "@router ")
e1 := strings.SplitN(elements, " ", 2)
if len(e1) < 1 {
return errors.New("you should has router infomation")
}
key := pkgpath + ":" + controllerName
cc := ControllerComments{}
cc.method = funcName
cc.router = e1[0]
if len(e1) == 2 && e1[1] != "" {
e1 = strings.SplitN(e1[1], " ", 2)
if len(e1) >= 1 {
cc.allowHTTPMethods = strings.Split(strings.Trim(e1[0], "[]"), ",")
} else {
cc.allowHTTPMethods = append(cc.allowHTTPMethods, "get")
}
} else {
cc.allowHTTPMethods = append(cc.allowHTTPMethods, "get")
}
if len(e1) == 2 && e1[1] != "" {
keyval := strings.Split(strings.Trim(e1[1], "[]"), " ")
for _, kv := range keyval {
kk := strings.Split(kv, ":")
cc.params = append(cc.params, map[string]string{strings.Join(kk[:len(kk)-1], ":"): kk[len(kk)-1]})
}
}
genInfoList[key] = append(genInfoList[key], cc)
}
}
}
return nil
}
func genRouterCode() {
os.Mkdir(path.Join(AppPath, "routers"), 0755)
Info("generate router from comments")
f, err := os.Create(path.Join(AppPath, "routers", "commentsRouter.go"))
if err != nil {
panic(err)
}
defer f.Close()
var globalinfo string
for k, cList := range genInfoList {
for _, c := range cList {
allmethod := "nil"
if len(c.allowHTTPMethods) > 0 {
allmethod = "[]string{"
for _, m := range c.allowHTTPMethods {
allmethod += `"` + m + `",`
}
allmethod = strings.TrimRight(allmethod, ",") + "}"
}
params := "nil"
if len(c.params) > 0 {
params = "[]map[string]string{"
for _, p := range c.params {
for k, v := range p {
params = params + `map[string]string{` + k + `:"` + v + `"},`
}
}
params = strings.TrimRight(params, ",") + "}"
}
globalinfo = globalinfo + fmt.Sprintln(`beego.GlobalControllerRouter["`+k+`"] = &ControllerComments{"`+
strings.TrimSpace(c.method)+`", "`+c.router+`", `+allmethod+", "+params+"}")
}
}
f.WriteString(strings.Replace(globalRouterTemplate, "{{.globalinfo}}", globalinfo, -1))
} }
...@@ -174,7 +174,7 @@ func (p *ControllerRegistor) Include(cList ...ControllerInterface) { ...@@ -174,7 +174,7 @@ func (p *ControllerRegistor) Include(cList ...ControllerInterface) {
if pkgpath != "" { if pkgpath != "" {
if _, ok := skip[pkgpath]; !ok { if _, ok := skip[pkgpath]; !ok {
skip[pkgpath] = true skip[pkgpath] = true
parserPkg(pkgpath) parserPkg(pkgpath, t.PkgPath())
} }
} }
} }
...@@ -184,7 +184,9 @@ func (p *ControllerRegistor) Include(cList ...ControllerInterface) { ...@@ -184,7 +184,9 @@ func (p *ControllerRegistor) Include(cList ...ControllerInterface) {
t := reflect.Indirect(reflectVal).Type() t := reflect.Indirect(reflectVal).Type()
key := t.PkgPath() + ":" + t.Name() key := t.PkgPath() + ":" + t.Name()
if comm, ok := GlobalControllerRouter[key]; ok { if comm, ok := GlobalControllerRouter[key]; ok {
p.Add(comm.router, c, strings.Join(comm.allowHTTPMethods, ",")+":"+comm.method) for _, a := range comm {
p.Add(a.router, c, strings.Join(a.allowHTTPMethods, ",")+":"+a.method)
}
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment