From cf3a1020b0a1eca6d3b2fc059d08dfd5797d020f Mon Sep 17 00:00:00 2001 From: kingxt Date: Tue, 12 Jan 2021 14:14:49 +0800 Subject: [PATCH] Java optimized (#376) * optiimzed java gen * optiimzed java gen * fix --- tools/goctl/api/javagen/gencomponents.go | 225 ++++++++++++++++++++--- tools/goctl/api/javagen/util.go | 116 +++--------- tools/goctl/api/parser/util.go | 7 - 3 files changed, 226 insertions(+), 122 deletions(-) delete mode 100644 tools/goctl/api/parser/util.go diff --git a/tools/goctl/api/javagen/gencomponents.go b/tools/goctl/api/javagen/gencomponents.go index dbaedd1f..25a52171 100644 --- a/tools/goctl/api/javagen/gencomponents.go +++ b/tools/goctl/api/javagen/gencomponents.go @@ -1,6 +1,8 @@ package javagen import ( + "bufio" + "bytes" "errors" "fmt" "io" @@ -22,9 +24,43 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; {{.imports}} -{{.componentType}} +public class {{.className}} extends {{.superClassName}} { + +{{.properties}} +{{if .HasProperty}} + + public {{.className}}() { + } + + public {{.className}}({{.params}}) { +{{.constructorSetter}} + } +{{end}} + +{{.getSet}} +} +` + getSetTemplate = ` +{{.indent}}{{.decorator}} +{{.indent}}public {{.returnType}} get{{.property}}() { +{{.indent}} return this.{{.tagValue}}; +{{.indent}}} + +{{.indent}}public void set{{.property}}({{.type}} {{.propertyValue}}) { +{{.indent}} this.{{.tagValue}} = {{.propertyValue}}; +{{.indent}}} ` + boolTemplate = ` +{{.indent}}{{.decorator}} +{{.indent}}public {{.returnType}} is{{.property}}() { +{{.indent}} return this.{{.tagValue}}; +{{.indent}}} + +{{.indent}}public void set{{.property}}({{.type}} {{.propertyValue}}) { +{{.indent}} this.{{.tagValue}} = {{.propertyValue}}; +{{.indent}}} +` httpResponseData = "import com.xhb.core.response.HttpResponseData;" httpData = "import com.xhb.core.packet.HttpData;" ) @@ -34,6 +70,7 @@ type componentsContext struct { requestTypes []spec.Type responseTypes []spec.Type imports []string + members []spec.Member } func genComponents(dir, packetName string, api *spec.ApiSpec) error { @@ -94,56 +131,86 @@ func (c *componentsContext) createComponent(dir, packetName string, ty spec.Type } defer fp.Close() - tyString, err := c.buildType(defineStruct) + propertiesString, err := c.buildProperties(defineStruct) if err != nil { return err } - t := template.Must(template.New("componentType").Parse(componentTemplate)) - return t.Execute(fp, map[string]string{ - "componentType": tyString, - "packet": packetName, - "imports": strings.Join(c.imports, "\n"), - }) -} - -func (c *componentsContext) buildType(ty spec.DefineStruct) (string, error) { - var builder strings.Builder - if err := c.writeType(&builder, ty); err != nil { - return "", apiutil.WrapErr(err, "Type "+ty.Name()+" generate error") + getSetString, err := c.buildGetterSetter(defineStruct) + if err != nil { + return err } - return builder.String(), nil -} - -func (c *componentsContext) writeType(writer io.Writer, defineStruct spec.DefineStruct) error { - responseData := "HttpData" + superClassName := "HttpData" for _, item := range c.responseTypes { if item.Name() == defineStruct.Name() { - responseData = "HttpResponseData" + superClassName = "HttpResponseData" if !stringx.Contains(c.imports, httpResponseData) { c.imports = append(c.imports, httpResponseData) } break } } - if responseData == "HttpData" && !stringx.Contains(c.imports, httpData) { + if superClassName == "HttpData" && !stringx.Contains(c.imports, httpData) { c.imports = append(c.imports, httpData) } - fmt.Fprintf(writer, "public class %s extends %s {\n", util.Title(defineStruct.Name()), responseData) + params, constructorSetter, err := c.buildConstructor() + if err != nil { + return err + } + + buffer := new(bytes.Buffer) + t := template.Must(template.New("componentType").Parse(componentTemplate)) + err = t.Execute(buffer, map[string]interface{}{ + "properties": propertiesString, + "params": params, + "constructorSetter": constructorSetter, + "getSet": getSetString, + "packet": packetName, + "imports": strings.Join(c.imports, "\n"), + "className": util.Title(defineStruct.Name()), + "superClassName": superClassName, + "HasProperty": len(strings.TrimSpace(propertiesString)) > 0, + }) + if err != nil { + return err + } + + _, err = fp.WriteString(formatSource(buffer.String())) + return err +} + +func (c *componentsContext) buildProperties(defineStruct spec.DefineStruct) (string, error) { + var builder strings.Builder + if err := c.writeType(&builder, defineStruct); err != nil { + return "", apiutil.WrapErr(err, "Type "+defineStruct.Name()+" generate error") + } + + return builder.String(), nil +} + +func (c *componentsContext) buildGetterSetter(defineStruct spec.DefineStruct) (string, error) { + var builder strings.Builder + if err := c.genGetSet(&builder, defineStruct, 1); err != nil { + return "", apiutil.WrapErr(err, "Type "+defineStruct.Name()+" get or set generate error") + } + + return builder.String(), nil +} + +func (c *componentsContext) writeType(writer io.Writer, defineStruct spec.DefineStruct) error { + c.members = make([]spec.Member, 0) err := c.writeMembers(writer, defineStruct, 1) if err != nil { return err } - genGetSet(writer, defineStruct, 1) - fmt.Fprintf(writer, "}") return nil } -func (c *componentsContext) writeMembers(writer io.Writer, ty spec.DefineStruct, indent int) error { - for _, member := range ty.Members { +func (c *componentsContext) writeMembers(writer io.Writer, defineStruct spec.DefineStruct, indent int) error { + for _, member := range defineStruct.Members { if member.IsInline { defineStruct, ok := member.Type.(spec.DefineStruct) if ok { @@ -160,7 +227,113 @@ func (c *componentsContext) writeMembers(writer io.Writer, ty spec.DefineStruct, if err := writeProperty(writer, member, indent); err != nil { return err } + + c.members = append(c.members, member) } } + return nil } + +func (c *componentsContext) buildConstructor() (string, string, error) { + var params strings.Builder + var constructorSetter strings.Builder + for index, member := range c.members { + tp, err := specTypeToJava(member.Type) + if err != nil { + return "", "", err + } + + params.WriteString(fmt.Sprintf("%s %s", tp, util.Untitle(member.Name))) + pn, err := member.GetPropertyName() + if err != nil { + return "", "", err + } + + if index != len(c.members)-1 { + params.WriteString(", ") + } + + writeIndent(&constructorSetter, 2) + constructorSetter.WriteString(fmt.Sprintf("this.%s = %s;", pn, util.Untitle(member.Name))) + if index != len(c.members)-1 { + constructorSetter.WriteString(util.NL) + } + } + return params.String(), constructorSetter.String(), nil +} + +func (c *componentsContext) genGetSet(writer io.Writer, defineStruct spec.DefineStruct, indent int) error { + var members = defineStruct.GetBodyMembers() + members = append(members, defineStruct.GetFormMembers()...) + for _, member := range members { + javaType, err := specTypeToJava(member.Type) + if err != nil { + return nil + } + + var property = util.Title(member.Name) + var templateStr = getSetTemplate + if javaType == "boolean" { + templateStr = boolTemplate + property = strings.TrimPrefix(property, "Is") + property = strings.TrimPrefix(property, "is") + } + t := template.Must(template.New(templateStr).Parse(getSetTemplate)) + var tmplBytes bytes.Buffer + + tyString := javaType + decorator := "" + javaPrimitiveType := []string{"int", "long", "boolean", "float", "double", "short"} + if !stringx.Contains(javaPrimitiveType, javaType) { + if member.IsOptional() || member.IsOmitEmpty() { + decorator = "@Nullable " + } else { + decorator = "@NotNull " + } + tyString = decorator + tyString + } + + tagName, err := member.GetPropertyName() + if err != nil { + return err + } + + err = t.Execute(&tmplBytes, map[string]string{ + "property": property, + "propertyValue": util.Untitle(member.Name), + "tagValue": tagName, + "type": tyString, + "decorator": decorator, + "returnType": javaType, + "indent": indentString(indent), + }) + if err != nil { + return err + } + + r := tmplBytes.String() + r = strings.Replace(r, " boolean get", " boolean is", 1) + writer.Write([]byte(r)) + } + return nil +} + +func formatSource(source string) string { + var builder strings.Builder + scanner := bufio.NewScanner(strings.NewReader(source)) + preIsBreakLine := false + for scanner.Scan() { + text := strings.TrimSpace(scanner.Text()) + if text == "" && preIsBreakLine { + continue + } + preIsBreakLine = text == "" + builder.WriteString(scanner.Text() + "\n") + } + + if err := scanner.Err(); err != nil { + fmt.Println(err) + } + return builder.String() +} diff --git a/tools/goctl/api/javagen/util.go b/tools/goctl/api/javagen/util.go index de976d53..06d7742b 100644 --- a/tools/goctl/api/javagen/util.go +++ b/tools/goctl/api/javagen/util.go @@ -1,43 +1,18 @@ package javagen import ( - "bytes" "errors" "fmt" "io" "strings" - "text/template" - "github.com/tal-tech/go-zero/core/stringx" "github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/tal-tech/go-zero/tools/goctl/util" ) -const getSetTemplate = ` -{{.indent}}{{.decorator}} -{{.indent}}public {{.returnType}} get{{.property}}() { -{{.indent}} return this.{{.tagValue}}; -{{.indent}}} - -{{.indent}}public void set{{.property}}({{.type}} {{.propertyValue}}) { -{{.indent}} this.{{.tagValue}} = {{.propertyValue}}; -{{.indent}}} -` - -const boolTemplate = ` -{{.indent}}{{.decorator}} -{{.indent}}public {{.returnType}} is{{.property}}() { -{{.indent}} return this.{{.tagValue}}; -{{.indent}}} - -{{.indent}}public void set{{.property}}({{.type}} {{.propertyValue}}) { -{{.indent}} this.{{.tagValue}} = {{.propertyValue}}; -{{.indent}}} -` - func writeProperty(writer io.Writer, member spec.Member, indent int) error { writeIndent(writer, indent) - ty, err := goTypeToJava(member.Type) + ty, err := specTypeToJava(member.Type) ty = strings.Replace(ty, "*", "", 1) if err != nil { return err @@ -53,13 +28,17 @@ func writeProperty(writer io.Writer, member spec.Member, indent int) error { return err } - writeDefaultValue(writer, member) + err = writeDefaultValue(writer, member) + if err != nil { + return err + } + fmt.Fprint(writer, ";\n") return err } func writeDefaultValue(writer io.Writer, member spec.Member) error { - javaType, err := goTypeToJava(member.Type) + javaType, err := specTypeToJava(member.Type) if err != nil { return err } @@ -85,7 +64,7 @@ func indentString(indent int) string { return result } -func goTypeToJava(tp spec.Type) (string, error) { +func specTypeToJava(tp spec.Type) (string, error) { switch v := tp.(type) { case spec.DefineStruct: return util.Title(tp.Name()), nil @@ -96,7 +75,7 @@ func goTypeToJava(tp spec.Type) (string, error) { } return r, nil case spec.MapType: - valueType, err := goTypeToJava(v.Value) + valueType, err := specTypeToJava(v.Value) if err != nil { return "", err } @@ -107,16 +86,29 @@ func goTypeToJava(tp spec.Type) (string, error) { return "byte[]", nil } - valueType, err := goTypeToJava(v.Value) + valueType, err := specTypeToJava(v.Value) if err != nil { return "", err } + switch valueType { + case "int": + return "Integer[]", nil + case "long": + return "Long[]", nil + case "float": + return "Float[]", nil + case "double": + return "Double[]", nil + case "boolean": + return "Boolean[]", nil + } + return fmt.Sprintf("java.util.ArrayList<%s>", util.Title(valueType)), nil case spec.InterfaceType: return "Object", nil case spec.PointerType: - return goTypeToJava(v.Type) + return specTypeToJava(v.Type) } return "", errors.New("unsupported primitive type " + tp.Name()) @@ -130,7 +122,9 @@ func primitiveType(tp string) (string, bool) { return "long", true case "int", "int8", "int32", "uint", "uint8", "uint16", "uint32": return "int", true - case "float", "float32", "float64": + case "float", "float32": + return "float", true + case "float64": return "double", true case "bool": return "boolean", true @@ -138,59 +132,3 @@ func primitiveType(tp string) (string, bool) { return "", false } - -func genGetSet(writer io.Writer, defineStruct spec.DefineStruct, indent int) error { - var members = defineStruct.GetBodyMembers() - members = append(members, defineStruct.GetFormMembers()...) - for _, member := range members { - javaType, err := goTypeToJava(member.Type) - if err != nil { - return nil - } - - var property = util.Title(member.Name) - var templateStr = getSetTemplate - if javaType == "boolean" { - templateStr = boolTemplate - property = strings.TrimPrefix(property, "Is") - property = strings.TrimPrefix(property, "is") - } - t := template.Must(template.New(templateStr).Parse(getSetTemplate)) - var tmplBytes bytes.Buffer - - tyString := javaType - decorator := "" - javaPrimitiveType := []string{"int", "long", "boolean", "float", "double", "short"} - if !stringx.Contains(javaPrimitiveType, javaType) { - if member.IsOptional() || member.IsOmitEmpty() { - decorator = "@Nullable " - } else { - decorator = "@NotNull " - } - tyString = decorator + tyString - } - - tagName, err := member.GetPropertyName() - if err != nil { - return err - } - - err = t.Execute(&tmplBytes, map[string]string{ - "property": property, - "propertyValue": util.Untitle(member.Name), - "tagValue": tagName, - "type": tyString, - "decorator": decorator, - "returnType": javaType, - "indent": indentString(indent), - }) - if err != nil { - return err - } - - r := tmplBytes.String() - r = strings.Replace(r, " boolean get", " boolean is", 1) - writer.Write([]byte(r)) - } - return nil -} diff --git a/tools/goctl/api/parser/util.go b/tools/goctl/api/parser/util.go deleted file mode 100644 index 7a0ebdff..00000000 --- a/tools/goctl/api/parser/util.go +++ /dev/null @@ -1,7 +0,0 @@ -package parser - -import ( - "github.com/tal-tech/go-zero/tools/goctl/api/spec" -) - -var emptyType spec.Type