Goctl rpc patch (#117)

* remove mock generation

* add: proto project import

* update document

* remove mock generation

* add: proto project import

* update document

* remove NL

* update document

* optimize code

* add test

* add test
This commit is contained in:
Keson
2020-10-10 16:19:46 +08:00
committed by GitHub
parent c32759d735
commit 0a9c427443
26 changed files with 1394 additions and 230 deletions

View File

@@ -1,68 +1,37 @@
package gen
import (
"errors"
"bytes"
"fmt"
"io/ioutil"
"path/filepath"
"strings"
"github.com/dsymonds/gotoc/parser"
"github.com/tal-tech/go-zero/core/lang"
"github.com/tal-tech/go-zero/core/collection"
"github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
astParser "github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
)
const (
protocCmd = "protoc"
grpcPluginCmd = "--go_out=plugins=grpc"
)
func (g *defaultRpcGenerator) genPb() error {
importPath, filename := filepath.Split(g.Ctx.ProtoFileSrc)
tree, err := parser.ParseFiles([]string{filename}, []string{importPath})
if err != nil {
return err
}
if len(tree.Files) == 0 {
return errors.New("proto ast parse failed")
}
file := tree.Files[0]
if len(file.Package) == 0 {
return errors.New("expected package, but nothing found")
}
targetStruct := make(map[string]lang.PlaceholderType)
for _, item := range file.Messages {
if len(item.Messages) > 0 {
return fmt.Errorf(`line %v: unexpected inner message near: "%v""`, item.Messages[0].Position.Line, item.Messages[0].Name)
}
name := stringx.From(item.Name)
if _, ok := targetStruct[name.Lower()]; ok {
return fmt.Errorf("line %v: duplicate %v", item.Position.Line, name)
}
targetStruct[name.Lower()] = lang.Placeholder
}
pbPath := g.dirM[dirPb]
protoFileName := filepath.Base(g.Ctx.ProtoFileSrc)
err = g.protocGenGo(pbPath)
imports, containsAny, err := parser.ParseImport(g.Ctx.ProtoFileSrc)
if err != nil {
return err
}
pbGo := strings.TrimSuffix(protoFileName, ".proto") + ".pb.go"
pbFile := filepath.Join(pbPath, pbGo)
bts, err := ioutil.ReadFile(pbFile)
err = g.protocGenGo(pbPath, imports)
if err != nil {
return err
}
aspParser := astParser.NewAstParser(bts, targetStruct, g.Ctx.Console)
ast, err := aspParser.Parse()
ast, err := parser.Transfer(g.Ctx.ProtoFileSrc, pbPath, imports, g.Ctx.Console)
if err != nil {
return err
}
ast.ContainsAny = containsAny
if len(ast.Service) == 0 {
return fmt.Errorf("service not found")
@@ -71,10 +40,35 @@ func (g *defaultRpcGenerator) genPb() error {
return nil
}
func (g *defaultRpcGenerator) protocGenGo(target string) error {
src := filepath.Dir(g.Ctx.ProtoFileSrc)
sh := fmt.Sprintf(`protoc -I=%s --go_out=plugins=grpc:%s %s`, src, target, g.Ctx.ProtoFileSrc)
stdout, err := execx.Run(sh, "")
func (g *defaultRpcGenerator) protocGenGo(target string, imports []*parser.Import) error {
dir := filepath.Dir(g.Ctx.ProtoFileSrc)
// cmd join,see the document of proto generating class @https://developers.google.com/protocol-buffers/docs/proto3#generating
// template: protoc -I=${import_path} -I=${other_import_path} -I=${...} --go_out=plugins=grpc,M${pb_package_kv}, M${...} :${target_dir}
// eg: protoc -I=${GOPATH}/src -I=. example.proto --go_out=plugins=grpc,Mbase/base.proto=github.com/go-zero/base.proto:.
// note: the external import out of the project which are found in ${GOPATH}/src so far.
buffer := new(bytes.Buffer)
buffer.WriteString(protocCmd + " ")
targetImportFiltered := collection.NewSet()
for _, item := range imports {
buffer.WriteString(fmt.Sprintf("-I=%s ", item.OriginalDir))
if len(item.BridgeImport) == 0 {
continue
}
targetImportFiltered.AddStr(item.BridgeImport)
}
buffer.WriteString("-I=${GOPATH}/src ")
buffer.WriteString(fmt.Sprintf("-I=%s %s ", dir, g.Ctx.ProtoFileSrc))
buffer.WriteString(grpcPluginCmd)
if targetImportFiltered.Count() > 0 {
buffer.WriteString(fmt.Sprintf(",%v", strings.Join(targetImportFiltered.KeysStr(), ",")))
}
buffer.WriteString(":" + target)
g.Ctx.Debug("-> " + buffer.String())
stdout, err := execx.Run(buffer.String(), "")
if err != nil {
return err
}