Browse Source

optimized goctl format (#336)

* fix format

* refactor

* refactor

* optimized

* refactor

* refactor

* refactor

* add js path prefix
kingxt 4 years ago
parent
commit
12e235efb0

+ 88 - 2
tools/goctl/api/format/format.go

@@ -4,6 +4,7 @@ import (
 	"bufio"
 	"errors"
 	"fmt"
+	"go/format"
 	"go/scanner"
 	"io/ioutil"
 	"os"
@@ -13,6 +14,7 @@ import (
 	"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"
+	ctlutil "github.com/tal-tech/go-zero/tools/goctl/util"
 	"github.com/urfave/cli"
 )
 
@@ -103,24 +105,108 @@ func apiFormat(data string) (string, error) {
 	var builder strings.Builder
 	s := bufio.NewScanner(strings.NewReader(data))
 	var tapCount = 0
+	var newLineCount = 0
+	var preLine string
 	for s.Scan() {
 		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)
 		if noCommentLine == rightParenthesis || noCommentLine == rightBrace {
 			tapCount -= 1
 		}
 		if tapCount < 0 {
-			line = strings.TrimSuffix(line, rightBrace)
+			line := strings.TrimSuffix(noCommentLine, rightBrace)
 			line = strings.TrimSpace(line)
 			if strings.HasSuffix(line, leftBrace) {
 				tapCount += 1
 			}
 		}
 		util.WriteIndent(&builder, tapCount)
-		builder.WriteString(line + "\n")
+		builder.WriteString(line + ctlutil.NL)
 		if strings.HasSuffix(noCommentLine, leftParenthesis) || strings.HasSuffix(noCommentLine, leftBrace) {
 			tapCount += 1
 		}
+		preLine = line
 	}
 	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
+}

+ 3 - 3
tools/goctl/api/format/format_test.go

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

+ 6 - 0
tools/goctl/api/javagen/gencomponents.go

@@ -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 {
 	for _, member := range members {
+		if !member.IsInline {
+			_, err := member.GetPropertyName()
+			if err != nil {
+				return err
+			}
+		}
 		if !member.IsBodyMember() {
 			continue
 		}

+ 0 - 4
tools/goctl/api/spec/fn.go

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

+ 40 - 31
tools/goctl/api/tsgen/genpacket.go

@@ -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)
 	}
 
-	apis, err := genApi(api, localTypes, caller, prefixForType)
+	apis, err := genApi(api, caller, prefixForType)
 	if err != nil {
 		return err
 	}
@@ -119,32 +119,34 @@ func genTypes(localTypes []spec.Type, inlineType func(string) (*spec.Type, error
 	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
-	for _, route := range api.Service.Routes() {
-		handler, ok := apiutil.GetAnnotationValue(route.Annotations, "server", "handler")
-		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
+	for _, group := range api.Service.Groups {
+		for _, route := range group.Routes {
+			handler, ok := apiutil.GetAnnotationValue(route.Annotations, "server", "handler")
+			if !ok {
+				return "", fmt.Errorf("missing handler annotation for route %q", route.Path)
 			}
-			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()
@@ -188,21 +190,28 @@ func commentForRoute(route spec.Route) string {
 	return builder.String()
 }
 
-func callParamsForRoute(route spec.Route) string {
+func callParamsForRoute(route spec.Route, group spec.Group) string {
 	hasParams := pathHasParams(route)
 	hasBody := hasRequestBody(route)
 	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 {
-		return fmt.Sprintf("%s, %s", pathForRoute(route), "params")
+		return fmt.Sprintf("%s, %s", pathForRoute(route, group), "params")
 	} 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 {
-	return "\"" + route.Path + "\""
+func pathForRoute(route spec.Route, group spec.Group) string {
+	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 {

+ 1 - 0
tools/goctl/api/tsgen/vars.go

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