optimized goctl format (#336)

* fix format

* refactor

* refactor

* optimized

* refactor

* refactor

* refactor

* add js path prefix
master
kingxt 4 years ago committed by GitHub
parent 01060cf16d
commit 12e235efb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,6 +4,7 @@ import (
"bufio" "bufio"
"errors" "errors"
"fmt" "fmt"
"go/format"
"go/scanner" "go/scanner"
"io/ioutil" "io/ioutil"
"os" "os"
@ -13,6 +14,7 @@ import (
"github.com/tal-tech/go-zero/core/errorx" "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/parser"
"github.com/tal-tech/go-zero/tools/goctl/api/util" "github.com/tal-tech/go-zero/tools/goctl/api/util"
ctlutil "github.com/tal-tech/go-zero/tools/goctl/util"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
@ -103,24 +105,108 @@ func apiFormat(data string) (string, error) {
var builder strings.Builder var builder strings.Builder
s := bufio.NewScanner(strings.NewReader(data)) s := bufio.NewScanner(strings.NewReader(data))
var tapCount = 0 var tapCount = 0
var newLineCount = 0
var preLine string
for s.Scan() { for s.Scan() {
line := strings.TrimSpace(s.Text()) line := strings.TrimSpace(s.Text())
if len(line) == 0 {
if newLineCount > 0 {
continue
}
newLineCount++
} else {
if preLine == rightBrace {
builder.WriteString(ctlutil.NL)
}
newLineCount = 0
}
if tapCount == 0 {
format, err := formatGoTypeDef(line, s, &builder)
if err != nil {
return "", err
}
if format {
continue
}
}
noCommentLine := util.RemoveComment(line) noCommentLine := util.RemoveComment(line)
if noCommentLine == rightParenthesis || noCommentLine == rightBrace { if noCommentLine == rightParenthesis || noCommentLine == rightBrace {
tapCount -= 1 tapCount -= 1
} }
if tapCount < 0 { if tapCount < 0 {
line = strings.TrimSuffix(line, rightBrace) line := strings.TrimSuffix(noCommentLine, rightBrace)
line = strings.TrimSpace(line) line = strings.TrimSpace(line)
if strings.HasSuffix(line, leftBrace) { if strings.HasSuffix(line, leftBrace) {
tapCount += 1 tapCount += 1
} }
} }
util.WriteIndent(&builder, tapCount) util.WriteIndent(&builder, tapCount)
builder.WriteString(line + "\n") builder.WriteString(line + ctlutil.NL)
if strings.HasSuffix(noCommentLine, leftParenthesis) || strings.HasSuffix(noCommentLine, leftBrace) { if strings.HasSuffix(noCommentLine, leftParenthesis) || strings.HasSuffix(noCommentLine, leftBrace) {
tapCount += 1 tapCount += 1
} }
preLine = line
} }
return strings.TrimSpace(builder.String()), nil return strings.TrimSpace(builder.String()), nil
} }
func formatGoTypeDef(line string, scanner *bufio.Scanner, builder *strings.Builder) (bool, error) {
noCommentLine := util.RemoveComment(line)
tokenCount := 0
if strings.HasPrefix(noCommentLine, "type") && (strings.HasSuffix(noCommentLine, leftParenthesis) ||
strings.HasSuffix(noCommentLine, leftBrace)) {
var typeBuilder strings.Builder
typeBuilder.WriteString(mayInsertStructKeyword(line, &tokenCount) + ctlutil.NL)
for scanner.Scan() {
noCommentLine := util.RemoveComment(scanner.Text())
typeBuilder.WriteString(mayInsertStructKeyword(scanner.Text(), &tokenCount) + ctlutil.NL)
if noCommentLine == rightBrace || noCommentLine == rightParenthesis {
tokenCount--
}
if tokenCount == 0 {
ts, err := format.Source([]byte(typeBuilder.String()))
if err != nil {
return false, errors.New("error format \n" + typeBuilder.String())
}
result := strings.ReplaceAll(string(ts), " struct ", " ")
result = strings.ReplaceAll(result, "type ()", "")
builder.WriteString(result)
break
}
}
return true, nil
}
return false, nil
}
func mayInsertStructKeyword(line string, token *int) string {
insertStruct := func() string {
if strings.Contains(line, " struct") {
return line
}
index := strings.Index(line, leftBrace)
return line[:index] + " struct " + line[index:]
}
noCommentLine := util.RemoveComment(line)
if strings.HasSuffix(noCommentLine, leftBrace) {
*token++
return insertStruct()
}
if strings.HasSuffix(noCommentLine, rightBrace) {
noCommentLine = strings.TrimSuffix(noCommentLine, rightBrace)
noCommentLine = util.RemoveComment(noCommentLine)
if strings.HasSuffix(noCommentLine, leftBrace) {
return insertStruct()
}
}
if strings.HasSuffix(noCommentLine, leftParenthesis) {
*token++
}
return line
}

@ -24,11 +24,11 @@ handler: GreetHandler
} }
` `
formattedStr = `type Request struct { formattedStr = `type Request {
Name string Name string
} }
type Response struct { type Response {
Message string Message string
} }
@ -40,7 +40,7 @@ service A-api {
}` }`
) )
func TestInlineTypeNotExist(t *testing.T) { func TestFormat(t *testing.T) {
r, err := apiFormat(notFormattedStr) r, err := apiFormat(notFormattedStr)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, r, formattedStr) assert.Equal(t, r, formattedStr)

@ -90,6 +90,12 @@ func writeType(writer io.Writer, tp spec.Type, types []spec.Type) error {
func writeMembers(writer io.Writer, types []spec.Type, members []spec.Member, allMembers *[]spec.Member, indent int) error { func writeMembers(writer io.Writer, types []spec.Type, members []spec.Member, allMembers *[]spec.Member, indent int) error {
for _, member := range members { for _, member := range members {
if !member.IsInline {
_, err := member.GetPropertyName()
if err != nil {
return err
}
}
if !member.IsBodyMember() { if !member.IsBodyMember() {
continue continue
} }

@ -63,10 +63,6 @@ func (m Member) IsOmitempty() bool {
func (m Member) GetPropertyName() (string, error) { func (m Member) GetPropertyName() (string, error) {
tags := m.Tags() tags := m.Tags()
if len(tags) == 0 {
return "", errors.New("json property name not exist, member: " + m.Name)
}
for _, tag := range tags { for _, tag := range tags {
if stringx.Contains(definedKeys, tag.Key) { if stringx.Contains(definedKeys, tag.Key) {
if tag.Name == "-" { if tag.Name == "-" {

@ -85,7 +85,7 @@ func genHandler(dir, webApi, caller string, api *spec.ApiSpec, unwrapApi bool) e
imports += fmt.Sprintf(`import * as components from "%s"`, "./"+outputFile) imports += fmt.Sprintf(`import * as components from "%s"`, "./"+outputFile)
} }
apis, err := genApi(api, localTypes, caller, prefixForType) apis, err := genApi(api, caller, prefixForType)
if err != nil { if err != nil {
return err return err
} }
@ -119,32 +119,34 @@ func genTypes(localTypes []spec.Type, inlineType func(string) (*spec.Type, error
return types, nil return types, nil
} }
func genApi(api *spec.ApiSpec, localTypes []spec.Type, caller string, prefixForType func(string) string) (string, error) { func genApi(api *spec.ApiSpec, caller string, prefixForType func(string) string) (string, error) {
var builder strings.Builder var builder strings.Builder
for _, route := range api.Service.Routes() { for _, group := range api.Service.Groups {
handler, ok := apiutil.GetAnnotationValue(route.Annotations, "server", "handler") for _, route := range group.Routes {
if !ok { handler, ok := apiutil.GetAnnotationValue(route.Annotations, "server", "handler")
return "", fmt.Errorf("missing handler annotation for route %q", route.Path) if !ok {
} return "", fmt.Errorf("missing handler annotation for route %q", route.Path)
handler = util.Untitle(handler)
handler = strings.Replace(handler, "Handler", "", 1)
comment := commentForRoute(route)
if len(comment) > 0 {
fmt.Fprintf(&builder, "%s\n", comment)
}
fmt.Fprintf(&builder, "export function %s(%s) {\n", handler, paramsForRoute(route, prefixForType))
writeIndent(&builder, 1)
responseGeneric := "<null>"
if len(route.ResponseType.Name) > 0 {
val, err := goTypeToTs(route.ResponseType.Name, prefixForType)
if err != nil {
return "", err
} }
responseGeneric = fmt.Sprintf("<%s>", val) handler = util.Untitle(handler)
handler = strings.Replace(handler, "Handler", "", 1)
comment := commentForRoute(route)
if len(comment) > 0 {
fmt.Fprintf(&builder, "%s\n", comment)
}
fmt.Fprintf(&builder, "export function %s(%s) {\n", handler, paramsForRoute(route, prefixForType))
writeIndent(&builder, 1)
responseGeneric := "<null>"
if len(route.ResponseType.Name) > 0 {
val, err := goTypeToTs(route.ResponseType.Name, prefixForType)
if err != nil {
return "", err
}
responseGeneric = fmt.Sprintf("<%s>", val)
}
fmt.Fprintf(&builder, `return %s.%s%s(%s)`, caller, strings.ToLower(route.Method),
util.Title(responseGeneric), callParamsForRoute(route, group))
builder.WriteString("\n}\n\n")
} }
fmt.Fprintf(&builder, `return %s.%s%s(%s)`, caller, strings.ToLower(route.Method),
util.Title(responseGeneric), callParamsForRoute(route))
builder.WriteString("\n}\n\n")
} }
apis := builder.String() apis := builder.String()
@ -188,21 +190,28 @@ func commentForRoute(route spec.Route) string {
return builder.String() return builder.String()
} }
func callParamsForRoute(route spec.Route) string { func callParamsForRoute(route spec.Route, group spec.Group) string {
hasParams := pathHasParams(route) hasParams := pathHasParams(route)
hasBody := hasRequestBody(route) hasBody := hasRequestBody(route)
if hasParams && hasBody { if hasParams && hasBody {
return fmt.Sprintf("%s, %s, %s", pathForRoute(route), "params", "req") return fmt.Sprintf("%s, %s, %s", pathForRoute(route, group), "params", "req")
} else if hasParams { } else if hasParams {
return fmt.Sprintf("%s, %s", pathForRoute(route), "params") return fmt.Sprintf("%s, %s", pathForRoute(route, group), "params")
} else if hasBody { } else if hasBody {
return fmt.Sprintf("%s, %s", pathForRoute(route), "req") return fmt.Sprintf("%s, %s", pathForRoute(route, group), "req")
} }
return pathForRoute(route) return pathForRoute(route, group)
} }
func pathForRoute(route spec.Route) string { func pathForRoute(route spec.Route, group spec.Group) string {
return "\"" + route.Path + "\"" value, ok := apiutil.GetAnnotationValue(group.Annotations, "server", pathPrefix)
if !ok {
return "\"" + route.Path + "\""
} else {
value = strings.TrimPrefix(value, `"`)
value = strings.TrimSuffix(value, `"`)
return fmt.Sprintf(`"%s/%s"`, value, strings.TrimPrefix(route.Path, "/"))
}
} }
func pathHasParams(route spec.Route) bool { func pathHasParams(route spec.Route) bool {

@ -2,4 +2,5 @@ package tsgen
const ( const (
packagePrefix = "components." packagePrefix = "components."
pathPrefix = "pathPrefix"
) )

Loading…
Cancel
Save