feat: Remove command `goctl rpc proto` (#1665)

* Fix goctl completion expression

* Fix code generation error if the pkg of pb/grpc is same to zrpc call client pkg

* Remove deprecated comment on action goctl rpc new

* Remove zrpc code generation on action goctl rpc proto

* Remove zrpc code generation on action goctl rpc proto

* Remove Generator interface

Co-authored-by: anqiansong <anqiansong@bytedance.com>
master
anqiansong 3 years ago committed by GitHub
parent 448029aa4b
commit 227104d7d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

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

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

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

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

@ -1,6 +1,7 @@
syntax = "proto3";
package common;
option go_package="./common";
message User {
string name = 1;

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

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

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

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

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

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

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

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

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

@ -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.0github.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

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

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

@ -12,6 +12,7 @@ import (
const rpcTemplateText = `syntax = "proto3";
package {{.package}};
option go_package="./{{.package}}";
message Request {
string ping = 1;

Loading…
Cancel
Save