gobuf/gobuf.go

168 lines
3.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package gobuf
import (
"bytes"
"fmt"
"io"
"os"
"path/filepath"
"github.com/emicklei/proto"
"gitter.top/sync/proto-contrib/pkg/protofmt"
)
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
}
func (parser *Parser) CreateFile(filename string) error {
// 检查文件是否存在
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内容此步骤会创建文件
baseContent := []byte("syntax = \"proto3\";\npackage proto.v1;\noption go_package = \"projects/gen;genv1\";\n")
if err := os.WriteFile(filename, baseContent, os.ModePerm); err != nil {
return err
}
return nil
}
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{
" @desc: 描述",
" @author: 作者",
" @method: GET",
" @api: /" + calm2Case(rpcName),
},
},
Name: rpcName,
RequestType: toUpperCamlCase(serviceName) + toUpperCamlCase(rpcName) + "Req",
ReturnsType: toUpperCamlCase(serviceName) + toUpperCamlCase(rpcName) + "Resp",
Parent: service,
})
}))
parser.proto.Elements = append(parser.proto.Elements, &proto.Message{
Name: toUpperCamlCase(serviceName) + toUpperCamlCase(rpcName) + "Req",
Parent: parser.proto,
})
parser.proto.Elements = append(parser.proto.Elements, &proto.Message{
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,
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
}