mirror of
https://github.com/beego/bee.git
synced 2024-11-21 23:50:54 +00:00
add support for controller methods with paramaters
- allow automatic mapping of type from method params - generate swagger for parameters not covered by comment annotations
This commit is contained in:
parent
c76d4d1451
commit
a117a48d7b
@ -362,11 +362,11 @@ func analyseControllerPkg(vendorPath, localName, pkgpath string) {
|
|||||||
pkgRealpath = wg
|
pkgRealpath = wg
|
||||||
} else {
|
} else {
|
||||||
wgopath := gopaths
|
wgopath := gopaths
|
||||||
for _, wg := range wgopath {
|
for _, wg := range wgopath {
|
||||||
wg, _ = filepath.EvalSymlinks(filepath.Join(wg, "src", pkgpath))
|
wg, _ = filepath.EvalSymlinks(filepath.Join(wg, "src", pkgpath))
|
||||||
if utils.FileExists(wg) {
|
if utils.FileExists(wg) {
|
||||||
pkgRealpath = wg
|
pkgRealpath = wg
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -395,7 +395,7 @@ func analyseControllerPkg(vendorPath, localName, pkgpath string) {
|
|||||||
if specDecl.Recv != nil && len(specDecl.Recv.List) > 0 {
|
if specDecl.Recv != nil && len(specDecl.Recv.List) > 0 {
|
||||||
if t, ok := specDecl.Recv.List[0].Type.(*ast.StarExpr); ok {
|
if t, ok := specDecl.Recv.List[0].Type.(*ast.StarExpr); ok {
|
||||||
// Parse controller method
|
// Parse controller method
|
||||||
parserComments(specDecl.Doc, specDecl.Name.String(), fmt.Sprint(t.X), pkgpath)
|
parserComments(specDecl, fmt.Sprint(t.X), pkgpath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *ast.GenDecl:
|
case *ast.GenDecl:
|
||||||
@ -448,12 +448,16 @@ func peekNextSplitString(ss string) (s string, spacePos int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse the func comments
|
// parse the func comments
|
||||||
func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpath string) error {
|
func parserComments(f *ast.FuncDecl, controllerName, pkgpath string) error {
|
||||||
var routerPath string
|
var routerPath string
|
||||||
var HTTPMethod string
|
var HTTPMethod string
|
||||||
opts := swagger.Operation{
|
opts := swagger.Operation{
|
||||||
Responses: make(map[string]swagger.Response),
|
Responses: make(map[string]swagger.Response),
|
||||||
}
|
}
|
||||||
|
funcName := f.Name.String()
|
||||||
|
comments := f.Doc
|
||||||
|
funcParamMap := buildParamMap(f.Type.Params)
|
||||||
|
//TODO: resultMap := buildParamMap(f.Type.Results)
|
||||||
if comments != nil && comments.List != nil {
|
if comments != nil && comments.List != nil {
|
||||||
for _, c := range comments.List {
|
for _, c := range comments.List {
|
||||||
t := strings.TrimSpace(strings.TrimLeft(c.Text, "//"))
|
t := strings.TrimSpace(strings.TrimLeft(c.Text, "//"))
|
||||||
@ -526,7 +530,17 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
if len(p) < 4 {
|
if len(p) < 4 {
|
||||||
beeLogger.Log.Fatal(controllerName + "_" + funcName + "'s comments @Param should have at least 4 params")
|
beeLogger.Log.Fatal(controllerName + "_" + funcName + "'s comments @Param should have at least 4 params")
|
||||||
}
|
}
|
||||||
para.Name = p[0]
|
paramNames := strings.SplitN(p[0], "=>", 2)
|
||||||
|
para.Name = paramNames[0]
|
||||||
|
funcParamName := para.Name
|
||||||
|
if len(paramNames) > 1 {
|
||||||
|
funcParamName = paramNames[1]
|
||||||
|
}
|
||||||
|
paramType, ok := funcParamMap[funcParamName]
|
||||||
|
if ok {
|
||||||
|
delete(funcParamMap, funcParamName)
|
||||||
|
}
|
||||||
|
|
||||||
switch p[1] {
|
switch p[1] {
|
||||||
case "query":
|
case "query":
|
||||||
fallthrough
|
fallthrough
|
||||||
@ -555,33 +569,10 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
modelsList[pkgpath+controllerName][typ] = mod
|
modelsList[pkgpath+controllerName][typ] = mod
|
||||||
appendModels(pkgpath, controllerName, realTypes)
|
appendModels(pkgpath, controllerName, realTypes)
|
||||||
} else {
|
} else {
|
||||||
isArray := false
|
if typ == "auto" {
|
||||||
paraType := ""
|
typ = paramType
|
||||||
paraFormat := ""
|
|
||||||
if strings.HasPrefix(typ, "[]") {
|
|
||||||
typ = typ[2:]
|
|
||||||
isArray = true
|
|
||||||
}
|
|
||||||
if typ == "string" || typ == "number" || typ == "integer" || typ == "boolean" ||
|
|
||||||
typ == "array" || typ == "file" {
|
|
||||||
paraType = typ
|
|
||||||
} else if sType, ok := basicTypes[typ]; ok {
|
|
||||||
typeFormat := strings.Split(sType, ":")
|
|
||||||
paraType = typeFormat[0]
|
|
||||||
paraFormat = typeFormat[1]
|
|
||||||
} else {
|
|
||||||
beeLogger.Log.Warnf("[%s.%s] Unknown param type: %s\n", controllerName, funcName, typ)
|
|
||||||
}
|
|
||||||
if isArray {
|
|
||||||
para.Type = "array"
|
|
||||||
para.Items = &swagger.ParameterItems{
|
|
||||||
Type: paraType,
|
|
||||||
Format: paraFormat,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
para.Type = paraType
|
|
||||||
para.Format = paraFormat
|
|
||||||
}
|
}
|
||||||
|
setParamType(¶, typ, pkgpath, controllerName)
|
||||||
}
|
}
|
||||||
switch len(p) {
|
switch len(p) {
|
||||||
case 5:
|
case 5:
|
||||||
@ -636,7 +627,21 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if routerPath != "" {
|
if routerPath != "" {
|
||||||
|
//Go over function parameters which were not mapped and create swagger params for them
|
||||||
|
for name, typ := range funcParamMap {
|
||||||
|
para := swagger.Parameter{}
|
||||||
|
para.Name = name
|
||||||
|
setParamType(¶, typ, pkgpath, controllerName)
|
||||||
|
if paramInPath(name, routerPath) {
|
||||||
|
para.In = "path"
|
||||||
|
} else {
|
||||||
|
para.In = "query"
|
||||||
|
}
|
||||||
|
opts.Parameters = append(opts.Parameters, para)
|
||||||
|
}
|
||||||
|
|
||||||
var item *swagger.Item
|
var item *swagger.Item
|
||||||
if itemList, ok := controllerList[pkgpath+controllerName]; ok {
|
if itemList, ok := controllerList[pkgpath+controllerName]; ok {
|
||||||
if it, ok := itemList[routerPath]; !ok {
|
if it, ok := itemList[routerPath]; !ok {
|
||||||
@ -669,6 +674,91 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setParamType(para *swagger.Parameter, typ string, pkgpath, controllerName string) {
|
||||||
|
isArray := false
|
||||||
|
paraType := ""
|
||||||
|
paraFormat := ""
|
||||||
|
|
||||||
|
if strings.HasPrefix(typ, "[]") {
|
||||||
|
typ = typ[2:]
|
||||||
|
isArray = true
|
||||||
|
}
|
||||||
|
if typ == "string" || typ == "number" || typ == "integer" || typ == "boolean" ||
|
||||||
|
typ == "array" || typ == "file" {
|
||||||
|
paraType = typ
|
||||||
|
} else if sType, ok := basicTypes[typ]; ok {
|
||||||
|
typeFormat := strings.Split(sType, ":")
|
||||||
|
paraType = typeFormat[0]
|
||||||
|
paraFormat = typeFormat[1]
|
||||||
|
} else {
|
||||||
|
m, mod, realTypes := getModel(typ)
|
||||||
|
para.Schema = &swagger.Schema{
|
||||||
|
Ref: "#/definitions/" + m,
|
||||||
|
}
|
||||||
|
if _, ok := modelsList[pkgpath+controllerName]; !ok {
|
||||||
|
modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema)
|
||||||
|
}
|
||||||
|
modelsList[pkgpath+controllerName][typ] = mod
|
||||||
|
appendModels(pkgpath, controllerName, realTypes)
|
||||||
|
}
|
||||||
|
if isArray {
|
||||||
|
para.Type = "array"
|
||||||
|
para.Items = &swagger.ParameterItems{
|
||||||
|
Type: paraType,
|
||||||
|
Format: paraFormat,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
para.Type = paraType
|
||||||
|
para.Format = paraFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func paramInPath(name, route string) bool {
|
||||||
|
return strings.HasSuffix(route, ":"+name) ||
|
||||||
|
strings.Contains(route, ":"+name+"/")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFunctionParamType(t ast.Expr) string {
|
||||||
|
switch paramType := t.(type) {
|
||||||
|
case *ast.Ident:
|
||||||
|
return paramType.Name
|
||||||
|
// case *ast.Ellipsis:
|
||||||
|
// result := getFunctionParamType(paramType.Elt)
|
||||||
|
// result.array = true
|
||||||
|
// return result
|
||||||
|
case *ast.ArrayType:
|
||||||
|
return "[]" + getFunctionParamType(paramType.Elt)
|
||||||
|
case *ast.StarExpr:
|
||||||
|
return getFunctionParamType(paramType.X)
|
||||||
|
case *ast.SelectorExpr:
|
||||||
|
return getFunctionParamType(paramType.X) + "." + paramType.Sel.Name
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildParamMap(list *ast.FieldList) map[string]string {
|
||||||
|
i := 0
|
||||||
|
result := map[string]string{}
|
||||||
|
if list != nil {
|
||||||
|
funcParams := list.List
|
||||||
|
for _, fparam := range funcParams {
|
||||||
|
param := getFunctionParamType(fparam.Type)
|
||||||
|
var paramName string
|
||||||
|
if len(fparam.Names) > 0 {
|
||||||
|
paramName = fparam.Names[0].Name
|
||||||
|
} else {
|
||||||
|
paramName = fmt.Sprint(i)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
result[paramName] = param
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// analisys params return []string
|
// analisys params return []string
|
||||||
// @Param query form string true "The email for login"
|
// @Param query form string true "The email for login"
|
||||||
// [query form string true "The email for login"]
|
// [query form string true "The email for login"]
|
||||||
|
Loading…
Reference in New Issue
Block a user