feat: Support for multiple rpc service generation and rpc grouping (#1972)

* Add group & compatible flag

* Add group & compatible flag

* Support for multiple rpc service generation and rpc grouping

* Support for multiple rpc service generation and rpc grouping

* Format code

* Format code

* Add comments

* Fix unit test

* Refactor function name

* Add example & Update grpc readme

* go mod tidy

* update mod

* update mod
This commit is contained in:
anqiansong
2022-07-21 12:47:46 +08:00
committed by GitHub
parent 1b51d0ce82
commit ca3c687f1c
47 changed files with 2305 additions and 377 deletions

View File

@@ -1,8 +1,6 @@
package parser
import (
"errors"
"fmt"
"go/token"
"os"
"path/filepath"
@@ -14,7 +12,7 @@ import (
)
type (
// DefaultProtoParser types a empty struct
// DefaultProtoParser types an empty struct
DefaultProtoParser struct{}
)
@@ -25,7 +23,7 @@ func NewDefaultProtoParser() *DefaultProtoParser {
// Parse provides to parse the proto file into a golang structure,
// which is convenient for subsequent rpc generation and use
func (p *DefaultProtoParser) Parse(src string) (Proto, error) {
func (p *DefaultProtoParser) Parse(src string, multiple ...bool) (Proto, error) {
var ret Proto
abs, err := filepath.Abs(src)
@@ -45,7 +43,7 @@ func (p *DefaultProtoParser) Parse(src string) (Proto, error) {
return ret, err
}
var serviceList []Service
var serviceList Services
proto.Walk(
set,
proto.WithImport(func(i *proto.Import) {
@@ -76,31 +74,18 @@ func (p *DefaultProtoParser) Parse(src string) (Proto, error) {
}
}),
)
if len(serviceList) == 0 {
return ret, errors.New("rpc service not found")
if err = serviceList.validate(abs, multiple...); err != nil {
return ret, err
}
if len(serviceList) > 1 {
return ret, errors.New("only one service expected")
}
service := serviceList[0]
name := filepath.Base(abs)
for _, rpc := range service.RPC {
if strings.Contains(rpc.RequestType, ".") {
return ret, fmt.Errorf("line %v:%v, request type must defined in %s", rpc.Position.Line, rpc.Position.Column, name)
}
if strings.Contains(rpc.ReturnsType, ".") {
return ret, fmt.Errorf("line %v:%v, returns type must defined in %s", rpc.Position.Line, rpc.Position.Column, name)
}
}
if len(ret.GoPackage) == 0 {
ret.GoPackage = ret.Package.Name
}
ret.PbPackage = GoSanitized(filepath.Base(ret.GoPackage))
ret.Src = abs
ret.Name = name
ret.Service = service
ret.Name = filepath.Base(abs)
ret.Service = serviceList
return ret, nil
}

View File

@@ -19,17 +19,22 @@ func TestDefaultProtoParse(t *testing.T) {
assert.Equal(t, "test", data.Package.Name)
assert.Equal(t, true, data.GoPackage == "go")
assert.Equal(t, true, data.PbPackage == "_go")
assert.Equal(t, []string{"Inline", "Inner", "TestMessage", "TestReply", "TestReq"}, func() []string {
var list []string
for _, item := range data.Message {
list = append(list, item.Name)
}
sort.Strings(list)
return list
}())
assert.Equal(t, []string{"Inline", "Inner", "TestMessage", "TestReply", "TestReq"},
func() []string {
var list []string
for _, item := range data.Message {
list = append(list, item.Name)
}
sort.Strings(list)
return list
}())
assert.Equal(t, true, func() bool {
s := data.Service
if len(data.Service) != 1 {
return false
}
s := data.Service[0]
if s.Name != "TestService" {
return false
}

View File

@@ -9,5 +9,5 @@ type Proto struct {
GoPackage string
Import []Import
Message []Message
Service Service
Service Services
}

View File

@@ -1,10 +1,54 @@
package parser
import "github.com/emicklei/proto"
import (
"errors"
"fmt"
"path/filepath"
"strings"
// Service describes the rpc service, which is the relevant
// content after the translation of the proto file
type Service struct {
*proto.Service
RPC []*RPC
"github.com/emicklei/proto"
)
type (
// Services is a slice of Service.
Services []Service
// Service describes the rpc service, which is the relevant
// content after the translation of the proto file
Service struct {
*proto.Service
RPC []*RPC
}
)
func (s Services) validate(filename string, multipleOpt ...bool) error {
if len(s) == 0 {
return errors.New("rpc service not found")
}
var multiple bool
for _, c := range multipleOpt {
multiple = c
}
if !multiple && len(s) > 1 {
return errors.New("only one service expected")
}
name := filepath.Base(filename)
for _, service := range s {
for _, rpc := range service.RPC {
if strings.Contains(rpc.RequestType, ".") {
return fmt.Errorf("line %v:%v, request type must defined in %s",
rpc.Position.Line,
rpc.Position.Column, name)
}
if strings.Contains(rpc.ReturnsType, ".") {
return fmt.Errorf("line %v:%v, returns type must defined in %s",
rpc.Position.Line,
rpc.Position.Column, name)
}
}
}
return nil
}