From 9f2dd3ed3591c2883e203f85be8e514a3acaa6c4 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Thu, 25 Feb 2021 14:19:09 +0300 Subject: [PATCH] allow to generate standalone code Signed-off-by: Vasiliy Tolstov --- chi.go | 7 +++- gorilla.go | 7 +++- http.go | 97 +++--------------------------------------------------- main.go | 26 +++++++-------- micro.go | 7 +++- rpc.go | 6 +++- util.go | 74 ++++++++++++++++++++--------------------- 7 files changed, 76 insertions(+), 148 deletions(-) diff --git a/chi.go b/chi.go index 6d319c3..55b664c 100644 --- a/chi.go +++ b/chi.go @@ -23,7 +23,12 @@ func (g *Generator) chiGenerate(component string, plugin *protogen.Plugin) error chiPackageFiles[file.GoPackageName] = struct{}{} gname := "micro" + "_" + component + ".pb.go" - gfile := plugin.NewGeneratedFile(gname, file.GoImportPath) + + path := file.GoImportPath + if g.standalone { + path = "." + } + gfile := plugin.NewGeneratedFile(gname, path) gfile.P("// Code generated by protoc-gen-micro") gfile.P("package ", file.GoPackageName) diff --git a/gorilla.go b/gorilla.go index f5b2e30..c671612 100644 --- a/gorilla.go +++ b/gorilla.go @@ -23,7 +23,12 @@ func (g *Generator) gorillaGenerate(component string, plugin *protogen.Plugin) e gorillaPackageFiles[file.GoPackageName] = struct{}{} gname := "micro" + "_" + component + ".pb.go" - gfile := plugin.NewGeneratedFile(gname, file.GoImportPath) + + path := file.GoImportPath + if g.standalone { + path = "." + } + gfile := plugin.NewGeneratedFile(gname, path) gfile.P("// Code generated by protoc-gen-micro") gfile.P("package ", file.GoPackageName) diff --git a/http.go b/http.go index 8b20c87..9a18680 100644 --- a/http.go +++ b/http.go @@ -1,21 +1,10 @@ package main import ( - "strings" - - openapi_options "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options" "google.golang.org/protobuf/compiler/protogen" - "google.golang.org/protobuf/proto" ) -type Error struct { - packageName string - types []string -} - func (g *Generator) httpGenerate(component string, plugin *protogen.Plugin) error { - errors := make(map[string]struct{}) - for _, file := range plugin.Files { if !file.Generate { continue @@ -25,7 +14,11 @@ func (g *Generator) httpGenerate(component string, plugin *protogen.Plugin) erro } gname := file.GeneratedFilenamePrefix + "_micro_" + component + ".pb.go" - gfile := plugin.NewGeneratedFile(gname, file.GoImportPath) + path := file.GoImportPath + if g.standalone { + path = "." + } + gfile := plugin.NewGeneratedFile(gname, path) gfile.P("// Code generated by protoc-gen-micro") gfile.P("// source: ", *file.Proto.Name) @@ -44,88 +37,8 @@ func (g *Generator) httpGenerate(component string, plugin *protogen.Plugin) erro generateServiceServer(gfile, service) generateServiceServerMethods(gfile, service) generateServiceRegister(gfile, service) - if component == "http" { - for k, v := range getErrors(service) { - errors[k] = v - } - } - } - } - - files := make(map[string]*Error) - for _, file := range plugin.Files { - if !file.Generate { - continue - } - - err, ok := files[file.GeneratedFilenamePrefix] - if !ok { - err = &Error{packageName: string(file.GoPackageName)} - } - fok := false - for _, message := range file.Messages { - if _, ok := errors["."+string(message.Desc.FullName())]; ok { - fok = true - err.types = append(err.types, string(message.Desc.FullName())) - } - } - if fok { - files[file.GeneratedFilenamePrefix] = err - } - } - - for _, file := range plugin.Files { - for efile, err := range files { - if file.GeneratedFilenamePrefix != efile { - continue - } - gfile := plugin.NewGeneratedFile(efile+"_micro_errors.pb.go", file.GoImportPath) - generateServiceErrors(gfile, err) } } return nil } - -func getErrors(service *protogen.Service) map[string]struct{} { - errors := make(map[string]struct{}) - - for _, method := range service.Methods { - if method.Desc.Options() == nil { - continue - } - if !proto.HasExtension(method.Desc.Options(), openapi_options.E_Openapiv2Operation) { - continue - } - - opts := proto.GetExtension(method.Desc.Options(), openapi_options.E_Openapiv2Operation) - if opts == nil { - continue - } - - r := opts.(*openapi_options.Operation) - for _, response := range r.Responses { - if response.Schema == nil || response.Schema.JsonSchema == nil { - continue - } - errors[response.Schema.JsonSchema.Ref] = struct{}{} - } - } - - return errors -} - -func generateServiceErrors(gfile *protogen.GeneratedFile, err *Error) { - gfile.P("// Code generated by protoc-gen-micro") - gfile.P("package ", err.packageName) - gfile.P() - - gfile.Import(fmtPackage) - - for _, typ := range err.types { - gfile.P("func (err *", typ[strings.LastIndex(typ, ".")+1:], ") Error() string {") - gfile.P(`return `, fmtPackage.Ident("Sprintf"), `("%#v", err)`) - gfile.P("}") - gfile.P() - } -} diff --git a/main.go b/main.go index 8465d5d..adfd7e8 100644 --- a/main.go +++ b/main.go @@ -9,23 +9,14 @@ import ( ) var ( - flags flag.FlagSet - flagDebug *bool - flagComponents *string - flagPaths *string - flagModule *string + flagDebug = flag.Bool("debug", false, "") + flagStandalone = flag.Bool("standalone", false, "") + flagComponents = flag.String("components", "micro|rpc", "") ) -func init() { - flagDebug = flags.Bool("debug", false, "") - flagComponents = flags.String("components", "micro|rpc", "") - flagPaths = flag.String("paths", "", "") - flagModule = flag.String("module", "", "") -} - func main() { opts := &protogen.Options{ - ParamFunc: flags.Set, + ParamFunc: flag.CommandLine.Set, } g := &Generator{} @@ -34,13 +25,20 @@ func main() { } type Generator struct { + components string + standalone bool + debug bool } func (g *Generator) Generate(plugin *protogen.Plugin) error { var err error + g.standalone = *flagStandalone + g.debug = *flagDebug + g.components = *flagComponents + // Protoc passes a slice of File structs for us to process - for _, component := range strings.Split(*flagComponents, "|") { + for _, component := range strings.Split(g.components, "|") { switch component { case "micro": err = g.microGenerate(component, plugin) diff --git a/micro.go b/micro.go index 991443f..98f70f4 100644 --- a/micro.go +++ b/micro.go @@ -14,7 +14,12 @@ func (g *Generator) microGenerate(component string, plugin *protogen.Plugin) err } gname := file.GeneratedFilenamePrefix + "_" + component + ".pb.go" - gfile := plugin.NewGeneratedFile(gname, file.GoImportPath) + + path := file.GoImportPath + if g.standalone { + path = "." + } + gfile := plugin.NewGeneratedFile(gname, path) gfile.P("// Code generated by protoc-gen-micro") gfile.P("// source: ", *file.Proto.Name) diff --git a/rpc.go b/rpc.go index 6d99932..ba5e4dd 100644 --- a/rpc.go +++ b/rpc.go @@ -14,7 +14,11 @@ func (g *Generator) rpcGenerate(component string, plugin *protogen.Plugin) error } gname := file.GeneratedFilenamePrefix + "_micro_" + component + ".pb.go" - gfile := plugin.NewGeneratedFile(gname, file.GoImportPath) + path := file.GoImportPath + if g.standalone { + path = "." + } + gfile := plugin.NewGeneratedFile(gname, path) gfile.P("// Code generated by protoc-gen-micro") gfile.P("// source: ", *file.Proto.Name) diff --git a/util.go b/util.go index 0161e25..f2d0f63 100644 --- a/util.go +++ b/util.go @@ -31,21 +31,20 @@ func unexport(s string) string { } func generateServiceClient(gfile *protogen.GeneratedFile, service *protogen.Service) { - serviceName := strings.TrimSuffix(service.GoName, "Service") - gfile.P("type ", unexport(serviceName), "Service struct {") + serviceName := service.GoName + gfile.P("type ", unexport(serviceName), "Client struct {") gfile.P("c ", microClientPackage.Ident("Client")) gfile.P("name string") gfile.P("}") - gfile.P("// New", serviceName, "Service create new service client") - gfile.P("func New", serviceName, "Service(name string, c ", microClientPackage.Ident("Client"), ") ", serviceName, "Service {") - gfile.P("return &", unexport(serviceName), "Service{c: c, name: name}") + gfile.P("func New", serviceName, "Client(name string, c ", microClientPackage.Ident("Client"), ") ", serviceName, "Client {") + gfile.P("return &", unexport(serviceName), "Client{c: c, name: name}") gfile.P("}") gfile.P() } func generateServiceClientMethods(gfile *protogen.GeneratedFile, service *protogen.Service, http bool) { - serviceName := strings.TrimSuffix(service.GoName, "Service") + serviceName := service.GoName for _, method := range service.Methods { methodName := fmt.Sprintf("%s.%s", serviceName, method.GoName) generateClientFuncSignature(gfile, serviceName, method) @@ -104,18 +103,18 @@ func generateServiceClientMethods(gfile *protogen.GeneratedFile, service *protog gfile.P("return nil, err") gfile.P("}") } - gfile.P("return &", unexport(serviceName), "Service", method.GoName, "{stream}, nil") + gfile.P("return &", unexport(serviceName), "Client", method.GoName, "{stream}, nil") gfile.P("}") gfile.P() if method.Desc.IsStreamingServer() || method.Desc.IsStreamingClient() { - gfile.P("type ", unexport(serviceName), "Service", method.GoName, " struct {") + gfile.P("type ", unexport(serviceName), "Client", method.GoName, " struct {") gfile.P("stream ", microClientPackage.Ident("Stream")) gfile.P("}") } if method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() { - gfile.P("func (s *", unexport(serviceName), "Service", method.GoName, ") RecvAndClose() (*", gfile.QualifiedGoIdent(method.Output.GoIdent), ", error) {") + gfile.P("func (s *", unexport(serviceName), "Client", method.GoName, ") RecvAndClose() (*", gfile.QualifiedGoIdent(method.Output.GoIdent), ", error) {") gfile.P("msg := &", gfile.QualifiedGoIdent(method.Output.GoIdent), "{}") gfile.P("err := s.RecvMsg(msg)") gfile.P("if err == nil {") @@ -129,32 +128,32 @@ func generateServiceClientMethods(gfile *protogen.GeneratedFile, service *protog } gfile.P() - gfile.P("func (s *", unexport(serviceName), "Service", method.GoName, ") Close() error {") + gfile.P("func (s *", unexport(serviceName), "Client", method.GoName, ") Close() error {") gfile.P("return s.stream.Close()") gfile.P("}") gfile.P() - gfile.P("func (s *", unexport(serviceName), "Service", method.GoName, ") Context() ", contextPackage.Ident("Context"), " {") + gfile.P("func (s *", unexport(serviceName), "Client", method.GoName, ") Context() ", contextPackage.Ident("Context"), " {") gfile.P("return s.stream.Context()") gfile.P("}") gfile.P() - gfile.P("func (s *", unexport(serviceName), "Service", method.GoName, ") SendMsg(msg interface{}) error {") + gfile.P("func (s *", unexport(serviceName), "Client", method.GoName, ") SendMsg(msg interface{}) error {") gfile.P("return s.stream.Send(msg)") gfile.P("}") gfile.P() - gfile.P("func (s *", unexport(serviceName), "Service", method.GoName, ") RecvMsg(msg interface{}) error {") + gfile.P("func (s *", unexport(serviceName), "Client", method.GoName, ") RecvMsg(msg interface{}) error {") gfile.P("return s.stream.Recv(msg)") gfile.P("}") gfile.P() if method.Desc.IsStreamingClient() { - gfile.P("func (s *", unexport(serviceName), "Service", method.GoName, ") Send(msg *", gfile.QualifiedGoIdent(method.Input.GoIdent), ") error {") + gfile.P("func (s *", unexport(serviceName), "Client", method.GoName, ") Send(msg *", gfile.QualifiedGoIdent(method.Input.GoIdent), ") error {") gfile.P("return s.stream.Send(msg)") gfile.P("}") gfile.P() } if method.Desc.IsStreamingServer() { - gfile.P("func (s *", unexport(serviceName), "Service", method.GoName, ") Recv() (*", gfile.QualifiedGoIdent(method.Output.GoIdent), ", error) {") + gfile.P("func (s *", unexport(serviceName), "Client", method.GoName, ") Recv() (*", gfile.QualifiedGoIdent(method.Output.GoIdent), ", error) {") gfile.P("msg := &", gfile.QualifiedGoIdent(method.Output.GoIdent), "{}") gfile.P("if err := s.stream.Recv(msg); err != nil {") gfile.P("return nil, err") @@ -167,15 +166,15 @@ func generateServiceClientMethods(gfile *protogen.GeneratedFile, service *protog } func generateServiceServer(gfile *protogen.GeneratedFile, service *protogen.Service) { - serviceName := strings.TrimSuffix(service.GoName, "Service") - gfile.P("type ", unexport(serviceName), "Handler struct {") - gfile.P(serviceName, "Handler") + serviceName := service.GoName + gfile.P("type ", unexport(serviceName), "Server struct {") + gfile.P(serviceName, "Server") gfile.P("}") gfile.P() } func generateServiceServerMethods(gfile *protogen.GeneratedFile, service *protogen.Service) { - serviceName := strings.TrimSuffix(service.GoName, "Service") + serviceName := service.GoName for _, method := range service.Methods { generateServerFuncSignature(gfile, serviceName, method, true) @@ -185,12 +184,12 @@ func generateServiceServerMethods(gfile *protogen.GeneratedFile, service *protog gfile.P("if err := stream.Recv(msg); err != nil {") gfile.P("return err") gfile.P("}") - gfile.P("return h.", serviceName, "Handler.", method.GoName, "(ctx, msg, &", unexport(serviceName), method.GoName, "Stream{stream})") + gfile.P("return h.", serviceName, "Server.", method.GoName, "(ctx, msg, &", unexport(serviceName), method.GoName, "Stream{stream})") } else { - gfile.P("return h.", serviceName, "Handler.", method.GoName, "(ctx, &", unexport(serviceName), method.GoName, "Stream{stream})") + gfile.P("return h.", serviceName, "Server.", method.GoName, "(ctx, &", unexport(serviceName), method.GoName, "Stream{stream})") } } else { - gfile.P("return h.", serviceName, "Handler.", method.GoName, "(ctx, req, rsp)") + gfile.P("return h.", serviceName, "Server.", method.GoName, "(ctx, req, rsp)") } gfile.P("}") gfile.P() @@ -255,8 +254,8 @@ func generateServiceServerMethods(gfile *protogen.GeneratedFile, service *protog } func generateServiceRegister(gfile *protogen.GeneratedFile, service *protogen.Service) { - serviceName := strings.TrimSuffix(service.GoName, "Service") - gfile.P("func Register", serviceName, "Handler(s ", microServerPackage.Ident("Server"), ", sh ", serviceName, "Handler, opts ...", microServerPackage.Ident("HandlerOption"), ") error {") + serviceName := service.GoName + gfile.P("func Register", serviceName, "Server(s ", microServerPackage.Ident("Server"), ", sh ", serviceName, "Server, opts ...", microServerPackage.Ident("HandlerOption"), ") error {") gfile.P("type ", unexport(serviceName), " interface {") for _, method := range service.Methods { generateServerSignature(gfile, serviceName, method, true) @@ -265,7 +264,7 @@ func generateServiceRegister(gfile *protogen.GeneratedFile, service *protogen.Se gfile.P("type ", serviceName, " struct {") gfile.P(unexport(serviceName)) gfile.P("}") - gfile.P("h := &", unexport(serviceName), "Handler{sh}") + gfile.P("h := &", unexport(serviceName), "Server{sh}") gfile.P("for _, endpoint := range New", serviceName, "Endpoints() {") gfile.P("opts = append(opts, ", microApiPackage.Ident("WithEndpoint"), "(endpoint))") gfile.P("}") @@ -275,7 +274,7 @@ func generateServiceRegister(gfile *protogen.GeneratedFile, service *protogen.Se func generateServerFuncSignature(gfile *protogen.GeneratedFile, serviceName string, method *protogen.Method, private bool) { args := append([]interface{}{}, - "func (h *", unexport(serviceName), "Handler) ", method.GoName, + "func (h *", unexport(serviceName), "Server) ", method.GoName, "(ctx ", contextPackage.Ident("Context"), ) if private && (method.Desc.IsStreamingClient() || method.Desc.IsStreamingServer()) { @@ -321,7 +320,7 @@ func generateClientFuncSignature(gfile *protogen.GeneratedFile, serviceName stri args := append([]interface{}{}, "func (c *", unexport(serviceName), - "Service) ", + "Client) ", method.GoName, "(ctx ", contextPackage.Ident("Context"), ", ", ) @@ -332,7 +331,7 @@ func generateClientFuncSignature(gfile *protogen.GeneratedFile, serviceName stri if !method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() { args = append(args, "*", gfile.QualifiedGoIdent(method.Output.GoIdent)) } else { - args = append(args, serviceName, "_", method.GoName, "Service") + args = append(args, serviceName, "_", method.GoName, "Client") } args = append(args, ", error) {") gfile.P(args...) @@ -350,15 +349,15 @@ func generateClientSignature(gfile *protogen.GeneratedFile, serviceName string, if !method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() { args = append(args, "*", gfile.QualifiedGoIdent(method.Output.GoIdent)) } else { - args = append(args, serviceName, "_", method.GoName, "Service") + args = append(args, serviceName, "_", method.GoName, "Client") } args = append(args, ", error)") gfile.P(args...) } func generateServiceClientInterface(gfile *protogen.GeneratedFile, service *protogen.Service) { - serviceName := strings.TrimSuffix(service.GoName, "Service") - gfile.P("type ", serviceName, "Service interface {") + serviceName := service.GoName + gfile.P("type ", serviceName, "Client interface {") for _, method := range service.Methods { generateClientSignature(gfile, serviceName, method) } @@ -367,8 +366,8 @@ func generateServiceClientInterface(gfile *protogen.GeneratedFile, service *prot } func generateServiceServerInterface(gfile *protogen.GeneratedFile, service *protogen.Service) { - serviceName := strings.TrimSuffix(service.GoName, "Service") - gfile.P("type ", serviceName, "Handler interface {") + serviceName := service.GoName + gfile.P("type ", serviceName, "Server interface {") for _, method := range service.Methods { generateServerSignature(gfile, serviceName, method, false) } @@ -377,13 +376,13 @@ func generateServiceServerInterface(gfile *protogen.GeneratedFile, service *prot } func generateServiceClientStreamInterface(gfile *protogen.GeneratedFile, service *protogen.Service) { - serviceName := strings.TrimSuffix(service.GoName, "Service") + serviceName := service.GoName for _, method := range service.Methods { if !method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() { continue } methodName := method.GoName - gfile.P("type ", serviceName, "_", methodName, "Service interface {") + gfile.P("type ", serviceName, "_", methodName, "Client interface {") gfile.P("Context() ", contextPackage.Ident("Context")) gfile.P("SendMsg(msg interface{}) error") gfile.P("RecvMsg(msg interface{}) error") @@ -403,7 +402,7 @@ func generateServiceClientStreamInterface(gfile *protogen.GeneratedFile, service } func generateServiceServerStreamInterface(gfile *protogen.GeneratedFile, service *protogen.Service) { - serviceName := strings.TrimSuffix(service.GoName, "Service") + serviceName := service.GoName for _, method := range service.Methods { if !method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() { continue @@ -429,8 +428,7 @@ func generateServiceServerStreamInterface(gfile *protogen.GeneratedFile, service } func generateServiceEndpoints(gfile *protogen.GeneratedFile, service *protogen.Service) { - serviceName := strings.TrimSuffix(service.GoName, "Service") - gfile.P("// New", serviceName, "Endpoints provides api endpoints metdata for ", serviceName, " service") + serviceName := service.GoName gfile.P("func New", serviceName, "Endpoints() []*", microApiPackage.Ident("Endpoint"), " {") gfile.P("return []*", microApiPackage.Ident("Endpoint"), "{") for _, method := range service.Methods {