diff --git a/g_docs.go b/g_docs.go index fbc22b3..00995b0 100644 --- a/g_docs.go +++ b/g_docs.go @@ -220,6 +220,9 @@ func generateDocs(curpath string) { Name: strings.Trim(s, "/"), Description: v, }) + if policy := policyList[controllerName]; policy != nil { + policyPathList[version+s] = policy + } } } } @@ -260,6 +263,8 @@ func generateDocs(curpath string) { if err != nil || erryml != nil { panic(err) } + + generatePolicies(curpath) } // analyseNewNamespace returns version and the others params @@ -390,6 +395,7 @@ func analyseControllerPkg(localName, pkgpath string) { // Parse controller definition comments if strings.TrimSpace(specDecl.Doc.Text()) != "" { controllerComments[pkgpath+s.(*ast.TypeSpec).Name.String()] = specDecl.Doc.Text() + controllerFindPolicies(specDecl.Doc, s.(*ast.TypeSpec).Name.Name, pkgpath) } } } @@ -438,6 +444,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat opts := swagger.Operation{ Responses: make(map[string]swagger.Response), } + policy := Policy{} if comments != nil && comments.List != nil { for _, c := range comments.List { t := strings.TrimSpace(strings.TrimLeft(c.Text, "//")) @@ -617,6 +624,11 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat opts.Produces = append(opts.Produces, ahtml) } } + } else if strings.HasPrefix(t, "@policy") { + policyFields := strings.FieldsFunc(t[len("@policy"):], func(c rune) bool {return !unicode.IsLetter(c) && !unicode.IsNumber(c) && c!='_'}) + for _, val := range policyFields { + policy.Policies = append(policy.Policies, val) + } } } } @@ -649,6 +661,27 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat item.Options = &opts } controllerList[pkgpath+controllerName][routerPath] = item + + if len(policy.Policies) > 0 { + policy.Method = strings.ToLower(HTTPMethod) + if i := strings.Index(routerPath, ":"); i < 0 { + policy.Path = routerPath + } else { + policy.Path = routerPath[:i] + } + policyMethods := policyList[pkgpath+controllerName] + if policyMethods == nil { + policyMethods = make(map[string]*Policy) + policyList[pkgpath+controllerName] = policyMethods + } + if pm := policyMethods[policy.Method]; pm != nil { + for _, curPolicy := range policy.Policies { + pm.Policies = append(pm.Policies, curPolicy) + } + } else { + policyMethods[policy.Method] = &policy + } + } } return nil } diff --git a/g_policies.go b/g_policies.go new file mode 100644 index 0000000..5c4f92d --- /dev/null +++ b/g_policies.go @@ -0,0 +1,104 @@ +// Copyright 2016 bee authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "bytes" + "go/ast" + "os" + "path" + "strings" + "text/template" + "unicode" +) + +type Policy struct { + Method string + Path string + Policies []string +} + +var ( + policyList = make(map[string]map[string]*Policy) //controllername -> method -> policy + policyPathList = make(map[string]map[string]*Policy) //path -> method -> policy +) + +func controllerFindPolicies(comments *ast.CommentGroup, controllerName, pkgpath string) { + if comments == nil || comments.List == nil { + return + } + for _, c := range comments.List { + t := strings.TrimSpace(strings.TrimLeft(c.Text, "//")) + if strings.HasPrefix(t, "@policy") { + policy := Policy{ + Method: "*", + } + policyFields := strings.FieldsFunc(t[len("@policy"):], func(c rune) bool { return !unicode.IsLetter(c) && !unicode.IsNumber(c) && c != '_' }) + for _, val := range policyFields { + policy.Policies = append(policy.Policies, val) + } + policyMethods := policyList[pkgpath+controllerName] + if policyMethods == nil { + policyMethods = make(map[string]*Policy) + policyList[pkgpath+controllerName] = policyMethods + } + if pm := policyMethods[policy.Method]; pm != nil { + for _, curPolicy := range policy.Policies { + pm.Policies = append(pm.Policies, curPolicy) + } + } else { + policyMethods[policy.Method] = &policy + } + } + } +} + +func generatePolicies(curpath string) { + fn := template.FuncMap{ + "join": strings.Join, + } + + tmpl, err := template.New("policy template").Funcs(fn).Parse(policyTpl) + if err != nil { + panic("Can't parse policy template: " + err.Error()) + } + var buf bytes.Buffer + err = tmpl.Execute(&buf, policyPathList) + if err != nil { + panic("Can't execute policy template: " + err.Error()) + + } + policyFile, err := os.Create(path.Join(curpath, "policies", "policies_autogen.go")) + if err != nil { + panic(err) + } + defer policyFile.Close() + + _, err = policyFile.Write(buf.Bytes()) + if err != nil { + panic(err) + } +} + +var policyTpl = `// This file was auto-generated by bee tools, do not change it! +package policies + +import "github.com/astaxie/beego" + +func init() { +{{ range $path, $policyList := . }}{{ range $, $policy := $policyList }} beego.Policy("{{$path}}{{$policy.Path}}", "{{$policy.Method}}", {{ join $policy.Policies ", " }}) +{{ end }}{{ end }} +} +` diff --git a/watch.go b/watch.go index 2ce1f9b..de9c5f0 100644 --- a/watch.go +++ b/watch.go @@ -261,6 +261,7 @@ var ignoredFilesRegExps = []string{ `.(\w+).go.swp`, `(\w+).go~`, `(\w+).tmp`, + `policies_autogen.go`, } // shouldWatchFileWithExtension returns true if the name of the file