mirror of
https://github.com/beego/bee.git
synced 2024-11-25 20:10:55 +00:00
bee support swagger2.0
This commit is contained in:
parent
e2cd28d5f5
commit
d9f182c84f
185
g_docs.go
185
g_docs.go
@ -45,7 +45,7 @@ const (
|
|||||||
var pkgCache map[string]struct{} //pkg:controller:function:comments comments: key:value
|
var pkgCache map[string]struct{} //pkg:controller:function:comments comments: key:value
|
||||||
var controllerComments map[string]string
|
var controllerComments map[string]string
|
||||||
var importlist map[string]string
|
var importlist map[string]string
|
||||||
var controllerList map[string]map[string]swagger.Item //controllername Paths items
|
var controllerList map[string]map[string]*swagger.Item //controllername Paths items
|
||||||
var modelsList map[string]map[string]swagger.Schema
|
var modelsList map[string]map[string]swagger.Schema
|
||||||
var rootapi swagger.Swagger
|
var rootapi swagger.Swagger
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ func init() {
|
|||||||
pkgCache = make(map[string]struct{})
|
pkgCache = make(map[string]struct{})
|
||||||
controllerComments = make(map[string]string)
|
controllerComments = make(map[string]string)
|
||||||
importlist = make(map[string]string)
|
importlist = make(map[string]string)
|
||||||
controllerList = make(map[string]map[string]swagger.Item)
|
controllerList = make(map[string]map[string]*swagger.Item)
|
||||||
modelsList = make(map[string]map[string]swagger.Schema)
|
modelsList = make(map[string]map[string]swagger.Schema)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,6 +91,7 @@ func generateDocs(curpath string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// analisys controller package
|
||||||
for _, im := range f.Imports {
|
for _, im := range f.Imports {
|
||||||
localName := ""
|
localName := ""
|
||||||
if im.Name != nil {
|
if im.Name != nil {
|
||||||
@ -102,33 +103,41 @@ func generateDocs(curpath string) {
|
|||||||
switch specDecl := d.(type) {
|
switch specDecl := d.(type) {
|
||||||
case *ast.FuncDecl:
|
case *ast.FuncDecl:
|
||||||
for _, l := range specDecl.Body.List {
|
for _, l := range specDecl.Body.List {
|
||||||
switch smtp := l.(type) {
|
switch stmt := l.(type) {
|
||||||
case *ast.AssignStmt:
|
case *ast.AssignStmt:
|
||||||
for _, l := range smtp.Rhs {
|
for _, l := range stmt.Rhs {
|
||||||
if v, ok := l.(*ast.CallExpr); ok {
|
if v, ok := l.(*ast.CallExpr); ok {
|
||||||
f, params := analisysNewNamespace(v)
|
// analisys NewNamespace, it will return version and the subfunction
|
||||||
globalDocsTemplate = strings.Replace(globalDocsTemplate, "{{.version}}", f, -1)
|
version, params := analisysNewNamespace(v)
|
||||||
|
rootapi.BasePath = version
|
||||||
for _, p := range params {
|
for _, p := range params {
|
||||||
switch pp := p.(type) {
|
switch pp := p.(type) {
|
||||||
case *ast.CallExpr:
|
case *ast.CallExpr:
|
||||||
|
controllerName := ""
|
||||||
if selname := pp.Fun.(*ast.SelectorExpr).Sel.String(); selname == "NSNamespace" {
|
if selname := pp.Fun.(*ast.SelectorExpr).Sel.String(); selname == "NSNamespace" {
|
||||||
s, params := analisysNewNamespace(pp)
|
s, params := analisysNewNamespace(pp)
|
||||||
subapi := swagger.APIRef{Path: s}
|
|
||||||
controllerName := ""
|
|
||||||
for _, sp := range params {
|
for _, sp := range params {
|
||||||
switch pp := sp.(type) {
|
switch pp := sp.(type) {
|
||||||
case *ast.CallExpr:
|
case *ast.CallExpr:
|
||||||
if pp.Fun.(*ast.SelectorExpr).Sel.String() == "NSInclude" {
|
if pp.Fun.(*ast.SelectorExpr).Sel.String() == "NSInclude" {
|
||||||
controllerName = analisysNSInclude(s, pp)
|
controllerName = analisysNSInclude(s, pp)
|
||||||
|
if v, ok := controllerComments[controllerName]; ok {
|
||||||
|
rootapi.Tags = append(rootapi.Tags, swagger.Tag{
|
||||||
|
Name: s,
|
||||||
|
Description: v,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if v, ok := controllerComments[controllerName]; ok {
|
|
||||||
subapi.Description = v
|
|
||||||
}
|
|
||||||
rootapi.APIs = append(rootapi.APIs, subapi)
|
|
||||||
} else if selname == "NSInclude" {
|
} else if selname == "NSInclude" {
|
||||||
analisysNSInclude(f, pp)
|
controllerName = analisysNSInclude("", 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,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,6 +161,7 @@ func generateDocs(curpath string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return version and the others params
|
||||||
func analisysNewNamespace(ce *ast.CallExpr) (first string, others []ast.Expr) {
|
func analisysNewNamespace(ce *ast.CallExpr) (first string, others []ast.Expr) {
|
||||||
for i, p := range ce.Args {
|
for i, p := range ce.Args {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
@ -168,32 +178,45 @@ func analisysNewNamespace(ce *ast.CallExpr) (first string, others []ast.Expr) {
|
|||||||
|
|
||||||
func analisysNSInclude(baseurl string, ce *ast.CallExpr) string {
|
func analisysNSInclude(baseurl string, ce *ast.CallExpr) string {
|
||||||
cname := ""
|
cname := ""
|
||||||
a := &swagger.APIDeclaration{}
|
|
||||||
a.APIVersion = rootapi.APIVersion
|
|
||||||
a.SwaggerVersion = swagger.SwaggerVersion
|
|
||||||
a.ResourcePath = baseurl
|
|
||||||
a.Produces = []string{"application/json", "application/xml", "text/plain", "text/html"}
|
|
||||||
a.APIs = make([]swagger.API, 0)
|
|
||||||
a.Models = make(map[string]swagger.Model)
|
|
||||||
for _, p := range ce.Args {
|
for _, p := range ce.Args {
|
||||||
x := p.(*ast.UnaryExpr).X.(*ast.CompositeLit).Type.(*ast.SelectorExpr)
|
x := p.(*ast.UnaryExpr).X.(*ast.CompositeLit).Type.(*ast.SelectorExpr)
|
||||||
if v, ok := importlist[fmt.Sprint(x.X)]; ok {
|
if v, ok := importlist[fmt.Sprint(x.X)]; ok {
|
||||||
cname = v + x.Sel.Name
|
cname = v + x.Sel.Name
|
||||||
}
|
}
|
||||||
if apis, ok := controllerList[cname]; ok {
|
if apis, ok := controllerList[cname]; ok {
|
||||||
if len(a.APIs) > 0 {
|
for rt, item := range apis {
|
||||||
a.APIs = append(a.APIs, apis...)
|
tag := ""
|
||||||
} else {
|
if baseurl != "" {
|
||||||
a.APIs = apis
|
rt = "/" + baseurl + rt
|
||||||
}
|
tag = baseurl
|
||||||
}
|
} else {
|
||||||
if models, ok := modelsList[cname]; ok {
|
tag = cname
|
||||||
for _, m := range models {
|
}
|
||||||
a.Models[m.ID] = m
|
if item.Get != nil {
|
||||||
|
item.Get.Tags = []string{tag}
|
||||||
|
}
|
||||||
|
if item.Post != nil {
|
||||||
|
item.Post.Tags = []string{tag}
|
||||||
|
}
|
||||||
|
if item.Put != nil {
|
||||||
|
item.Put.Tags = []string{tag}
|
||||||
|
}
|
||||||
|
if item.Patch != nil {
|
||||||
|
item.Patch.Tags = []string{tag}
|
||||||
|
}
|
||||||
|
if item.Head != nil {
|
||||||
|
item.Head.Tags = []string{tag}
|
||||||
|
}
|
||||||
|
if item.Delete != nil {
|
||||||
|
item.Delete.Tags = []string{tag}
|
||||||
|
}
|
||||||
|
if item.Options != nil {
|
||||||
|
item.Options.Tags = []string{tag}
|
||||||
|
}
|
||||||
|
rootapi.Paths[rt] = item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
apilist[baseurl] = a
|
|
||||||
return cname
|
return cname
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,9 +251,8 @@ func analisyscontrollerPkg(localName, pkgpath string) {
|
|||||||
if pkgRealpath != "" {
|
if pkgRealpath != "" {
|
||||||
if _, ok := pkgCache[pkgpath]; ok {
|
if _, ok := pkgCache[pkgpath]; ok {
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
pkgCache[pkgpath] = struct{}{}
|
|
||||||
}
|
}
|
||||||
|
pkgCache[pkgpath] = struct{}{}
|
||||||
} else {
|
} else {
|
||||||
ColorLog("[ERRO] the %s pkg not exist in gopath\n", pkgpath)
|
ColorLog("[ERRO] the %s pkg not exist in gopath\n", pkgpath)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -263,7 +285,9 @@ func analisyscontrollerPkg(localName, pkgpath string) {
|
|||||||
case *ast.StructType:
|
case *ast.StructType:
|
||||||
_ = tp.Struct
|
_ = tp.Struct
|
||||||
//parse controller definition comments
|
//parse controller definition comments
|
||||||
controllerComments[pkgpath+s.(*ast.TypeSpec).Name.String()] = specDecl.Doc.Text()
|
if strings.TrimSpace(specDecl.Doc.Text()) != "" {
|
||||||
|
controllerComments[pkgpath+s.(*ast.TypeSpec).Name.String()] = specDecl.Doc.Text()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -294,7 +318,8 @@ func isSystemPackage(pkgpath string) bool {
|
|||||||
|
|
||||||
// parse the func comments
|
// parse the func comments
|
||||||
func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpath string) error {
|
func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpath string) error {
|
||||||
innerapi := swagger.Item{}
|
var routerPath string
|
||||||
|
var HTTPMethod string
|
||||||
opts := swagger.Operation{}
|
opts := swagger.Operation{}
|
||||||
if comments != nil && comments.List != nil {
|
if comments != nil && comments.List != nil {
|
||||||
for _, c := range comments.List {
|
for _, c := range comments.List {
|
||||||
@ -305,20 +330,20 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
if len(e1) < 1 {
|
if len(e1) < 1 {
|
||||||
return errors.New("you should has router infomation")
|
return errors.New("you should has router infomation")
|
||||||
}
|
}
|
||||||
innerapi.Path = e1[0]
|
routerPath = e1[0]
|
||||||
if len(e1) == 2 && e1[1] != "" {
|
if len(e1) == 2 && e1[1] != "" {
|
||||||
e1 = strings.SplitN(e1[1], " ", 2)
|
e1 = strings.SplitN(e1[1], " ", 2)
|
||||||
opts.HTTPMethod = strings.ToUpper(strings.Trim(e1[0], "[]"))
|
HTTPMethod = strings.ToUpper(strings.Trim(e1[0], "[]"))
|
||||||
} else {
|
} else {
|
||||||
opts.HTTPMethod = "GET"
|
HTTPMethod = "GET"
|
||||||
}
|
}
|
||||||
} else if strings.HasPrefix(t, "@Title") {
|
} else if strings.HasPrefix(t, "@Title") {
|
||||||
opts.Nickname = strings.TrimSpace(t[len("@Title"):])
|
opts.OperationID = controllerName + "." + strings.TrimSpace(t[len("@Title"):])
|
||||||
} else if strings.HasPrefix(t, "@Description") {
|
} else if strings.HasPrefix(t, "@Description") {
|
||||||
opts.Summary = strings.TrimSpace(t[len("@Description"):])
|
opts.Summary = strings.TrimSpace(t[len("@Description"):])
|
||||||
} else if strings.HasPrefix(t, "@Success") {
|
} else if strings.HasPrefix(t, "@Success") {
|
||||||
ss := strings.TrimSpace(t[len("@Success"):])
|
ss := strings.TrimSpace(t[len("@Success"):])
|
||||||
rs := swagger.ResponseMessage{}
|
rs := swagger.Response{}
|
||||||
st := make([]string, 3)
|
st := make([]string, 3)
|
||||||
j := 0
|
j := 0
|
||||||
var tmp []rune
|
var tmp []rune
|
||||||
@ -350,7 +375,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
if len(tmp) > 0 && st[2] == "" {
|
if len(tmp) > 0 && st[2] == "" {
|
||||||
st[2] = strings.TrimSpace(string(tmp))
|
st[2] = strings.TrimSpace(string(tmp))
|
||||||
}
|
}
|
||||||
rs.Message = st[2]
|
rs.Description = st[2]
|
||||||
if st[1] == "{object}" {
|
if st[1] == "{object}" {
|
||||||
if st[2] == "" {
|
if st[2] == "" {
|
||||||
panic(controllerName + " " + funcName + " has no object")
|
panic(controllerName + " " + funcName + " has no object")
|
||||||
@ -358,16 +383,14 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
cmpath, m, mod, realTypes := getModel(st[2])
|
cmpath, m, mod, realTypes := getModel(st[2])
|
||||||
//ll := strings.Split(st[2], ".")
|
//ll := strings.Split(st[2], ".")
|
||||||
//opts.Type = ll[len(ll)-1]
|
//opts.Type = ll[len(ll)-1]
|
||||||
rs.ResponseModel = m
|
rs.Ref = "#/definitions/" + m
|
||||||
if _, ok := modelsList[pkgpath+controllerName]; !ok {
|
if _, ok := modelsList[pkgpath+controllerName]; !ok {
|
||||||
modelsList[pkgpath+controllerName] = make(map[string]swagger.Model, 0)
|
modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema, 0)
|
||||||
}
|
}
|
||||||
modelsList[pkgpath+controllerName][st[2]] = mod
|
modelsList[pkgpath+controllerName][st[2]] = mod
|
||||||
appendModels(cmpath, pkgpath, controllerName, realTypes)
|
appendModels(cmpath, pkgpath, controllerName, realTypes)
|
||||||
}
|
}
|
||||||
|
opts.Responses[st[0]] = rs
|
||||||
rs.Code, _ = strconv.Atoi(st[0])
|
|
||||||
opts.ResponseMessages = append(opts.ResponseMessages, rs)
|
|
||||||
} else if strings.HasPrefix(t, "@Param") {
|
} else if strings.HasPrefix(t, "@Param") {
|
||||||
para := swagger.Parameter{}
|
para := swagger.Parameter{}
|
||||||
p := getparams(strings.TrimSpace(t[len("@Param "):]))
|
p := getparams(strings.TrimSpace(t[len("@Param "):]))
|
||||||
@ -375,9 +398,10 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
panic(controllerName + "_" + funcName + "'s comments @Param at least should has 4 params")
|
panic(controllerName + "_" + funcName + "'s comments @Param at least should has 4 params")
|
||||||
}
|
}
|
||||||
para.Name = p[0]
|
para.Name = p[0]
|
||||||
para.ParamType = p[1]
|
para.In = p[1]
|
||||||
pp := strings.Split(p[2], ".")
|
pp := strings.Split(p[2], ".")
|
||||||
para.DataType = pp[len(pp)-1]
|
//@TODO models.Objects need to ref
|
||||||
|
para.Type = pp[len(pp)-1]
|
||||||
if len(p) > 4 {
|
if len(p) > 4 {
|
||||||
para.Required, _ = strconv.ParseBool(p[3])
|
para.Required, _ = strconv.ParseBool(p[3])
|
||||||
para.Description = p[4]
|
para.Description = p[4]
|
||||||
@ -386,14 +410,14 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
}
|
}
|
||||||
opts.Parameters = append(opts.Parameters, para)
|
opts.Parameters = append(opts.Parameters, para)
|
||||||
} else if strings.HasPrefix(t, "@Failure") {
|
} else if strings.HasPrefix(t, "@Failure") {
|
||||||
rs := swagger.ResponseMessage{}
|
rs := swagger.Response{}
|
||||||
st := strings.TrimSpace(t[len("@Failure"):])
|
st := strings.TrimSpace(t[len("@Failure"):])
|
||||||
var cd []rune
|
var cd []rune
|
||||||
var start bool
|
var start bool
|
||||||
for i, s := range st {
|
for i, s := range st {
|
||||||
if unicode.IsSpace(s) {
|
if unicode.IsSpace(s) {
|
||||||
if start {
|
if start {
|
||||||
rs.Message = strings.TrimSpace(st[i+1:])
|
rs.Description = strings.TrimSpace(st[i+1:])
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
continue
|
continue
|
||||||
@ -402,10 +426,9 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
start = true
|
start = true
|
||||||
cd = append(cd, s)
|
cd = append(cd, s)
|
||||||
}
|
}
|
||||||
rs.Code, _ = strconv.Atoi(string(cd))
|
opts.Responses[string(cd)] = rs
|
||||||
opts.ResponseMessages = append(opts.ResponseMessages, rs)
|
} else if strings.HasPrefix(t, "@Deprecated") {
|
||||||
} else if strings.HasPrefix(t, "@Type") {
|
opts.Deprecated, _ = strconv.ParseBool(strings.TrimSpace(t[len("@Deprecated"):]))
|
||||||
opts.Type = strings.TrimSpace(t[len("@Type"):])
|
|
||||||
} else if strings.HasPrefix(t, "@Accept") {
|
} else if strings.HasPrefix(t, "@Accept") {
|
||||||
accepts := strings.Split(strings.TrimSpace(strings.TrimSpace(t[len("@Accept"):])), ",")
|
accepts := strings.Split(strings.TrimSpace(strings.TrimSpace(t[len("@Accept"):])), ",")
|
||||||
for _, a := range accepts {
|
for _, a := range accepts {
|
||||||
@ -427,14 +450,35 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
innerapi.Operations = append(innerapi.Operations, opts)
|
if routerPath != "" {
|
||||||
if innerapi.Path != "" {
|
var item *swagger.Item
|
||||||
if _, ok := controllerList[pkgpath+controllerName]; ok {
|
if itemList, ok := controllerList[pkgpath+controllerName]; ok {
|
||||||
controllerList[pkgpath+controllerName] = append(controllerList[pkgpath+controllerName], innerapi)
|
if it, ok := itemList[routerPath]; !ok {
|
||||||
|
item = &swagger.Item{}
|
||||||
|
} else {
|
||||||
|
item = it
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
controllerList[pkgpath+controllerName] = make([]swagger.API, 1)
|
controllerList[pkgpath+controllerName] = make(map[string]*swagger.Item)
|
||||||
controllerList[pkgpath+controllerName][0] = innerapi
|
item = &swagger.Item{}
|
||||||
}
|
}
|
||||||
|
switch HTTPMethod {
|
||||||
|
case "GET":
|
||||||
|
item.Get = &opts
|
||||||
|
case "POST":
|
||||||
|
item.Post = &opts
|
||||||
|
case "PUT":
|
||||||
|
item.Put = &opts
|
||||||
|
case "PATCH":
|
||||||
|
item.Patch = &opts
|
||||||
|
case "DELETE":
|
||||||
|
item.Delete = &opts
|
||||||
|
case "Head":
|
||||||
|
item.Head = &opts
|
||||||
|
case "OPTIONS":
|
||||||
|
item.Options = &opts
|
||||||
|
}
|
||||||
|
controllerList[pkgpath+controllerName][routerPath] = item
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -470,7 +514,7 @@ func getparams(str string) []string {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func getModel(str string) (pkgpath, objectname string, m swagger.Model, realTypes []string) {
|
func getModel(str string) (pkgpath, objectname string, m swagger.Schema, realTypes []string) {
|
||||||
strs := strings.Split(str, ".")
|
strs := strings.Split(str, ".")
|
||||||
objectname = strs[len(strs)-1]
|
objectname = strs[len(strs)-1]
|
||||||
pkgpath = strings.Join(strs[:len(strs)-1], "/")
|
pkgpath = strings.Join(strs[:len(strs)-1], "/")
|
||||||
@ -503,21 +547,25 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Model, realType
|
|||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
m.ID = k
|
m.Title = k
|
||||||
if st.Fields.List != nil {
|
if st.Fields.List != nil {
|
||||||
m.Properties = make(map[string]swagger.ModelProperty)
|
m.Properties = make(map[string]swagger.Propertie)
|
||||||
for _, field := range st.Fields.List {
|
for _, field := range st.Fields.List {
|
||||||
isSlice, realType := typeAnalyser(field)
|
isSlice, realType := typeAnalyser(field)
|
||||||
realTypes = append(realTypes, realType)
|
realTypes = append(realTypes, realType)
|
||||||
mp := swagger.ModelProperty{}
|
mp := swagger.Propertie{}
|
||||||
// add type slice
|
// add type slice
|
||||||
if isSlice {
|
if isSlice {
|
||||||
|
mp.Type = "array"
|
||||||
|
mp.Properties = make(map[string]swagger.Propertie)
|
||||||
if isBasicType(realType) {
|
if isBasicType(realType) {
|
||||||
mp.Type = "[]" + realType
|
mp.Properties["items"] = swagger.Propertie{
|
||||||
|
Type: realType,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mp.Type = "array"
|
mp.Properties["items"] = swagger.Propertie{
|
||||||
mp.Items = make(map[string]string)
|
Ref: "#/definitions/" + realType,
|
||||||
mp.Items["$ref"] = realType
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mp.Type = realType
|
mp.Type = realType
|
||||||
@ -577,10 +625,11 @@ func getModel(str string) (pkgpath, objectname string, m swagger.Model, realType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if m.ID == "" {
|
if m.Title == "" {
|
||||||
ColorLog("can't find the object: %v", str)
|
ColorLog("can't find the object: %v", str)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
rootapi.Definitions[objectname] = m
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user