type should not define nested (#212)

* nest type should not supported

* nest type should not supported

* nest type should not supported

* nest type should not supported

* new test

* new test
This commit is contained in:
kingxt 2020-11-17 18:08:55 +08:00 committed by GitHub
parent 9592639cb4
commit d6d8fc21d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 29 deletions

View File

@ -11,10 +11,18 @@ import (
"strings"
"github.com/tal-tech/go-zero/core/errorx"
"github.com/tal-tech/go-zero/tools/goctl/api/parser"
"github.com/tal-tech/go-zero/tools/goctl/api/util"
"github.com/urfave/cli"
)
const (
leftParenthesis = "("
rightParenthesis = ")"
leftBrace = "{"
rightBrace = "}"
)
func GoFormatApi(c *cli.Context) error {
useStdin := c.Bool("stdin")
@ -57,7 +65,10 @@ func ApiFormatByStdin() error {
return err
}
result := apiFormat(string(data))
result, err := apiFormat(string(data))
if err != nil {
return err
}
_, err = fmt.Print(result)
if err != nil {
@ -72,28 +83,44 @@ func ApiFormatByPath(apiFilePath string) error {
return err
}
result := apiFormat(string(data))
result, err := apiFormat(string(data))
if err != nil {
return err
}
if err := ioutil.WriteFile(apiFilePath, []byte(result), os.ModePerm); err != nil {
return err
}
return nil
}
func apiFormat(data string) string {
func apiFormat(data string) (string, error) {
_, err := parser.ParseApi(data)
if err != nil {
return "", err
}
var builder strings.Builder
scanner := bufio.NewScanner(strings.NewReader(data))
s := bufio.NewScanner(strings.NewReader(data))
var tapCount = 0
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
for s.Scan() {
line := strings.TrimSpace(s.Text())
noCommentLine := util.RemoveComment(line)
if noCommentLine == ")" || noCommentLine == "}" {
if noCommentLine == rightParenthesis || noCommentLine == rightBrace {
tapCount -= 1
}
if tapCount < 0 {
line = strings.TrimSuffix(line, rightBrace)
line = strings.TrimSpace(line)
if strings.HasSuffix(line, leftBrace) {
tapCount += 1
}
}
util.WriteIndent(&builder, tapCount)
builder.WriteString(line + "\n")
if strings.HasSuffix(noCommentLine, "(") || strings.HasSuffix(noCommentLine, "{") {
if strings.HasSuffix(noCommentLine, leftParenthesis) || strings.HasSuffix(noCommentLine, leftBrace) {
tapCount += 1
}
}
return strings.TrimSpace(builder.String())
return strings.TrimSpace(builder.String()), nil
}

View File

@ -41,6 +41,7 @@ service A-api {
)
func TestInlineTypeNotExist(t *testing.T) {
r := apiFormat(notFormattedStr)
r, err := apiFormat(notFormattedStr)
assert.Nil(t, err)
assert.Equal(t, r, formattedStr)
}

View File

@ -288,13 +288,16 @@ type Request {
Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
}
type XXX {
}
type XXX {}
type (
Response {
Message string ` + "`" + `json:"message"` + "`" + `
}
A {}
B struct {}
)
service A-api {
@ -303,6 +306,19 @@ service A-api {
}
`
const nestTypeApi = `
type Request {
Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
XXX struct {
}
}
service A-api {
@handler GreetHandler
get /greet/from/:name(Request)
}
`
func TestParser(t *testing.T) {
filename := "greet.api"
err := ioutil.WriteFile(filename, []byte(testApiTemplate), os.ModePerm)
@ -532,11 +548,21 @@ func TestNoStructApi(t *testing.T) {
spec, err := parser.Parse()
assert.Nil(t, err)
assert.Equal(t, len(spec.Types), 3)
assert.Equal(t, len(spec.Types), 5)
validate(t, filename)
}
func TestNestTypeApi(t *testing.T) {
filename := "greet.api"
err := ioutil.WriteFile(filename, []byte(nestTypeApi), os.ModePerm)
assert.Nil(t, err)
defer os.Remove(filename)
_, err = parser.NewParser(filename)
assert.NotNil(t, err)
}
func validate(t *testing.T, api string) {
dir := "_go"
os.RemoveAll(dir)

View File

@ -154,6 +154,7 @@ func (s *apiImportState) process(api *ApiStruct, token string) (apiFileState, er
func (s *apiTypeState) process(api *ApiStruct, token string) (apiFileState, error) {
var blockCount = 0
var braceCount = 0
for {
line, err := s.readLine()
if err != nil {
@ -161,7 +162,7 @@ func (s *apiTypeState) process(api *ApiStruct, token string) (apiFileState, erro
}
line = token + line
if blockCount <= 1 {
if braceCount == 0 {
line = mayInsertStructKeyword(line)
}
api.Type += newline + newline + line
@ -171,17 +172,31 @@ func (s *apiTypeState) process(api *ApiStruct, token string) (apiFileState, erro
if strings.HasSuffix(line, leftBrace) {
blockCount++
braceCount++
}
if strings.HasSuffix(line, string(leftParenthesis)) {
blockCount++
}
if strings.HasSuffix(line, string(rightBrace)) {
blockCount--
braceCount--
}
if strings.HasSuffix(line, string(rightParenthesis)) {
blockCount--
}
if braceCount >= 2 {
return nil, errors.New("nested type not supported: " + line)
}
if braceCount < 0 {
line = strings.TrimSuffix(line, string(rightBrace))
line = strings.TrimSpace(line)
if strings.HasSuffix(line, leftBrace) {
blockCount++
braceCount++
}
}
if blockCount == 0 {
return &apiRootState{s.baseState}, nil
}
@ -223,12 +238,15 @@ func (s *apiServiceState) process(api *ApiStruct, token string) (apiFileState, e
func mayInsertStructKeyword(line string) string {
line = util.RemoveComment(line)
if !strings.HasSuffix(line, leftBrace) {
if !strings.HasSuffix(line, leftBrace) && !strings.HasSuffix(line, string(rightBrace)) {
return line
}
fields := strings.Fields(line)
if stringx.Contains(fields, tokenStruct) || stringx.Contains(fields, tokenStruct+leftBrace) || len(fields) <= 1 {
if stringx.Contains(fields, tokenStruct) ||
stringx.Contains(fields, tokenStruct+leftBrace) ||
stringx.Contains(fields, tokenStruct+leftBrace+string(rightBrace)) ||
len(fields) <= 1 {
return line
}

View File

@ -26,19 +26,6 @@ func MaybeCreateFile(dir, subdir, file string) (fp *os.File, created bool, err e
return
}
func ClearAndOpenFile(fpath string) (*os.File, error) {
f, err := os.OpenFile(fpath, os.O_WRONLY|os.O_TRUNC, 0600)
if err != nil {
return nil, err
}
_, err = f.WriteString("")
if err != nil {
return nil, err
}
return f, nil
}
func WrapErr(err error, message string) error {
return errors.New(message + ", " + err.Error())
}