diff --git a/tools/goctl/completion/completion.go b/tools/goctl/completion/completion.go index 67493b99..5e29e52e 100644 --- a/tools/goctl/completion/completion.go +++ b/tools/goctl/completion/completion.go @@ -48,17 +48,15 @@ func Completion(c *cli.Context) error { flag := magic err = ioutil.WriteFile(zshF, zsh, os.ModePerm) - if err != nil { - return err + if err == nil { + flag |= flagZsh } - flag |= flagZsh err = ioutil.WriteFile(bashF, bash, os.ModePerm) - if err != nil { - return err + if err == nil { + flag |= flagBash } - flag |= flagBash buffer.WriteString(aurora.BrightGreen("generation auto completion success!\n").String()) buffer.WriteString(aurora.BrightGreen("executes the following script to setting shell:\n").String()) switch flag { diff --git a/tools/goctl/goctl.go b/tools/goctl/goctl.go index cccf38bd..4ab0dc3b 100644 --- a/tools/goctl/goctl.go +++ b/tools/goctl/goctl.go @@ -492,9 +492,8 @@ var commands = []cli.Command{ Usage: "generate rpc code", Subcommands: []cli.Command{ { - Name: "new", - Usage: `generate rpc demo service`, - Description: aurora.Yellow(`deprecated: zrpc code generation use "goctl rpc protoc" instead, for the details see "goctl rpc protoc --help"`).String(), + Name: "new", + Usage: `generate rpc demo service`, Flags: []cli.Flag{ cli.StringFlag{ Name: "style", @@ -603,53 +602,6 @@ var commands = []cli.Command{ }, }, }, - { - Name: "proto", - Usage: `generate rpc from proto`, - Description: aurora.Yellow(`deprecated: zrpc code generation use "goctl rpc protoc" instead, for the details see "goctl rpc protoc --help"`).String(), - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "src, s", - Usage: "the file path of the proto source file", - }, - cli.StringSliceFlag{ - Name: "proto_path, I", - Usage: `native command of protoc, specify the directory in which to search for imports. [optional]`, - }, - cli.StringSliceFlag{ - Name: "go_opt", - Usage: `native command of protoc-gen-go, specify the mapping from proto to go, eg --go_opt=proto_import=go_package_import. [optional]`, - }, - cli.StringFlag{ - Name: "dir, d", - Usage: `the target path of the code`, - }, - cli.StringFlag{ - Name: "style", - Usage: "the file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]", - }, - cli.BoolFlag{ - Name: "idea", - Usage: "whether the command execution environment is from idea plugin. [optional]", - }, - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority", - }, - cli.StringFlag{ - Name: "remote", - Usage: "the remote git repo of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the " + - "https://github.com/zeromicro/go-zero-template directory structure", - }, - cli.StringFlag{ - Name: "branch", - Usage: "the branch of the remote repo, it does work with --remote", - }, - }, - Action: rpc.RPC, - }, }, }, { diff --git a/tools/goctl/rpc/cli/cli.go b/tools/goctl/rpc/cli/cli.go index 0229ff6a..b9716ac6 100644 --- a/tools/goctl/rpc/cli/cli.go +++ b/tools/goctl/rpc/cli/cli.go @@ -4,84 +4,16 @@ import ( "errors" "fmt" "path/filepath" - "runtime" "github.com/urfave/cli" "github.com/zeromicro/go-zero/tools/goctl/rpc/generator" "github.com/zeromicro/go-zero/tools/goctl/util" - "github.com/zeromicro/go-zero/tools/goctl/util/console" - "github.com/zeromicro/go-zero/tools/goctl/util/env" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) -// Deprecated: use ZRPC instead. -// RPC is to generate rpc service code from a proto file by specifying a proto file using flag src, -// you can specify a target folder for code generation, when the proto file has import, you can specify -// the import search directory through the proto_path command, for specific usage, please refer to protoc -h -func RPC(c *cli.Context) error { - console.Warning("deprecated: use %q instead, for the details see %q", - "goctl rpc protoc", "goctl rpc protoc --help") - - if err := prepare(); err != nil { - return err - } - - src := c.String("src") - out := c.String("dir") - style := c.String("style") - protoImportPath := c.StringSlice("proto_path") - goOptions := c.StringSlice("go_opt") - home := c.String("home") - remote := c.String("remote") - branch := c.String("branch") - if len(remote) > 0 { - repo, _ := util.CloneIntoGitHome(remote, branch) - if len(repo) > 0 { - home = repo - } - } - if len(home) > 0 { - pathx.RegisterGoctlHome(home) - } - - if len(src) == 0 { - return errors.New("missing -src") - } - - if len(out) == 0 { - return errors.New("missing -dir") - } - - g, err := generator.NewDefaultRPCGenerator(style) - if err != nil { - return err - } - - return g.Generate(src, out, protoImportPath, goOptions...) -} - -func prepare() error { - if !env.CanExec() { - return fmt.Errorf("%s: can not start new processes using os.StartProcess or exec.Command", runtime.GOOS) - } - if _, err := env.LookUpGo(); err != nil { - return err - } - if _, err := env.LookUpProtoc(); err != nil { - return err - } - if _, err := env.LookUpProtocGenGo(); err != nil { - return err - } - return nil -} - // RPCNew is to generate rpc greet service, this greet service can speed // up your understanding of the zrpc service structure func RPCNew(c *cli.Context) error { - console.Warning("deprecated: it will be removed in the feature, zrpc code generation please use %q instead", - "goctl rpc protoc") - rpcname := c.Args().First() ext := filepath.Ext(rpcname) if len(ext) > 0 { @@ -113,12 +45,15 @@ func RPCNew(c *cli.Context) error { return err } - g, err := generator.NewDefaultRPCGenerator(style) - if err != nil { - return err - } - - return g.Generate(src, filepath.Dir(src), nil) + var ctx generator.ZRpcContext + ctx.Src = src + ctx.GoOutput = filepath.Dir(src) + ctx.GrpcOutput = filepath.Dir(src) + ctx.IsGooglePlugin = true + ctx.Output = filepath.Dir(src) + ctx.ProtocCmd = fmt.Sprintf("protoc -I=%s %s --go_out=%s --go-grpc_out=%s", filepath.Dir(src), filepath.Base(src), filepath.Dir(src), filepath.Dir(src)) + g := generator.NewGenerator(style) + return g.Generate(&ctx) } // RPCTemplate is the entry for generate rpc template diff --git a/tools/goctl/rpc/cli/zrpc.go b/tools/goctl/rpc/cli/zrpc.go index 8910b97a..e0ab934b 100644 --- a/tools/goctl/rpc/cli/zrpc.go +++ b/tools/goctl/rpc/cli/zrpc.go @@ -107,12 +107,8 @@ func ZRPC(c *cli.Context) error { ctx.IsGooglePlugin = isGooglePlugin ctx.Output = zrpcOut ctx.ProtocCmd = strings.Join(protocArgs, " ") - g, err := generator.NewDefaultRPCGenerator(style, generator.WithZRpcContext(&ctx)) - if err != nil { - return err - } - - return g.Generate(source, zrpcOut, nil) + g := generator.NewGenerator(style) + return g.Generate(&ctx) } func removeGoctlFlag(args []string) []string { diff --git a/tools/goctl/rpc/generator/base/common.proto b/tools/goctl/rpc/generator/base/common.proto index 42c9107e..883c65fe 100644 --- a/tools/goctl/rpc/generator/base/common.proto +++ b/tools/goctl/rpc/generator/base/common.proto @@ -1,6 +1,7 @@ syntax = "proto3"; package common; +option go_package="./common"; message User { string name = 1; diff --git a/tools/goctl/rpc/generator/defaultgenerator.go b/tools/goctl/rpc/generator/defaultgenerator.go deleted file mode 100644 index 8d20ddfa..00000000 --- a/tools/goctl/rpc/generator/defaultgenerator.go +++ /dev/null @@ -1,28 +0,0 @@ -package generator - -import ( - "github.com/zeromicro/go-zero/tools/goctl/env" - "github.com/zeromicro/go-zero/tools/goctl/util/console" -) - -// DefaultGenerator defines the environment needs of rpc service generation -type DefaultGenerator struct { - log console.Console -} - -// just test interface implement -var _ Generator = (*DefaultGenerator)(nil) - -// NewDefaultGenerator returns an instance of DefaultGenerator -func NewDefaultGenerator() Generator { - log := console.NewColorConsole() - return &DefaultGenerator{ - log: log, - } -} - -// Prepare provides environment detection generated by rpc service, -// including go environment, protoc, whether protoc-gen-go is installed or not -func (g *DefaultGenerator) Prepare() error { - return env.Prepare(true, true) -} diff --git a/tools/goctl/rpc/generator/gen.go b/tools/goctl/rpc/generator/gen.go index 2d6a4683..636f126d 100644 --- a/tools/goctl/rpc/generator/gen.go +++ b/tools/goctl/rpc/generator/gen.go @@ -3,22 +3,12 @@ package generator import ( "path/filepath" - conf "github.com/zeromicro/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/rpc/parser" "github.com/zeromicro/go-zero/tools/goctl/util/console" "github.com/zeromicro/go-zero/tools/goctl/util/ctx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) -// RPCGenerator defines a generator and configure -type RPCGenerator struct { - g Generator - cfg *conf.Config - ctx *ZRpcContext -} - -type RPCGeneratorOption func(g *RPCGenerator) - type ZRpcContext struct { Src string ProtocCmd string @@ -30,38 +20,11 @@ type ZRpcContext struct { Output string } -// NewDefaultRPCGenerator wraps Generator with configure -func NewDefaultRPCGenerator(style string, options ...RPCGeneratorOption) (*RPCGenerator, error) { - cfg, err := conf.NewConfig(style) - if err != nil { - return nil, err - } - return NewRPCGenerator(NewDefaultGenerator(), cfg, options...), nil -} - -// NewRPCGenerator creates an instance for RPCGenerator -func NewRPCGenerator(g Generator, cfg *conf.Config, options ...RPCGeneratorOption) *RPCGenerator { - out := &RPCGenerator{ - g: g, - cfg: cfg, - } - for _, opt := range options { - opt(out) - } - return out -} - -func WithZRpcContext(c *ZRpcContext) RPCGeneratorOption { - return func(g *RPCGenerator) { - g.ctx = c - } -} - // Generate generates an rpc service, through the proto file, // code storage directory, and proto import parameters to control // the source file and target location of the rpc service that needs to be generated -func (g *RPCGenerator) Generate(src, target string, protoImportPath []string, goOptions ...string) error { - abs, err := filepath.Abs(target) +func (g *Generator) Generate(zctx *ZRpcContext) error { + abs, err := filepath.Abs(zctx.Output) if err != nil { return err } @@ -71,7 +34,7 @@ func (g *RPCGenerator) Generate(src, target string, protoImportPath []string, go return err } - err = g.g.Prepare() + err = g.Prepare() if err != nil { return err } @@ -82,52 +45,52 @@ func (g *RPCGenerator) Generate(src, target string, protoImportPath []string, go } p := parser.NewDefaultProtoParser() - proto, err := p.Parse(src) + proto, err := p.Parse(zctx.Src) if err != nil { return err } - dirCtx, err := mkdir(projectCtx, proto, g.cfg, g.ctx) + dirCtx, err := mkdir(projectCtx, proto, g.cfg, zctx) if err != nil { return err } - err = g.g.GenEtc(dirCtx, proto, g.cfg) + err = g.GenEtc(dirCtx, proto, g.cfg) if err != nil { return err } - err = g.g.GenPb(dirCtx, protoImportPath, proto, g.cfg, g.ctx, goOptions...) + err = g.GenPb(dirCtx, zctx) if err != nil { return err } - err = g.g.GenConfig(dirCtx, proto, g.cfg) + err = g.GenConfig(dirCtx, proto, g.cfg) if err != nil { return err } - err = g.g.GenSvc(dirCtx, proto, g.cfg) + err = g.GenSvc(dirCtx, proto, g.cfg) if err != nil { return err } - err = g.g.GenLogic(dirCtx, proto, g.cfg) + err = g.GenLogic(dirCtx, proto, g.cfg) if err != nil { return err } - err = g.g.GenServer(dirCtx, proto, g.cfg) + err = g.GenServer(dirCtx, proto, g.cfg) if err != nil { return err } - err = g.g.GenMain(dirCtx, proto, g.cfg) + err = g.GenMain(dirCtx, proto, g.cfg) if err != nil { return err } - err = g.g.GenCall(dirCtx, proto, g.cfg) + err = g.GenCall(dirCtx, proto, g.cfg) console.NewColorConsole().MarkDone() diff --git a/tools/goctl/rpc/generator/gen_test.go b/tools/goctl/rpc/generator/gen_test.go index d849ba46..1bdd5383 100644 --- a/tools/goctl/rpc/generator/gen_test.go +++ b/tools/goctl/rpc/generator/gen_test.go @@ -1,6 +1,7 @@ package generator import ( + "fmt" "go/build" "os" "path/filepath" @@ -10,26 +11,19 @@ import ( "github.com/stretchr/testify/assert" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/stringx" - conf "github.com/zeromicro/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/rpc/execx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) -var cfg = &conf.Config{ - NamingFormat: "gozero", -} - func TestRpcGenerate(t *testing.T) { _ = Clean() - dispatcher := NewDefaultGenerator() - err := dispatcher.Prepare() + g := NewGenerator("gozero") + err := g.Prepare() if err != nil { logx.Error(err) return } projectName := stringx.Rand() - g := NewRPCGenerator(dispatcher, cfg) - src := filepath.Join(build.Default.GOPATH, "src") _, err = os.Stat(src) if err != nil { @@ -46,7 +40,15 @@ func TestRpcGenerate(t *testing.T) { // case go path t.Run("GOPATH", func(t *testing.T) { - err = g.Generate("./test.proto", projectDir, []string{common}, "Mbase/common.proto=./base") + ctx := &ZRpcContext{ + Src: "./test.proto", + ProtocCmd: fmt.Sprintf("protoc -I=%s test.proto --go_out=%s --go_opt=Mbase/common.proto=./base --go-grpc_out=%s", common, projectDir, projectDir), + IsGooglePlugin: true, + GoOutput: projectDir, + GrpcOutput: projectDir, + Output: projectDir, + } + err = g.Generate(ctx) assert.Nil(t, err) _, err = execx.Run("go test "+projectName, projectDir) if err != nil { @@ -67,7 +69,15 @@ func TestRpcGenerate(t *testing.T) { } projectDir = filepath.Join(workDir, projectName) - err = g.Generate("./test.proto", projectDir, []string{common}, "Mbase/common.proto=./base") + ctx := &ZRpcContext{ + Src: "./test.proto", + ProtocCmd: fmt.Sprintf("protoc -I=%s test.proto --go_out=%s --go_opt=Mbase/common.proto=./base --go-grpc_out=%s", common, projectDir, projectDir), + IsGooglePlugin: true, + GoOutput: projectDir, + GrpcOutput: projectDir, + Output: projectDir, + } + err = g.Generate(ctx) assert.Nil(t, err) _, err = execx.Run("go test "+projectName, projectDir) if err != nil { @@ -79,7 +89,15 @@ func TestRpcGenerate(t *testing.T) { // case not in go mod and go path t.Run("OTHER", func(t *testing.T) { - err = g.Generate("./test.proto", projectDir, []string{common, src}, "Mbase/common.proto=./base") + ctx := &ZRpcContext{ + Src: "./test.proto", + ProtocCmd: fmt.Sprintf("protoc -I=%s test.proto --go_out=%s --go_opt=Mbase/common.proto=./base --go-grpc_out=%s", common, projectDir, projectDir), + IsGooglePlugin: true, + GoOutput: projectDir, + GrpcOutput: projectDir, + Output: projectDir, + } + err = g.Generate(ctx) assert.Nil(t, err) _, err = execx.Run("go test "+projectName, projectDir) if err != nil { diff --git a/tools/goctl/rpc/generator/gencall.go b/tools/goctl/rpc/generator/gencall.go index 04544cc0..08b14900 100644 --- a/tools/goctl/rpc/generator/gencall.go +++ b/tools/goctl/rpc/generator/gencall.go @@ -58,7 +58,7 @@ func New{{.serviceName}}(cli zrpc.Client) {{.serviceName}} { callFunctionTemplate = ` {{if .hasComment}}{{.comment}}{{end}} func (m *default{{.serviceName}}) {{.method}}(ctx context.Context{{if .hasReq}}, in *{{.pbRequest}}{{end}}, opts ...grpc.CallOption) ({{if .notStream}}*{{.pbResponse}}, {{else}}{{.streamBody}},{{end}} error) { - client := {{.package}}.New{{.rpcServiceName}}Client(m.cli.Conn()) + client := {{if .isCallPkgSameToGrpcPkg}}{{else}}{{.package}}.{{end}}New{{.rpcServiceName}}Client(m.cli.Conn()) return client.{{.method}}(ctx{{if .hasReq}}, in{{end}}, opts...) } ` @@ -66,10 +66,17 @@ func (m *default{{.serviceName}}) {{.method}}(ctx context.Context{{if .hasReq}}, // GenCall generates the rpc client code, which is the entry point for the rpc service call. // It is a layer of encapsulation for the rpc client and shields the details in the pb. -func (g *DefaultGenerator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config) error { +func (g *Generator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config) error { dir := ctx.GetCall() service := proto.Service head := util.GetHead(proto.Name) + fmt.Printf(` +call: %s +pb: %s +grpc: %s +`, ctx.GetCall().Filename, ctx.GetPb().Filename, ctx.GetProtoGo().Filename) + isCallPkgSameToPbPkg := ctx.GetCall().Filename == ctx.GetPb().Filename + isCallPkgSameToGrpcPkg := ctx.GetCall().Filename == ctx.GetProtoGo().Filename callFilename, err := format.FileNamingFormat(cfg.NamingFormat, service.Name) if err != nil { @@ -77,12 +84,12 @@ func (g *DefaultGenerator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf } filename := filepath.Join(dir.Filename, fmt.Sprintf("%s.go", callFilename)) - functions, err := g.genFunction(proto.PbPackage, service) + functions, err := g.genFunction(proto.PbPackage, service, isCallPkgSameToGrpcPkg) if err != nil { return err } - iFunctions, err := g.getInterfaceFuncs(proto.PbPackage, service) + iFunctions, err := g.getInterfaceFuncs(proto.PbPackage, service, isCallPkgSameToGrpcPkg) if err != nil { return err } @@ -93,11 +100,19 @@ func (g *DefaultGenerator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf } alias := collection.NewSet() - for _, item := range proto.Message { - msgName := getMessageName(*item.Message) - alias.AddStr(fmt.Sprintf("%s = %s", parser.CamelCase(msgName), fmt.Sprintf("%s.%s", proto.PbPackage, parser.CamelCase(msgName)))) + if !isCallPkgSameToPbPkg { + for _, item := range proto.Message { + msgName := getMessageName(*item.Message) + alias.AddStr(fmt.Sprintf("%s = %s", parser.CamelCase(msgName), fmt.Sprintf("%s.%s", proto.PbPackage, parser.CamelCase(msgName)))) + } } + pbPackage := fmt.Sprintf(`"%s"`, ctx.GetPb().Package) + protoGoPackage := fmt.Sprintf(`"%s"`, ctx.GetProtoGo().Package) + if isCallPkgSameToGrpcPkg { + pbPackage = "" + protoGoPackage = "" + } aliasKeys := alias.KeysStr() sort.Strings(aliasKeys) err = util.With("shared").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{ @@ -105,8 +120,8 @@ func (g *DefaultGenerator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf "alias": strings.Join(aliasKeys, pathx.NL), "head": head, "filePackage": dir.Base, - "pbPackage": fmt.Sprintf(`"%s"`, ctx.GetPb().Package), - "protoGoPackage": fmt.Sprintf(`"%s"`, ctx.GetProtoGo().Package), + "pbPackage": pbPackage, + "protoGoPackage": protoGoPackage, "serviceName": stringx.From(service.Name).ToCamel(), "functions": strings.Join(functions, pathx.NL), "interface": strings.Join(iFunctions, pathx.NL), @@ -136,7 +151,7 @@ func getMessageName(msg proto.Message) string { return strings.Join(list, "_") } -func (g *DefaultGenerator) genFunction(goPackage string, service parser.Service) ([]string, error) { +func (g *Generator) genFunction(goPackage string, service parser.Service, isCallPkgSameToGrpcPkg bool) ([]string, error) { functions := make([]string, 0) for _, rpc := range service.RPC { @@ -147,18 +162,22 @@ func (g *DefaultGenerator) genFunction(goPackage string, service parser.Service) comment := parser.GetComment(rpc.Doc()) streamServer := fmt.Sprintf("%s.%s_%s%s", goPackage, parser.CamelCase(service.Name), parser.CamelCase(rpc.Name), "Client") + if isCallPkgSameToGrpcPkg { + streamServer = fmt.Sprintf("%s_%s%s", parser.CamelCase(service.Name), parser.CamelCase(rpc.Name), "Client") + } buffer, err := util.With("sharedFn").Parse(text).Execute(map[string]interface{}{ - "serviceName": stringx.From(service.Name).ToCamel(), - "rpcServiceName": parser.CamelCase(service.Name), - "method": parser.CamelCase(rpc.Name), - "package": goPackage, - "pbRequest": parser.CamelCase(rpc.RequestType), - "pbResponse": parser.CamelCase(rpc.ReturnsType), - "hasComment": len(comment) > 0, - "comment": comment, - "hasReq": !rpc.StreamsRequest, - "notStream": !rpc.StreamsRequest && !rpc.StreamsReturns, - "streamBody": streamServer, + "serviceName": stringx.From(service.Name).ToCamel(), + "rpcServiceName": parser.CamelCase(service.Name), + "method": parser.CamelCase(rpc.Name), + "package": goPackage, + "pbRequest": parser.CamelCase(rpc.RequestType), + "pbResponse": parser.CamelCase(rpc.ReturnsType), + "hasComment": len(comment) > 0, + "comment": comment, + "hasReq": !rpc.StreamsRequest, + "notStream": !rpc.StreamsRequest && !rpc.StreamsReturns, + "streamBody": streamServer, + "isCallPkgSameToGrpcPkg": isCallPkgSameToGrpcPkg, }) if err != nil { return nil, err @@ -170,7 +189,7 @@ func (g *DefaultGenerator) genFunction(goPackage string, service parser.Service) return functions, nil } -func (g *DefaultGenerator) getInterfaceFuncs(goPackage string, service parser.Service) ([]string, error) { +func (g *Generator) getInterfaceFuncs(goPackage string, service parser.Service, isCallPkgSameToGrpcPkg bool) ([]string, error) { functions := make([]string, 0) for _, rpc := range service.RPC { @@ -181,6 +200,9 @@ func (g *DefaultGenerator) getInterfaceFuncs(goPackage string, service parser.Se comment := parser.GetComment(rpc.Doc()) streamServer := fmt.Sprintf("%s.%s_%s%s", goPackage, parser.CamelCase(service.Name), parser.CamelCase(rpc.Name), "Client") + if isCallPkgSameToGrpcPkg { + streamServer = fmt.Sprintf("%s_%s%s", parser.CamelCase(service.Name), parser.CamelCase(rpc.Name), "Client") + } buffer, err := util.With("interfaceFn").Parse(text).Execute( map[string]interface{}{ "hasComment": len(comment) > 0, diff --git a/tools/goctl/rpc/generator/genconfig.go b/tools/goctl/rpc/generator/genconfig.go index 61250035..46567a5a 100644 --- a/tools/goctl/rpc/generator/genconfig.go +++ b/tools/goctl/rpc/generator/genconfig.go @@ -24,7 +24,7 @@ type Config struct { // which contains the zrpc.RpcServerConf configuration item by default. // You can specify the naming style of the target file name through config.Config. For details, // see https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/config.go -func (g *DefaultGenerator) GenConfig(ctx DirContext, _ parser.Proto, cfg *conf.Config) error { +func (g *Generator) GenConfig(ctx DirContext, _ parser.Proto, cfg *conf.Config) error { dir := ctx.GetConfig() configFilename, err := format.FileNamingFormat(cfg.NamingFormat, "config") if err != nil { diff --git a/tools/goctl/rpc/generator/generator.go b/tools/goctl/rpc/generator/generator.go index 3c4aa0de..c66627cc 100644 --- a/tools/goctl/rpc/generator/generator.go +++ b/tools/goctl/rpc/generator/generator.go @@ -1,19 +1,34 @@ package generator import ( + "log" + conf "github.com/zeromicro/go-zero/tools/goctl/config" - "github.com/zeromicro/go-zero/tools/goctl/rpc/parser" + "github.com/zeromicro/go-zero/tools/goctl/env" + "github.com/zeromicro/go-zero/tools/goctl/util/console" ) -// Generator defines a generator interface to describe how to generate rpc service -type Generator interface { - Prepare() error - GenMain(ctx DirContext, proto parser.Proto, cfg *conf.Config) error - GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config) error - GenEtc(ctx DirContext, proto parser.Proto, cfg *conf.Config) error - GenConfig(ctx DirContext, proto parser.Proto, cfg *conf.Config) error - GenLogic(ctx DirContext, proto parser.Proto, cfg *conf.Config) error - GenServer(ctx DirContext, proto parser.Proto, cfg *conf.Config) error - GenSvc(ctx DirContext, proto parser.Proto, cfg *conf.Config) error - GenPb(ctx DirContext, protoImportPath []string, proto parser.Proto, cfg *conf.Config, c *ZRpcContext, goOptions ...string) error +// Generator defines the environment needs of rpc service generation +type Generator struct { + log console.Console + cfg *conf.Config +} + +// NewGenerator returns an instance of Generator +func NewGenerator(style string) *Generator { + cfg, err := conf.NewConfig(style) + if err != nil { + log.Fatalln(err) + } + log := console.NewColorConsole() + return &Generator{ + log: log, + cfg: cfg, + } +} + +// Prepare provides environment detection generated by rpc service, +// including go environment, protoc, whether protoc-gen-go is installed or not +func (g *Generator) Prepare() error { + return env.Prepare(true, true) } diff --git a/tools/goctl/rpc/generator/genetc.go b/tools/goctl/rpc/generator/genetc.go index efa99f49..4b9fb6fe 100644 --- a/tools/goctl/rpc/generator/genetc.go +++ b/tools/goctl/rpc/generator/genetc.go @@ -23,7 +23,7 @@ Etcd: // GenEtc generates the yaml configuration file of the rpc service, // including host, port monitoring configuration items and etcd configuration -func (g *DefaultGenerator) GenEtc(ctx DirContext, _ parser.Proto, cfg *conf.Config) error { +func (g *Generator) GenEtc(ctx DirContext, _ parser.Proto, cfg *conf.Config) error { dir := ctx.GetEtc() etcFilename, err := format.FileNamingFormat(cfg.NamingFormat, ctx.GetServiceName().Source()) if err != nil { diff --git a/tools/goctl/rpc/generator/genlogic.go b/tools/goctl/rpc/generator/genlogic.go index 135ca522..968c3720 100644 --- a/tools/goctl/rpc/generator/genlogic.go +++ b/tools/goctl/rpc/generator/genlogic.go @@ -50,7 +50,7 @@ func (l *{{.logicName}}) {{.method}} ({{if .hasReq}}in {{.request}}{{if .stream} ) // GenLogic generates the logic file of the rpc service, which corresponds to the RPC definition items in proto. -func (g *DefaultGenerator) GenLogic(ctx DirContext, proto parser.Proto, cfg *conf.Config) error { +func (g *Generator) GenLogic(ctx DirContext, proto parser.Proto, cfg *conf.Config) error { dir := ctx.GetLogic() service := proto.Service.Service.Name for _, rpc := range proto.Service.RPC { @@ -84,7 +84,7 @@ func (g *DefaultGenerator) GenLogic(ctx DirContext, proto parser.Proto, cfg *con return nil } -func (g *DefaultGenerator) genLogicFunction(serviceName, goPackage string, rpc *parser.RPC) (string, error) { +func (g *Generator) genLogicFunction(serviceName, goPackage string, rpc *parser.RPC) (string, error) { functions := make([]string, 0) text, err := pathx.LoadTemplate(category, logicFuncTemplateFileFile, logicFunctionTemplate) if err != nil { diff --git a/tools/goctl/rpc/generator/genmain.go b/tools/goctl/rpc/generator/genmain.go index d7e59ade..91bfae85 100644 --- a/tools/goctl/rpc/generator/genmain.go +++ b/tools/goctl/rpc/generator/genmain.go @@ -53,7 +53,7 @@ func main() { ` // GenMain generates the main file of the rpc service, which is an rpc service program call entry -func (g *DefaultGenerator) GenMain(ctx DirContext, proto parser.Proto, cfg *conf.Config) error { +func (g *Generator) GenMain(ctx DirContext, proto parser.Proto, cfg *conf.Config) error { mainFilename, err := format.FileNamingFormat(cfg.NamingFormat, ctx.GetServiceName().Source()) if err != nil { return err diff --git a/tools/goctl/rpc/generator/genpb.go b/tools/goctl/rpc/generator/genpb.go index 8e09b538..3656d3e5 100644 --- a/tools/goctl/rpc/generator/genpb.go +++ b/tools/goctl/rpc/generator/genpb.go @@ -1,118 +1,24 @@ package generator import ( - "bytes" - "errors" "fmt" "io/fs" "os" "path/filepath" "strings" - "github.com/zeromicro/go-zero/core/collection" - conf "github.com/zeromicro/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/rpc/execx" - "github.com/zeromicro/go-zero/tools/goctl/rpc/parser" ) const googleProtocGenGoErr = `--go_out: protoc-gen-go: plugins are not supported; use 'protoc --go-grpc_out=...' to generate gRPC` // GenPb generates the pb.go file, which is a layer of packaging for protoc to generate gprc, // but the commands and flags in protoc are not completely joined in goctl. At present, proto_path(-I) is introduced -func (g *DefaultGenerator) GenPb(ctx DirContext, protoImportPath []string, proto parser.Proto, _ *conf.Config, c *ZRpcContext, goOptions ...string) error { - if c != nil { - return g.genPbDirect(ctx, c) - } - - // deprecated: use genPbDirect instead. - dir := ctx.GetPb() - cw := new(bytes.Buffer) - directory, base := filepath.Split(proto.Src) - directory = filepath.Clean(directory) - cw.WriteString("protoc ") - protoImportPathSet := collection.NewSet() - isSamePackage := true - for _, ip := range protoImportPath { - pip := " --proto_path=" + ip - if protoImportPathSet.Contains(pip) { - continue - } - - abs, err := filepath.Abs(ip) - if err != nil { - return err - } - - if abs == directory { - isSamePackage = true - } else { - isSamePackage = false - } - - protoImportPathSet.AddStr(pip) - cw.WriteString(pip) - } - currentPath := " --proto_path=" + directory - if !protoImportPathSet.Contains(currentPath) { - cw.WriteString(currentPath) - } - - cw.WriteString(" " + proto.Name) - if strings.Contains(proto.GoPackage, "/") { - cw.WriteString(" --go_out=plugins=grpc:" + ctx.GetMain().Filename) - } else { - cw.WriteString(" --go_out=plugins=grpc:" + dir.Filename) - } - - // Compatible with version 1.4.0,github.com/golang/protobuf/protoc-gen-go@v1.4.0 - // --go_opt usage please see https://developers.google.com/protocol-buffers/docs/reference/go-generated#package - optSet := collection.NewSet() - for _, op := range goOptions { - opt := " --go_opt=" + op - if optSet.Contains(opt) { - continue - } - - optSet.AddStr(op) - cw.WriteString(" --go_opt=" + op) - } - - var currentFileOpt string - if !isSamePackage || (len(proto.GoPackage) > 0 && proto.GoPackage != proto.Package.Name) { - if filepath.IsAbs(proto.GoPackage) { - currentFileOpt = " --go_opt=M" + base + "=" + proto.GoPackage - } else if strings.Contains(proto.GoPackage, string(filepath.Separator)) { - currentFileOpt = " --go_opt=M" + base + "=./" + proto.GoPackage - } else { - currentFileOpt = " --go_opt=M" + base + "=../" + proto.GoPackage - } - } else { - currentFileOpt = " --go_opt=M" + base + "=." - } - - if !optSet.Contains(currentFileOpt) { - cw.WriteString(currentFileOpt) - } - - command := cw.String() - g.log.Debug(command) - _, err := execx.Run(command, "") - if err != nil { - if strings.Contains(err.Error(), googleProtocGenGoErr) { - return errors.New(`unsupported plugin protoc-gen-go which installed from the following source: -google.golang.org/protobuf/cmd/protoc-gen-go, -github.com/protocolbuffers/protobuf-go/cmd/protoc-gen-go; - -Please replace it by the following command, we recommend to use version before v1.3.5: -go get -u github.com/golang/protobuf/protoc-gen-go`) - } - - return err - } - return nil +func (g *Generator) GenPb(ctx DirContext, c *ZRpcContext) error { + return g.genPbDirect(ctx, c) } -func (g *DefaultGenerator) genPbDirect(ctx DirContext, c *ZRpcContext) error { +func (g *Generator) genPbDirect(ctx DirContext, c *ZRpcContext) error { g.log.Debug("[command]: %s", c.ProtocCmd) pwd, err := os.Getwd() if err != nil { @@ -126,7 +32,7 @@ func (g *DefaultGenerator) genPbDirect(ctx DirContext, c *ZRpcContext) error { return g.setPbDir(ctx, c) } -func (g *DefaultGenerator) setPbDir(ctx DirContext, c *ZRpcContext) error { +func (g *Generator) setPbDir(ctx DirContext, c *ZRpcContext) error { pbDir, err := findPbFile(c.GoOutput, false) if err != nil { return err diff --git a/tools/goctl/rpc/generator/genserver.go b/tools/goctl/rpc/generator/genserver.go index b5dafda9..587a04e6 100644 --- a/tools/goctl/rpc/generator/genserver.go +++ b/tools/goctl/rpc/generator/genserver.go @@ -48,7 +48,7 @@ func (s *{{.server}}Server) {{.method}} ({{if .notStream}}ctx context.Context,{{ ) // GenServer generates rpc server file, which is an implementation of rpc server -func (g *DefaultGenerator) GenServer(ctx DirContext, proto parser.Proto, cfg *conf.Config) error { +func (g *Generator) GenServer(ctx DirContext, proto parser.Proto, cfg *conf.Config) error { dir := ctx.GetServer() logicImport := fmt.Sprintf(`"%v"`, ctx.GetLogic().Package) svcImport := fmt.Sprintf(`"%v"`, ctx.GetSvc().Package) @@ -94,7 +94,7 @@ func (g *DefaultGenerator) GenServer(ctx DirContext, proto parser.Proto, cfg *co return err } -func (g *DefaultGenerator) genFunctions(goPackage string, service parser.Service) ([]string, error) { +func (g *Generator) genFunctions(goPackage string, service parser.Service) ([]string, error) { var functionList []string for _, rpc := range service.RPC { text, err := pathx.LoadTemplate(category, serverFuncTemplateFile, functionTemplate) diff --git a/tools/goctl/rpc/generator/gensvc.go b/tools/goctl/rpc/generator/gensvc.go index cd128cc6..c96726fd 100644 --- a/tools/goctl/rpc/generator/gensvc.go +++ b/tools/goctl/rpc/generator/gensvc.go @@ -28,7 +28,7 @@ func NewServiceContext(c config.Config) *ServiceContext { // GenSvc generates the servicecontext.go file, which is the resource dependency of a service, // such as rpc dependency, model dependency, etc. -func (g *DefaultGenerator) GenSvc(ctx DirContext, _ parser.Proto, cfg *conf.Config) error { +func (g *Generator) GenSvc(ctx DirContext, _ parser.Proto, cfg *conf.Config) error { dir := ctx.GetSvc() svcFilename, err := format.FileNamingFormat(cfg.NamingFormat, "service_context") if err != nil { diff --git a/tools/goctl/rpc/generator/prototmpl.go b/tools/goctl/rpc/generator/prototmpl.go index 526058f8..e858e9d8 100644 --- a/tools/goctl/rpc/generator/prototmpl.go +++ b/tools/goctl/rpc/generator/prototmpl.go @@ -12,6 +12,7 @@ import ( const rpcTemplateText = `syntax = "proto3"; package {{.package}}; +option go_package="./{{.package}}"; message Request { string ping = 1;