mirror of
https://github.com/beego/bee.git
synced 2024-11-25 04:40:54 +00:00
Support NSRouter
and multi-level namespace
* Support `NSRouter` * As `NSRouter` doesn't need `@router` annotation, changed `parserComments` to parse comments of HTTP method functions(Get, Post, ...) without `@router` annotation * Support multi-level namespace * Traverse `Namespace`, `NSRouter`, `NSInclude` in a depth-first manner. * Set controller's tag as a concatenation of route path from root(`NewNamespace)` to leaf nodes(`NSRouter`, `NSInclude`)
This commit is contained in:
parent
36a17c40b0
commit
1eaaa91cab
@ -93,6 +93,16 @@ var stdlibObject = map[string]string{
|
||||
"&{json RawMessage}": "json.RawMessage",
|
||||
}
|
||||
|
||||
var httpMethods = map[string]bool{
|
||||
"GET": true,
|
||||
"POST": true,
|
||||
"PUT": true,
|
||||
"PATCH": true,
|
||||
"DELETE": true,
|
||||
"HEAD": true,
|
||||
"OPTIONS": true,
|
||||
}
|
||||
|
||||
func init() {
|
||||
pkgCache = make(map[string]struct{})
|
||||
controllerComments = make(map[string]string)
|
||||
@ -278,41 +288,7 @@ func GenerateDocs(curpath string) {
|
||||
if !selOK || selExpr.Sel.Name != "NewNamespace" {
|
||||
continue
|
||||
}
|
||||
version, params := analyseNewNamespace(v)
|
||||
if rootapi.BasePath == "" && version != "" {
|
||||
rootapi.BasePath = version
|
||||
}
|
||||
for _, p := range params {
|
||||
switch pp := p.(type) {
|
||||
case *ast.CallExpr:
|
||||
var controllerName string
|
||||
if selname := pp.Fun.(*ast.SelectorExpr).Sel.String(); selname == "NSNamespace" {
|
||||
s, params := analyseNewNamespace(pp)
|
||||
for _, sp := range params {
|
||||
switch pp := sp.(type) {
|
||||
case *ast.CallExpr:
|
||||
if pp.Fun.(*ast.SelectorExpr).Sel.String() == "NSInclude" {
|
||||
controllerName = analyseNSInclude(s, pp)
|
||||
if v, ok := controllerComments[controllerName]; ok {
|
||||
rootapi.Tags = append(rootapi.Tags, swagger.Tag{
|
||||
Name: strings.Trim(s, "/"),
|
||||
Description: v,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if selname == "NSInclude" {
|
||||
controllerName = analyseNSInclude("", pp)
|
||||
if v, ok := controllerComments[controllerName]; ok {
|
||||
rootapi.Tags = append(rootapi.Tags, swagger.Tag{
|
||||
Name: controllerName, // if the NSInclude has no prefix, we use the controllername as the tag
|
||||
Description: v,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
traverseNameSpace("", v)
|
||||
}
|
||||
|
||||
}
|
||||
@ -343,6 +319,41 @@ func GenerateDocs(curpath string) {
|
||||
}
|
||||
}
|
||||
|
||||
func traverseNameSpace(baseURL string, pp *ast.CallExpr) {
|
||||
s, params := analyseNewNamespace(pp)
|
||||
if rootapi.BasePath == "" && baseURL == "" {
|
||||
rootapi.BasePath = s // version
|
||||
s = ""
|
||||
}
|
||||
for _, sp := range params {
|
||||
switch pp := sp.(type) {
|
||||
case *ast.CallExpr:
|
||||
selname := pp.Fun.(*ast.SelectorExpr).Sel.String()
|
||||
switch selname {
|
||||
case "NSNamespace":
|
||||
traverseNameSpace(baseURL+s, pp)
|
||||
case "NSRouter":
|
||||
rootpath := strings.Trim(pp.Args[0].(*ast.BasicLit).Value, "\"")
|
||||
controllerName := analyseNSRouter(baseURL+s, rootpath, pp)
|
||||
if v, ok := controllerComments[controllerName]; ok {
|
||||
rootapi.Tags = append(rootapi.Tags, swagger.Tag{
|
||||
Name: strings.Trim(s, "/"),
|
||||
Description: v,
|
||||
})
|
||||
}
|
||||
case "NSInclude":
|
||||
controllerName := analyseNSInclude(baseURL+s, pp)
|
||||
if v, ok := controllerComments[controllerName]; ok {
|
||||
rootapi.Tags = append(rootapi.Tags, swagger.Tag{
|
||||
Name: strings.Trim(s, "/"),
|
||||
Description: v,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// analyseNewNamespace returns version and the others params
|
||||
func analyseNewNamespace(ce *ast.CallExpr) (first string, others []ast.Expr) {
|
||||
for i, p := range ce.Args {
|
||||
@ -358,29 +369,18 @@ func analyseNewNamespace(ce *ast.CallExpr) (first string, others []ast.Expr) {
|
||||
return
|
||||
}
|
||||
|
||||
func analyseNSInclude(baseurl string, ce *ast.CallExpr) string {
|
||||
cname := ""
|
||||
for _, p := range ce.Args {
|
||||
var x *ast.SelectorExpr
|
||||
var p1 interface{} = p
|
||||
if ident, ok := p1.(*ast.Ident); ok {
|
||||
if assign, ok := ident.Obj.Decl.(*ast.AssignStmt); ok {
|
||||
if len(assign.Rhs) > 0 {
|
||||
p1 = assign.Rhs[0].(*ast.UnaryExpr)
|
||||
}
|
||||
}
|
||||
}
|
||||
if _, ok := p1.(*ast.UnaryExpr); ok {
|
||||
x = p1.(*ast.UnaryExpr).X.(*ast.CompositeLit).Type.(*ast.SelectorExpr)
|
||||
} else {
|
||||
beeLogger.Log.Warnf("Couldn't determine type\n")
|
||||
continue
|
||||
}
|
||||
if v, ok := importlist[fmt.Sprint(x.X)]; ok {
|
||||
cname = v + x.Sel.Name
|
||||
func appendController(pkgname, cname, baseurl, routeurl string) string {
|
||||
if v, ok := importlist[pkgname]; ok {
|
||||
cname = v + cname
|
||||
}
|
||||
if apis, ok := controllerList[cname]; ok {
|
||||
for rt, item := range apis {
|
||||
if routeurl != "" {
|
||||
if rt != "" {
|
||||
continue
|
||||
}
|
||||
rt = routeurl // routers without '@router' annotation
|
||||
}
|
||||
tag := cname
|
||||
if baseurl != "" {
|
||||
rt = baseurl + rt
|
||||
@ -414,6 +414,41 @@ func analyseNSInclude(baseurl string, ce *ast.CallExpr) string {
|
||||
rootapi.Paths[rt] = item
|
||||
}
|
||||
}
|
||||
return cname
|
||||
}
|
||||
|
||||
func analyseNSRouter(baseurl, routeurl string, ce *ast.CallExpr) string {
|
||||
var x *ast.SelectorExpr
|
||||
var p interface{} = ce.Args[1]
|
||||
|
||||
if _, ok := p.(*ast.UnaryExpr); ok {
|
||||
x = p.(*ast.UnaryExpr).X.(*ast.CompositeLit).Type.(*ast.SelectorExpr)
|
||||
} else {
|
||||
beeLogger.Log.Warnf("Couldn't determine type\n")
|
||||
}
|
||||
return appendController(fmt.Sprint(x.X), x.Sel.Name, baseurl, routeurl)
|
||||
}
|
||||
|
||||
func analyseNSInclude(baseurl string, ce *ast.CallExpr) string {
|
||||
cname := ""
|
||||
for _, p := range ce.Args {
|
||||
var x *ast.SelectorExpr
|
||||
var p1 interface{} = p
|
||||
if ident, ok := p1.(*ast.Ident); ok {
|
||||
if assign, ok := ident.Obj.Decl.(*ast.AssignStmt); ok {
|
||||
if len(assign.Rhs) > 0 {
|
||||
p1 = assign.Rhs[0].(*ast.UnaryExpr)
|
||||
}
|
||||
}
|
||||
}
|
||||
if _, ok := p1.(*ast.UnaryExpr); ok {
|
||||
x = p1.(*ast.UnaryExpr).X.(*ast.CompositeLit).Type.(*ast.SelectorExpr)
|
||||
} else {
|
||||
beeLogger.Log.Warnf("Couldn't determine type\n")
|
||||
continue
|
||||
}
|
||||
|
||||
cname = appendController(fmt.Sprint(x.X), x.Sel.Name, baseurl, "")
|
||||
}
|
||||
return cname
|
||||
}
|
||||
@ -538,6 +573,10 @@ func parserComments(f *ast.FuncDecl, controllerName, pkgpath string) error {
|
||||
funcName := f.Name.String()
|
||||
comments := f.Doc
|
||||
funcParamMap := buildParamMap(f.Type.Params)
|
||||
|
||||
if fn := strings.ToUpper(funcName); httpMethods[fn] {
|
||||
HTTPMethod = fn
|
||||
}
|
||||
//TODO: resultMap := buildParamMap(f.Type.Results)
|
||||
if comments != nil && comments.List != nil {
|
||||
for _, c := range comments.List {
|
||||
@ -731,7 +770,7 @@ func parserComments(f *ast.FuncDecl, controllerName, pkgpath string) error {
|
||||
}
|
||||
}
|
||||
|
||||
if routerPath != "" {
|
||||
if HTTPMethod != "" {
|
||||
//Go over function parameters which were not mapped and create swagger params for them
|
||||
for name, typ := range funcParamMap {
|
||||
para := swagger.Parameter{}
|
||||
|
Loading…
Reference in New Issue
Block a user