Prechádzať zdrojové kódy

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
kingxt 4 rokov pred
rodič
commit
d6d8fc21d8

+ 36 - 9
tools/goctl/api/format/format.go

@@ -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
 }

+ 2 - 1
tools/goctl/api/format/format_test.go

@@ -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)
 }

+ 29 - 3
tools/goctl/api/gogen/gen_test.go

@@ -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)

+ 21 - 3
tools/goctl/api/parser/apifileparser.go

@@ -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
 	}
 

+ 0 - 13
tools/goctl/api/util/util.go

@@ -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())
 }