optimized

This commit is contained in:
MaxToby 2021-01-16 11:53:17 +08:00
parent ce24620329
commit d06684494a
8 changed files with 141 additions and 21 deletions

View File

@ -10,6 +10,7 @@ import (
func Generator(ctx *cli.Context) error { func Generator(ctx *cli.Context) error {
pkg := ctx.String("package") pkg := ctx.String("package")
fileName := ctx.String("filename")
std, err := ioutil.ReadAll(os.Stdin) std, err := ioutil.ReadAll(os.Stdin)
if err != nil { if err != nil {
return err return err
@ -17,7 +18,11 @@ func Generator(ctx *cli.Context) error {
var plugin generate.Plugin var plugin generate.Plugin
plugin.ParentPackage = pkg plugin.ParentPackage = pkg
plugin.FileName = fileName
if len(plugin.FileName) == 0 {
plugin.FileName = "rest.swagger.json"
}
err = json.Unmarshal(std, &plugin) err = json.Unmarshal(std, &plugin)
if err != nil { if err != nil {
return err return err

View File

@ -1,3 +1,3 @@
package example package example
//go:generate goctl api plugin -plugin goctl-swagger="swagger" -api user.api -dir . //go:generate goctl api plugin -plugin goctl-swagger="swagger -filename user.json" -api user.api -dir .

View File

@ -14,13 +14,13 @@ type (
} }
// 登录请求 // 登录请求
LoginReq { LoginReq {
// 用户名
Username string `json:"username" desc:"用户名"` Username string `json:"username" desc:"用户名"`
Password string `json:"password"` //密码 Password string `json:"password"` //密码
} // 登录请求 } // 登录请求
UserInfoReq { UserInfoReq {
Id string `path:"id"` Id string `path:"id"` // 会员ID
Page string `form:"page,default=1"` //分页
} }
UserInfoReply { UserInfoReply {
@ -36,7 +36,8 @@ type (
} }
UserSearchReply { UserSearchReply {
KeyWord []UserInfoReply KeyWord []*UserInfoReply
KeyWords []*UserSearchReq
} }
) )

View File

@ -14,6 +14,7 @@ type (
Style string Style string
Dir string Dir string
ParentPackage string ParentPackage string
FileName string
} }
) )
@ -24,6 +25,9 @@ var (
"int32": reflect.Int, "int32": reflect.Int,
"int64": reflect.Int64, "int64": reflect.Int64,
"[]string": reflect.Slice, "[]string": reflect.Slice,
"[]int": reflect.Slice,
"[]int64": reflect.Slice,
"[]int32": reflect.Slice,
"bool": reflect.Bool, "bool": reflect.Bool,
"struct": reflect.Struct, "struct": reflect.Struct,
} }
@ -153,7 +157,6 @@ type schemaCore struct {
Example json.RawMessage `json:"example,omitempty"` Example json.RawMessage `json:"example,omitempty"`
Items *swaggerItemsObject `json:"items,omitempty"` Items *swaggerItemsObject `json:"items,omitempty"`
// If the item is an enumeration include a list of all the *NAMES* of the // If the item is an enumeration include a list of all the *NAMES* of the
// enum values. I'm not sure how well this will work but assuming all enums // enum values. I'm not sure how well this will work but assuming all enums
// start from 0 index it will be great. I don't think that is a good assumption. // start from 0 index it will be great. I don't think that is a good assumption.

View File

@ -21,7 +21,7 @@ func Do(in Plugin) error {
} }
output := in.Dir + "/rest.swagger.json" output := in.Dir + "/" + in.FileName
err = ioutil.WriteFile(output, formatted.Bytes(), 0666) err = ioutil.WriteFile(output, formatted.Bytes(), 0666)

View File

@ -15,6 +15,16 @@ var (
strColon = []byte(":") strColon = []byte(":")
) )
const (
defaultOption = "default"
stringOption = "string"
optionalOption = "optional"
optionsOption = "options"
rangeOption = "range"
optionSeparator = "|"
equalToken = "="
)
func applyGenerate(p Plugin) (*swaggerObject, error) { func applyGenerate(p Plugin) (*swaggerObject, error) {
s := swaggerObject{ s := swaggerObject{
@ -43,6 +53,7 @@ func applyGenerate(p Plugin) (*swaggerObject, error) {
renderServiceRoutes(p.Api.Service, p.Api.Service.Groups, s.Paths, requestResponseRefs) renderServiceRoutes(p.Api.Service, p.Api.Service.Groups, s.Paths, requestResponseRefs)
m := messageMap{} m := messageMap{}
renderReplyAsDefinition(s.Definitions, m, p.Api.Types, requestResponseRefs) renderReplyAsDefinition(s.Definitions, m, p.Api.Types, requestResponseRefs)
return &s, nil return &s, nil
} }
@ -70,19 +81,54 @@ func renderServiceRoutes(service spec.Service, groups []spec.Group, paths swagge
} }
} }
reqRef := fmt.Sprintf("#/definitions/%s", route.RequestType.Name) if strings.ToUpper(route.Method) == http.MethodGet {
if len(route.RequestType.Name) > 0 { for _, member := range route.RequestType.Members {
var schema = swaggerSchemaObject{ if strings.Contains(member.Tag, "path") {
schemaCore: schemaCore{ continue
Ref: reqRef, }
}, tempKind := swaggerMapTypes[strings.Replace(member.Type, "[]", "", -1)]
ftype, format, ok := primitiveSchema(tempKind, member.Type)
if !ok {
ftype = tempKind.String()
format = "UNKNOWN"
}
sp := swaggerParameterObject{In: "query", Type: ftype, Format: format}
for _, tag := range member.Tags() {
sp.Name = tag.Name
if len(tag.Options) == 0 {
sp.Required = true
continue
}
for _, option := range tag.Options {
if strings.HasPrefix(option, defaultOption) {
segs := strings.Split(option, equalToken)
if len(segs) == 2 {
sp.Default = segs[1]
}
} else if !strings.HasPrefix(option, optionalOption) {
sp.Required = true
}
}
}
parameters = append(parameters, sp)
}
} else {
reqRef := fmt.Sprintf("#/definitions/%s", route.RequestType.Name)
if len(route.RequestType.Name) > 0 {
var schema = swaggerSchemaObject{
schemaCore: schemaCore{
Ref: reqRef,
},
}
parameters = append(parameters, swaggerParameterObject{
Name: "body",
In: "body",
Required: true,
Schema: &schema,
})
} }
parameters = append(parameters, swaggerParameterObject{
Name: "body",
In: "body",
Required: true,
Schema: &schema,
})
} }
pathItemObject, ok := paths[path] pathItemObject, ok := paths[path]
@ -172,7 +218,25 @@ func renderReplyAsDefinition(d swaggerDefinitionsObject, m messageMap, p []spec.
schema.Properties = &swaggerSchemaObjectProperties{} schema.Properties = &swaggerSchemaObjectProperties{}
} }
*schema.Properties = append(*schema.Properties, kv) *schema.Properties = append(*schema.Properties, kv)
for _, tag := range member.Tags() {
if len(tag.Options) == 0 {
schema.Required = append(schema.Required, tag.Name)
continue
}
for _, option := range tag.Options {
switch {
case !strings.HasPrefix(option, optionalOption):
if !contains(schema.Required, tag.Name) {
schema.Required = append(schema.Required, tag.Name)
}
case strings.HasPrefix(option, defaultOption):
case strings.HasPrefix(option, optionsOption):
}
}
}
} }
d[i2.Name] = schema d[i2.Name] = schema
} }
@ -182,18 +246,32 @@ func schemaOfField(member spec.Member) swaggerSchemaObject {
ret := swaggerSchemaObject{} ret := swaggerSchemaObject{}
var core schemaCore var core schemaCore
//spew.Dump(member)
kind := swaggerMapTypes[member.Type] kind := swaggerMapTypes[member.Type]
var props *swaggerSchemaObjectProperties var props *swaggerSchemaObjectProperties
comment := member.GetComment()
comment = strings.Replace(comment, "//", "", -1)
switch ft := kind; ft { switch ft := kind; ft {
case reflect.Invalid: //[]Struct 也有可能是 Struct case reflect.Invalid: //[]Struct 也有可能是 Struct
// []Struct // []Struct
//map[ArrayType:map[Star:map[StringExpr:UserSearchReq] StringExpr:*UserSearchReq] StringExpr:[]*UserSearchReq]
refTypeName := strings.Replace(member.Type, "[", "", 1) refTypeName := strings.Replace(member.Type, "[", "", 1)
refTypeName = strings.Replace(refTypeName, "]", "", 1) refTypeName = strings.Replace(refTypeName, "]", "", 1)
refTypeName = strings.Replace(refTypeName, "*", "", 1)
core = schemaCore{ core = schemaCore{
Ref: "#/definitions/" + refTypeName, Ref: "#/definitions/" + refTypeName,
} }
case reflect.Slice:
tempKind := swaggerMapTypes[strings.Replace(member.Type, "[]", "", -1)]
ftype, format, ok := primitiveSchema(tempKind, member.Type)
if ok {
core = schemaCore{Type: ftype, Format: format}
} else {
core = schemaCore{Type: ft.String(), Format: "UNKNOWN"}
}
default: default:
ftype, format, ok := primitiveSchema(ft, member.Type) ftype, format, ok := primitiveSchema(ft, member.Type)
if ok { if ok {
@ -221,7 +299,6 @@ func schemaOfField(member spec.Member) swaggerSchemaObject {
}, },
} }
} else { } else {
ret = swaggerSchemaObject{ ret = swaggerSchemaObject{
schemaCore: core, schemaCore: core,
Properties: props, Properties: props,
@ -233,6 +310,24 @@ func schemaOfField(member spec.Member) swaggerSchemaObject {
Properties: props, Properties: props,
} }
} }
ret.Description = comment
for _, tag := range member.Tags() {
if len(tag.Options) == 0 {
continue
}
for _, option := range tag.Options {
switch {
case strings.HasPrefix(option, defaultOption):
segs := strings.Split(option, equalToken)
if len(segs) == 2 {
ret.Default = segs[1]
}
case strings.HasPrefix(option, optionsOption):
}
}
}
return ret return ret
} }
@ -271,3 +366,12 @@ func countParams(path string) uint16 {
n += uint16(bytes.Count(s, strColon)) n += uint16(bytes.Count(s, strColon))
return n return n
} }
func contains(s []string, str string) bool {
for _, v := range s {
if v == str {
return true
}
}
return false
}

2
go.sum
View File

@ -250,7 +250,9 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=

View File

@ -15,7 +15,12 @@ var (
Name: "swagger", Name: "swagger",
Usage: "generates swagger.json", Usage: "generates swagger.json",
Action: action.Generator, Action: action.Generator,
Flags: []cli.Flag{}, Flags: []cli.Flag{
&cli.StringFlag{
Name: "filename",
Usage: "swagger save file name",
},
},
}, },
} }
) )