(goctl): support nested struct (#4211)

This commit is contained in:
kesonan
2024-06-25 23:18:15 +08:00
committed by GitHub
parent 4ec9cac82b
commit a012a9138f
28 changed files with 318 additions and 76 deletions

View File

@@ -57,6 +57,8 @@ var (
importTwiceApi string
//go:embed testdata/another_import_api.api
anotherImportApi string
//go:embed testdata/example.api
exampleApi string
)
func TestParser(t *testing.T) {
@@ -316,15 +318,32 @@ func TestCamelStyle(t *testing.T) {
validateWithCamel(t, filename, "GoZero")
}
func TestExampleGen(t *testing.T) {
env.Set(t, env.GoctlExperimental, env.ExperimentalOn)
filename := "greet.api"
err := os.WriteFile(filename, []byte(exampleApi), os.ModePerm)
assert.Nil(t, err)
t.Cleanup(func() {
_ = os.Remove(filename)
})
spec, err := parser.Parse(filename)
assert.Nil(t, err)
assert.Equal(t, len(spec.Types), 10)
validate(t, filename)
}
func validate(t *testing.T, api string) {
validateWithCamel(t, api, "gozero")
}
func validateWithCamel(t *testing.T, api, camel string) {
dir := "workspace"
defer func() {
os.RemoveAll(dir)
}()
t.Cleanup(func() {
_ = os.RemoveAll(dir)
})
err := pathx.MkdirIfNotExist(dir)
assert.Nil(t, err)
err = initMod(dir)

View File

@@ -74,8 +74,21 @@ func writeType(writer io.Writer, tp spec.Type) error {
return fmt.Errorf("unspport struct type: %s", tp.Name())
}
fmt.Fprintf(writer, "type %s struct {\n", util.Title(tp.Name()))
for _, member := range structType.Members {
_, err := fmt.Fprintf(writer, "type %s struct {\n", util.Title(tp.Name()))
if err != nil {
return err
}
if err := writeMember(writer, structType.Members); err != nil {
return err
}
_, err = fmt.Fprintf(writer, "}")
return err
}
func writeMember(writer io.Writer, members []spec.Member) error {
for _, member := range members {
if member.IsInline {
if _, err := fmt.Fprintf(writer, "%s\n", strings.Title(member.Type.Name())); err != nil {
return err
@@ -88,6 +101,5 @@ func writeType(writer io.Writer, tp spec.Type) error {
return err
}
}
fmt.Fprintf(writer, "}")
return nil
}

View File

@@ -0,0 +1,99 @@
syntax = "v1"
info(
title: "demo title"
desc: "demo desc"
author: "keson.an"
date: "2024-06-25"
version: "v1"
)
// empty structure
type Foo {
}
// type lit
type Bar {
Foo int `json:"foo"`
Bar bool `json:"bar"`
Baz []string `json:"baz"`
Qux map[string]string `json:"qux"`
}
type Baz {
Foo `json:"foo"`
// array type
Arr [2]int `json:"arr"`
// nested type
Bar {
Foo string `json:"foo"`
Bar bool `json:"bar"`
Baz {
Foo string `json:"foo"`
Bar bool `json:"bar"`
}
Qux {
Foo string `json:"foo"`
Bar bool `json:"bar"`
} `json:"qux"`
} `json:"bar"`
}
type UpdateReq {
Arg1 string `json:"arg1"`
}
type ListItem {
Value1 string `json:"value1"`
}
type LoginReq {
Username string `json:"username"`
Password string `json:"password"`
}
type LoginResp {
Name string `json:"name"`
}
type FormExampleReq {
Name string `form:"name"`
}
type PathExampleReq {
ID string `path:"id"`
}
type PathExampleResp {
Name string `json:"name"`
}
@server(
jwt: Auth
prefix: /v1
group: g1
timeout: 3s
middleware: AuthInterceptor
maxBytes: 1048576
)
service Foo {
@handler ping
get /ping
@handler update
post /update (UpdateReq)
@handler list
get /list returns ([]ListItem)
@handler login
post /login (LoginReq) returns (LoginResp)
@handler formExample
post /form/example (FormExampleReq)
@handler pathExample
get /path/example/:id (PathExampleReq) returns (PathExampleResp)
}

View File

@@ -59,16 +59,59 @@ func genFile(c fileGenConfig) error {
func writeProperty(writer io.Writer, name, tag, comment string, tp spec.Type, indent int) error {
util.WriteIndent(writer, indent)
var err error
var (
err error
isNestedStruct bool
)
structType, ok := tp.(spec.DefineStruct)
if ok && structType.IsNestedStruct() {
isNestedStruct = true
}
if len(comment) > 0 {
comment = strings.TrimPrefix(comment, "//")
comment = "//" + comment
_, err = fmt.Fprintf(writer, "%s %s %s %s\n", strings.Title(name), tp.Name(), tag, comment)
} else {
_, err = fmt.Fprintf(writer, "%s %s %s\n", strings.Title(name), tp.Name(), tag)
}
return err
if isNestedStruct {
_, err = fmt.Fprintf(writer, "%s struct {\n", strings.Title(name))
if err != nil {
return err
}
if err := writeMember(writer, structType.Members); err != nil {
return err
}
_, err := fmt.Fprintf(writer, "} %s", tag)
if err != nil {
return err
}
if len(comment) > 0 {
_, err = fmt.Fprintf(writer, " %s", comment)
if err != nil {
return err
}
}
_, err = fmt.Fprint(writer, "\n")
if err != nil {
return err
}
} else {
if len(comment) > 0 {
_, err = fmt.Fprintf(writer, "%s %s %s %s\n", strings.Title(name), tp.Name(), tag, comment)
if err != nil {
return err
}
} else {
_, err = fmt.Fprintf(writer, "%s %s %s\n", strings.Title(name), tp.Name(), tag)
if err != nil {
return err
}
}
}
return nil
}
func getAuths(api *spec.ApiSpec) []string {