Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tool): support protobuf customized gen-path and add comments #1679

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 5 additions & 9 deletions tool/cmd/kitex/args/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,9 @@ func (a *Arguments) ParseArgs(version, curpath string, kitexArgs []string) (err
return err
}
// todo finish protobuf
if a.IDLType != "thrift" {
a.GenPath = generator.KitexGenPath
}
//if a.IDLType != "thrift" {
// a.GenPath = generator.KitexGenPath
//}
return a.checkPath(curpath)
}

Expand Down Expand Up @@ -399,12 +399,8 @@ func (a *Arguments) BuildCmd(out io.Writer) (*exec.Cmd, error) {
for _, inc := range a.Includes {
cmd.Args = append(cmd.Args, "-I", inc)
}
outPath := util.JoinPath(".", a.GenPath)
if a.Use == "" {
os.MkdirAll(outPath, 0o755)
} else {
outPath = "."
}
// using current path as the output path
outPath := "."
cmd.Args = append(cmd.Args,
"--plugin=protoc-gen-kitex="+exe,
"--kitex_out="+outPath,
Expand Down
44 changes: 32 additions & 12 deletions tool/internal_pkg/pluginmode/protoc/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"fmt"
"path"
"path/filepath"
"strconv"
"strings"
"text/template"

Expand All @@ -40,6 +41,7 @@ type protocPlugin struct {
kg generator.Generator
err error
importPaths map[string]string // file -> import path
namespaces map[string]string // file name -> go_package in idl
}

// Name implements the protobuf_generator.Plugin interface.
Expand All @@ -52,6 +54,7 @@ func (pp *protocPlugin) init() {
pp.Dependencies = map[string]string{
"proto": "google.golang.org/protobuf/proto",
}
pp.namespaces = make(map[string]string)
}

// parse the 'M*' option
Expand Down Expand Up @@ -121,17 +124,13 @@ func (pp *protocPlugin) GenerateFile(gen *protogen.Plugin, file *protogen.File)
return
}
gopkg := file.Proto.GetOptions().GetGoPackage()
if !strings.HasPrefix(gopkg, pp.PackagePrefix) {
log.Warnf("[WARN] %q is skipped because its import path %q is not located in ./kitex_gen. Change the go_package option or use '--protobuf M%s=A-Import-Path-In-kitex_gen' to override it if you want this file to be generated under kitex_gen.\n",
file.Proto.GetName(), gopkg, file.Proto.GetName())
return
}
log.Infof("[INFO] Generate %q at %q\n", file.Proto.GetName(), gopkg)

if parts := strings.Split(gopkg, ";"); len(parts) > 1 {
gopkg = parts[0] // remove package alias from file path
}
pp.Namespace = strings.TrimPrefix(gopkg, pp.PackagePrefix)
// extract original go_package from idl
pp.Namespace = pp.namespaces[file.Proto.GetName()]
pp.IDLName = util.IDLName(pp.Config.IDL)

ss := pp.convertTypes(file)
Expand Down Expand Up @@ -160,7 +159,7 @@ func (pp *protocPlugin) GenerateFile(gen *protogen.Plugin, file *protogen.File)
// generate service interface
if pp.err == nil {
fixed := *file
fixed.GeneratedFilenamePrefix = strings.TrimPrefix(fixed.GeneratedFilenamePrefix, pp.PackagePrefix)
fixed.GeneratedFilenamePrefix = strings.TrimPrefix(fixed.GeneratedFilenamePrefix, pp.ModuleName)
f := gengo.GenerateFile(gen, &fixed)
f.QualifiedGoIdent(protogen.GoIdent{GoImportPath: "context"})
if hasStreaming {
Expand All @@ -183,7 +182,7 @@ func (pp *protocPlugin) GenerateFile(gen *protogen.Plugin, file *protogen.File)
// generate fast api
if !pp.Config.NoFastAPI && pp.err == nil {
fixed := *file
fixed.GeneratedFilenamePrefix = strings.TrimPrefix(fixed.GeneratedFilenamePrefix, pp.PackagePrefix)
fixed.GeneratedFilenamePrefix = strings.TrimPrefix(fixed.GeneratedFilenamePrefix, pp.ModuleName)
genfastpb.GenerateFile(gen, &fixed)
}
}
Expand Down Expand Up @@ -270,6 +269,7 @@ func (pp *protocPlugin) convertTypes(file *protogen.File) (ss []*generator.Servi
PkgRefName: goSanitized(path.Base(pth)),
ImportPath: pth,
}
refPkgMap := make(map[string]map[string]int)
for _, service := range file.Services {
si := &generator.ServiceInfo{
PkgInfo: pi,
Expand All @@ -278,8 +278,8 @@ func (pp *protocPlugin) convertTypes(file *protogen.File) (ss []*generator.Servi
}
si.ServiceTypeName = func() string { return si.PkgRefName + "." + si.ServiceName }
for _, m := range service.Methods {
req := pp.convertParameter(m.Input, "Req")
res := pp.convertParameter(m.Output, "Resp")
req := pp.convertParameter(m.Input, "Req", refPkgMap)
res := pp.convertParameter(m.Output, "Resp", refPkgMap)

methodName := m.GoName
mi := &generator.MethodInfo{
Expand Down Expand Up @@ -379,9 +379,25 @@ func (pp *protocPlugin) getCombineServiceName(name string, svcs []*generator.Ser
return name
}

func (pp *protocPlugin) convertParameter(msg *protogen.Message, paramName string) *generator.Parameter {
func (pp *protocPlugin) convertParameter(msg *protogen.Message, paramName string, refPkgMap map[string]map[string]int) *generator.Parameter {
importPath := pp.fixImport(msg.GoIdent.GoImportPath.String())
pkgRefName := goSanitized(path.Base(importPath))
importPkg, ok := refPkgMap[pkgRefName]
if !ok {
refPkgMap[pkgRefName] = map[string]int{
importPath: 0,
}
} else {
if idx, ok := importPkg[importPath]; ok {
if idx != 0 {
pkgRefName = pkgRefName + strconv.Itoa(idx)
}
} else {
newIdx := len(importPkg)
pkgRefName = pkgRefName + strconv.Itoa(newIdx)
importPkg[importPath] = newIdx
}
}
res := &generator.Parameter{
Deps: []generator.PkgInfo{
{
Expand Down Expand Up @@ -430,8 +446,12 @@ func (pp *protocPlugin) makeInterfaces(gf *protogen.GeneratedFile, file *protoge

func (pp *protocPlugin) adjustPath(path string) (ret string) {
cur, _ := filepath.Abs(".")
fileRelPath, _ := filepath.Rel(cur, path)
return fileRelPath
if pp.Config.Use == "" {
cur = util.JoinPath(cur, generator.KitexGenPath)
// change kitex_gen to custom path
genPath := util.CombineOutputPath(pp.GenPath, generator.KitexGenPath)
cur = util.JoinPath(cur, genPath)
}
if filepath.IsAbs(path) {
path, _ = filepath.Rel(cur, path)
Expand Down
7 changes: 4 additions & 3 deletions tool/internal_pkg/pluginmode/protoc/protoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,10 @@ func GenKitex(req *pluginpb.CodeGeneratorRequest, opts protogen.Options) (*plugi
}
gopkg = f.GetOptions().GetGoPackage()
}
if path, ok := pe.getImportPath(gopkg); ok {
f.Options.GoPackage = &path
log.Infof("[INFO] update import path for %q: %q -> %q\n", f.GetName(), gopkg, path)
if dirPath, ns, ok := pe.getImportPathAndNamespace(gopkg); ok {
f.Options.GoPackage = &dirPath
pp.namespaces[f.GetName()] = ns
log.Infof("[INFO] update import path for %q: %q -> %q\n", f.GetName(), gopkg, dirPath)
}
}

Expand Down
26 changes: 20 additions & 6 deletions tool/internal_pkg/pluginmode/protoc/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,34 @@ type pathElements struct {
prefix string // prefix of import path for generated codes
}

func (p *pathElements) getImportPath(pkg string) (path string, ok bool) {
parts := strings.Split(pkg, "/")
// getImportPath returns the complete import path for the given go_package defined in pb idl
func (p *pathElements) getImportPath(goPackage string) (path string, ok bool) {
parts := strings.Split(goPackage, "/")
if len(parts) == 0 {
// malformed import path
return "", false
}

if strings.HasPrefix(pkg, p.prefix) {
return pkg, true
if strings.HasPrefix(goPackage, p.prefix) {
return goPackage, true
}
if strings.Contains(parts[0], ".") || (p.module != "" && strings.HasPrefix(pkg, p.module)) {
if strings.Contains(parts[0], ".") || (p.module != "" && strings.HasPrefix(goPackage, p.module)) {
// already a complete import path, but outside the target path
return "", false
}
// incomplete import path
return util.JoinPath(p.prefix, pkg), true

return util.JoinPath(p.prefix, goPackage), true
}

func (p *pathElements) getImportPathAndNamespace(goPackage string) (path string, ns string, ok bool) {
parts := strings.Split(goPackage, "/")
if len(parts) == 0 {
return "", "", false
}
// todo: consider complete path
if strings.HasPrefix(goPackage, p.prefix) {
return goPackage, strings.TrimPrefix(goPackage, p.prefix), true
}
return util.CombineOutputPath(p.prefix, goPackage), goPackage, true
}