2023-03-21 01:08:22 +08:00
|
|
|
|
package gobuf
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
2023-03-21 01:20:24 +08:00
|
|
|
|
"fmt"
|
2023-03-21 01:08:22 +08:00
|
|
|
|
"io"
|
|
|
|
|
"os"
|
2024-03-20 23:35:52 +08:00
|
|
|
|
"path/filepath"
|
2023-03-21 01:20:24 +08:00
|
|
|
|
|
|
|
|
|
"github.com/emicklei/proto"
|
|
|
|
|
"gitter.top/sync/proto-contrib/pkg/protofmt"
|
2023-03-21 01:08:22 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Parser struct {
|
|
|
|
|
filename string
|
|
|
|
|
rawData io.Reader
|
|
|
|
|
proto *proto.Proto
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewParser(file string) (*Parser, error) {
|
|
|
|
|
reader, err := os.Open(file)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
defer reader.Close()
|
|
|
|
|
|
|
|
|
|
parser := proto.NewParser(reader)
|
|
|
|
|
definition, err := parser.Parse()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return &Parser{
|
|
|
|
|
filename: file,
|
|
|
|
|
rawData: reader,
|
|
|
|
|
proto: definition,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-20 23:45:19 +08:00
|
|
|
|
func CreateFile(filename string) error {
|
2024-03-20 23:35:52 +08:00
|
|
|
|
// 检查文件是否存在
|
|
|
|
|
if _, err := os.Stat(filename); err == nil {
|
|
|
|
|
return nil
|
|
|
|
|
} else if !os.IsNotExist(err) {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 确保文件所在的目录存在
|
|
|
|
|
baseDir := filepath.Dir(filename)
|
|
|
|
|
if baseDir != "." && baseDir != ".." {
|
|
|
|
|
if err := os.MkdirAll(baseDir, os.ModePerm); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 写入基础的protobuf内容,此步骤会创建文件
|
2024-03-22 00:06:16 +08:00
|
|
|
|
baseContent := []byte("syntax = \"proto3\";\n\npackage proto.v1;\n\noption go_package = \"projects/gen;genv1\";\n")
|
2024-03-20 23:35:52 +08:00
|
|
|
|
if err := os.WriteFile(filename, baseContent, os.ModePerm); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-21 01:08:22 +08:00
|
|
|
|
func (parser *Parser) ExistService(serviceName string) bool {
|
|
|
|
|
var result bool
|
|
|
|
|
proto.Walk(parser.proto, proto.WithService(func(service *proto.Service) {
|
|
|
|
|
if service.Name == serviceName {
|
|
|
|
|
result = true
|
|
|
|
|
}
|
|
|
|
|
}))
|
|
|
|
|
return result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (parser *Parser) ExistMessage(messageName string) bool {
|
|
|
|
|
var result bool
|
|
|
|
|
proto.Walk(parser.proto, proto.WithMessage(func(message *proto.Message) {
|
|
|
|
|
if message.Name == messageName {
|
|
|
|
|
result = true
|
|
|
|
|
}
|
|
|
|
|
}))
|
|
|
|
|
return result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (parser *Parser) ExistRPC(serviceName, rpcName string) bool {
|
|
|
|
|
var result bool
|
|
|
|
|
proto.Walk(parser.proto, proto.WithService(func(service *proto.Service) {
|
|
|
|
|
if service.Name != serviceName {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
for _, element := range service.Elements {
|
|
|
|
|
if rpc, ok := element.(*proto.RPC); ok {
|
|
|
|
|
if rpc.Name == rpcName {
|
|
|
|
|
result = true
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}))
|
|
|
|
|
return result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (parser *Parser) AddRPC(serviceName, rpcName string) error {
|
|
|
|
|
proto.Walk(parser.proto, proto.WithService(func(service *proto.Service) {
|
|
|
|
|
if service.Name != serviceName {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
service.Elements = append(service.Elements, &proto.RPC{
|
|
|
|
|
Comment: &proto.Comment{
|
|
|
|
|
Lines: []string{
|
2023-03-21 01:20:24 +08:00
|
|
|
|
" @desc: 描述",
|
|
|
|
|
" @author: 作者",
|
|
|
|
|
" @method: GET",
|
2023-03-21 01:08:22 +08:00
|
|
|
|
" @api: /" + calm2Case(rpcName),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
Name: rpcName,
|
2023-03-21 01:20:24 +08:00
|
|
|
|
RequestType: toUpperCamlCase(serviceName) + toUpperCamlCase(rpcName) + "Req",
|
|
|
|
|
ReturnsType: toUpperCamlCase(serviceName) + toUpperCamlCase(rpcName) + "Resp",
|
2023-03-21 01:08:22 +08:00
|
|
|
|
Parent: service,
|
|
|
|
|
})
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
parser.proto.Elements = append(parser.proto.Elements, &proto.Message{
|
2023-03-21 01:20:24 +08:00
|
|
|
|
Name: toUpperCamlCase(serviceName) + toUpperCamlCase(rpcName) + "Req",
|
2023-03-21 01:08:22 +08:00
|
|
|
|
Parent: parser.proto,
|
|
|
|
|
})
|
|
|
|
|
parser.proto.Elements = append(parser.proto.Elements, &proto.Message{
|
2023-03-21 01:20:24 +08:00
|
|
|
|
Name: toUpperCamlCase(serviceName) + toUpperCamlCase(rpcName) + "Resp",
|
|
|
|
|
Parent: parser.proto,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return parser.writeSync()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (parser *Parser) AddService(serviceName string) error {
|
|
|
|
|
if parser.ExistService(serviceName) {
|
|
|
|
|
return fmt.Errorf("service name exist")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parser.proto.Elements = append(parser.proto.Elements, &proto.Service{
|
|
|
|
|
Comment: &proto.Comment{
|
|
|
|
|
Lines: []string{
|
|
|
|
|
" @route_group: true",
|
|
|
|
|
" @base_url: /v1/" + calm2Case(serviceName),
|
|
|
|
|
" @gen_to: ./services/controller/v1/" + calm2Case(serviceName) + "_controller.go",
|
|
|
|
|
" @rpc_to: ./services/microservice/v1/" + calm2Case(serviceName) + "_service.go",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
Name: serviceName,
|
2023-03-21 01:08:22 +08:00
|
|
|
|
Parent: parser.proto,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return parser.writeSync()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (parser *Parser) writeSync() error {
|
|
|
|
|
var buf = new(bytes.Buffer)
|
|
|
|
|
|
|
|
|
|
protofmt.NewFormatter(buf, " ").Format(parser.proto) // 1 tab
|
|
|
|
|
|
|
|
|
|
// write back to input
|
|
|
|
|
if err := os.WriteFile(parser.filename, buf.Bytes(), os.ModePerm); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|