diff --git a/protocol/grpc/protoc-gen-dubbo/main.go b/protocol/grpc/protoc-gen-dubbo/main.go index 28458d743010e18d04ec523a19360ed4aac30bf1..e12ceca756117a5af9dd3c2dac323297e28e95fb 100644 --- a/protocol/grpc/protoc-gen-dubbo/main.go +++ b/protocol/grpc/protoc-gen-dubbo/main.go @@ -25,10 +25,10 @@ import ( import ( "github.com/golang/protobuf/proto" "github.com/golang/protobuf/protoc-gen-go/generator" + _ "github.com/golang/protobuf/protoc-gen-go/grpc" ) import( - _ "github.com/golang/protobuf/protoc-gen-go/grpc" _ "github.com/apache/dubbo-go/protocol/grpc/protoc-gen-dubbo/plugin/dubbo" ) diff --git a/protocol/grpc/protoc-gen-dubbo/plugin/dubbo/dubbo.go b/protocol/grpc/protoc-gen-dubbo/plugin/dubbo/dubbo.go index d52e1a02bbd085fc9fbe9f59d79ec24522cdc5c4..e84a7d0cc96887cf728f499c28c26f061ed1ccdf 100644 --- a/protocol/grpc/protoc-gen-dubbo/plugin/dubbo/dubbo.go +++ b/protocol/grpc/protoc-gen-dubbo/plugin/dubbo/dubbo.go @@ -18,12 +18,14 @@ limitations under the License. package dubbo import ( - "fmt" - "strconv" - "strings" + "fmt" + "strconv" + "strings" +) - pb "github.com/golang/protobuf/protoc-gen-go/descriptor" - "github.com/golang/protobuf/protoc-gen-go/generator" +import ( + pb "github.com/golang/protobuf/protoc-gen-go/descriptor" + "github.com/golang/protobuf/protoc-gen-go/generator" ) // generatedCodeVersion indicates a version of the generated code. @@ -35,50 +37,50 @@ const generatedCodeVersion = 4 // Paths for packages used by code generated in this file, // relative to the import_prefix of the generator.Generator. const ( - contextPkgPath = "context" - grpcPkgPath = "google.golang.org/grpc" - codePkgPath = "google.golang.org/grpc/codes" - statusPkgPath = "google.golang.org/grpc/status" + contextPkgPath = "context" + grpcPkgPath = "google.golang.org/grpc" + codePkgPath = "google.golang.org/grpc/codes" + statusPkgPath = "google.golang.org/grpc/status" ) func init() { - generator.RegisterPlugin(new(dubboGrpc)) + generator.RegisterPlugin(new(dubboGrpc)) } // grpc is an implementation of the Go protocol buffer compiler's // plugin architecture. It generates bindings for gRPC-dubbo support. type dubboGrpc struct { - gen *generator.Generator + gen *generator.Generator } // Name returns the name of this plugin, "grpc". func (g *dubboGrpc) Name() string { - return "dubbo" + return "dubbo" } // The names for packages imported in the generated code. // They may vary from the final path component of the import path // if the name is used by other packages. var ( - contextPkg string - grpcPkg string + contextPkg string + grpcPkg string ) // Init initializes the plugin. func (g *dubboGrpc) Init(gen *generator.Generator) { - g.gen = gen + g.gen = gen } // Given a type name defined in a .proto, return its object. // Also record that we're using it, to guarantee the associated import. func (g *dubboGrpc) objectNamed(name string) generator.Object { - g.gen.RecordTypeUse(name) - return g.gen.ObjectNamed(name) + g.gen.RecordTypeUse(name) + return g.gen.ObjectNamed(name) } // Given a type name defined in a .proto, return its name as we will print it. func (g *dubboGrpc) typeName(str string) string { - return g.gen.TypeName(g.objectNamed(str)) + return g.gen.TypeName(g.objectNamed(str)) } // P forwards to g.gen.P. @@ -87,26 +89,26 @@ func (g *dubboGrpc) P(args ...interface{}) { g.gen.P(args...) } // Generate generates code for the services in the given file. // be consistent with grpc plugin func (g *dubboGrpc) Generate(file *generator.FileDescriptor) { - if len(file.FileDescriptorProto.Service) == 0 { - return - } + if len(file.FileDescriptorProto.Service) == 0 { + return + } - contextPkg = string(g.gen.AddImport(contextPkgPath)) - grpcPkg = string(g.gen.AddImport(grpcPkgPath)) + contextPkg = string(g.gen.AddImport(contextPkgPath)) + grpcPkg = string(g.gen.AddImport(grpcPkgPath)) - for i, service := range file.FileDescriptorProto.Service { - g.generateService(file, service, i) - } + for i, service := range file.FileDescriptorProto.Service { + g.generateService(file, service, i) + } } // GenerateImports generates the import declaration for this file. func (g *dubboGrpc) GenerateImports(file *generator.FileDescriptor) { - g.P("import (") - g.P(`dgrpc "github.com/apache/dubbo-go/protocol/grpc"`) - g.P(`"github.com/apache/dubbo-go/protocol/invocation"`) - g.P(`"github.com/apache/dubbo-go/protocol"`) - g.P(`"github.com/apache/dubbo-go/config"`) - g.P(` ) `) + g.P("import (") + g.P(`dgrpc "github.com/apache/dubbo-go/protocol/grpc"`) + g.P(`"github.com/apache/dubbo-go/protocol/invocation"`) + g.P(`"github.com/apache/dubbo-go/protocol"`) + g.P(`"github.com/apache/dubbo-go/config"`) + g.P(` ) `) } func unexport(s string) string { return strings.ToLower(s[:1]) + s[1:] } @@ -117,228 +119,228 @@ var deprecationComment = "// Deprecated: Do not use." // generateService generates all the code for the named service. func (g *dubboGrpc) generateService(file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int) { - path := fmt.Sprintf("6,%d", index) // 6 means service. - - origServName := service.GetName() - fullServName := origServName - if pkg := file.GetPackage(); pkg != "" { - fullServName = pkg + "." + fullServName - } - servName := generator.CamelCase(origServName) - deprecated := service.GetOptions().GetDeprecated() - - g.P() - g.P(fmt.Sprintf(`// %sClientImpl is the client API for %s service. + path := fmt.Sprintf("6,%d", index) // 6 means service. + + origServName := service.GetName() + fullServName := origServName + if pkg := file.GetPackage(); pkg != "" { + fullServName = pkg + "." + fullServName + } + servName := generator.CamelCase(origServName) + deprecated := service.GetOptions().GetDeprecated() + + g.P() + g.P(fmt.Sprintf(`// %sClientImpl is the client API for %s service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.`, servName, servName)) - // Client interface. - if deprecated { - g.P("//") - g.P(deprecationComment) - } - dubboSrvName := servName + "ClientImpl" - g.P("type ", dubboSrvName, " struct {") - for i, method := range service.Method { - g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service. - if method.GetOptions().GetDeprecated() { - g.P("//") - g.P(deprecationComment) - } - g.P(g.generateClientSignature(servName, method)) - } - g.P("}") - g.P() - - // NewClient factory. - if deprecated { - g.P(deprecationComment) - } - - // add Reference method - //func (u *GrpcGreeterImpl) Reference() string { - // return "GrpcGreeterImpl" - //} - g.P("func (c *", dubboSrvName, ") ", " Reference() string ", "{") - g.P(`return "`, unexport(servName), `Impl"`) - g.P("}") - g.P() - - // add GetDubboStub method - // func (u *GrpcGreeterImpl) GetDubboStub(cc *grpc.ClientConn) GreeterClient { - // return NewGreeterClient(cc) - //} - g.P("func (c *", dubboSrvName, ") ", " GetDubboStub(cc *grpc.ClientConn) ", servName, "Client {") - g.P(`return New`, servName, `Client(cc)`) - g.P("}") - g.P() - - // Server interface. - serverType := servName + "ProviderBase" - g.P("type ", serverType, " struct {") - g.P("proxyImpl protocol.Invoker") - g.P("}") - g.P() - - // add set method - //func (g *GreeterProviderBase) SetProxyImpl(impl protocol.Invoker) { - // g.proxyImpl = impl - //} - g.P("func (s *", serverType, ") SetProxyImpl(impl protocol.Invoker) {") - g.P(`s.proxyImpl = impl`) - g.P("}") - g.P() - - // return get method - g.P("func (s *", serverType, ") GetProxyImpl() protocol.Invoker {") - g.P(`return s.proxyImpl`) - g.P("}") - g.P() - - // add handler - var handlerNames []string - for _, method := range service.Method { - hname := g.generateServerMethod(servName, fullServName, method) - handlerNames = append(handlerNames, hname) - } - - grpcserverType := servName + "Server" - // return service desc - g.P("func (s *", serverType, ") ServiceDesc() *grpc.ServiceDesc {") - g.P(`return &grpc.ServiceDesc{`) - g.P("ServiceName: ", strconv.Quote(fullServName), ",") - g.P("HandlerType: (*", grpcserverType, ")(nil),") - g.P("Methods: []", grpcPkg, ".MethodDesc{") - for i, method := range service.Method { - if method.GetServerStreaming() || method.GetClientStreaming() { - continue - } - g.P("{") - g.P("MethodName: ", strconv.Quote(method.GetName()), ",") - g.P("Handler: ", handlerNames[i], ",") - g.P("},") - } - g.P("},") - g.P("Streams: []", grpcPkg, ".StreamDesc{},") - g.P("Metadata: \"", file.GetName(), "\",") - g.P("}") - g.P("}") - g.P() + // Client interface. + if deprecated { + g.P("//") + g.P(deprecationComment) + } + dubboSrvName := servName + "ClientImpl" + g.P("type ", dubboSrvName, " struct {") + for i, method := range service.Method { + g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service. + if method.GetOptions().GetDeprecated() { + g.P("//") + g.P(deprecationComment) + } + g.P(g.generateClientSignature(servName, method)) + } + g.P("}") + g.P() + + // NewClient factory. + if deprecated { + g.P(deprecationComment) + } + + // add Reference method + //func (u *GrpcGreeterImpl) Reference() string { + // return "GrpcGreeterImpl" + //} + g.P("func (c *", dubboSrvName, ") ", " Reference() string ", "{") + g.P(`return "`, unexport(servName), `Impl"`) + g.P("}") + g.P() + + // add GetDubboStub method + // func (u *GrpcGreeterImpl) GetDubboStub(cc *grpc.ClientConn) GreeterClient { + // return NewGreeterClient(cc) + //} + g.P("func (c *", dubboSrvName, ") ", " GetDubboStub(cc *grpc.ClientConn) ", servName, "Client {") + g.P(`return New`, servName, `Client(cc)`) + g.P("}") + g.P() + + // Server interface. + serverType := servName + "ProviderBase" + g.P("type ", serverType, " struct {") + g.P("proxyImpl protocol.Invoker") + g.P("}") + g.P() + + // add set method + //func (g *GreeterProviderBase) SetProxyImpl(impl protocol.Invoker) { + // g.proxyImpl = impl + //} + g.P("func (s *", serverType, ") SetProxyImpl(impl protocol.Invoker) {") + g.P(`s.proxyImpl = impl`) + g.P("}") + g.P() + + // return get method + g.P("func (s *", serverType, ") GetProxyImpl() protocol.Invoker {") + g.P(`return s.proxyImpl`) + g.P("}") + g.P() + + // add handler + var handlerNames []string + for _, method := range service.Method { + hname := g.generateServerMethod(servName, fullServName, method) + handlerNames = append(handlerNames, hname) + } + + grpcserverType := servName + "Server" + // return service desc + g.P("func (s *", serverType, ") ServiceDesc() *grpc.ServiceDesc {") + g.P(`return &grpc.ServiceDesc{`) + g.P("ServiceName: ", strconv.Quote(fullServName), ",") + g.P("HandlerType: (*", grpcserverType, ")(nil),") + g.P("Methods: []", grpcPkg, ".MethodDesc{") + for i, method := range service.Method { + if method.GetServerStreaming() || method.GetClientStreaming() { + continue + } + g.P("{") + g.P("MethodName: ", strconv.Quote(method.GetName()), ",") + g.P("Handler: ", handlerNames[i], ",") + g.P("},") + } + g.P("},") + g.P("Streams: []", grpcPkg, ".StreamDesc{},") + g.P("Metadata: \"", file.GetName(), "\",") + g.P("}") + g.P("}") + g.P() } // generateClientSignature returns the client-side signature for a method. func (g *dubboGrpc) generateClientSignature(servName string, method *pb.MethodDescriptorProto) string { - origMethName := method.GetName() - methName := generator.CamelCase(origMethName) - //if reservedClientName[methName] { - // methName += "_" - //} - reqArg := ", in *" + g.typeName(method.GetInputType()) - if method.GetClientStreaming() { - reqArg = "" - } - respName := "out *" + g.typeName(method.GetOutputType()) - if method.GetServerStreaming() || method.GetClientStreaming() { - respName = servName + "_" + generator.CamelCase(origMethName) + "Client" - } - return fmt.Sprintf("%s func(ctx %s.Context%s, %s) error", methName, contextPkg, reqArg, respName) + origMethName := method.GetName() + methName := generator.CamelCase(origMethName) + //if reservedClientName[methName] { + // methName += "_" + //} + reqArg := ", in *" + g.typeName(method.GetInputType()) + if method.GetClientStreaming() { + reqArg = "" + } + respName := "out *" + g.typeName(method.GetOutputType()) + if method.GetServerStreaming() || method.GetClientStreaming() { + respName = servName + "_" + generator.CamelCase(origMethName) + "Client" + } + return fmt.Sprintf("%s func(ctx %s.Context%s, %s) error", methName, contextPkg, reqArg, respName) } func (g *dubboGrpc) generateClientMethod(servName, fullServName, serviceDescVar string, method *pb.MethodDescriptorProto, descExpr string) { } func (g *dubboGrpc) generateServerMethod(servName, fullServName string, method *pb.MethodDescriptorProto) string { - methName := generator.CamelCase(method.GetName()) - hname := fmt.Sprintf("_DUBBO_%s_%s_Handler", servName, methName) - inType := g.typeName(method.GetInputType()) - outType := g.typeName(method.GetOutputType()) - - if !method.GetServerStreaming() && !method.GetClientStreaming() { - g.P("func ", hname, "(srv interface{}, ctx ", contextPkg, ".Context, dec func(interface{}) error, interceptor ", grpcPkg, ".UnaryServerInterceptor) (interface{}, error) {") - g.P("in := new(", inType, ")") - g.P("if err := dec(in); err != nil { return nil, err }") - - g.P("base := srv.(dgrpc.DubboGrpcService)") - g.P("args := []interface{}{}") - g.P("args = append(args, in)") - g.P(`invo := invocation.NewRPCInvocation("`, methName, `", args, nil)`) - - g.P("if interceptor == nil {") - g.P("result := base.GetProxyImpl().Invoke(invo)") - g.P("return result.Result(), result.Error()") - g.P("}") - - g.P("info := &", grpcPkg, ".UnaryServerInfo{") - g.P("Server: srv,") - g.P("FullMethod: ", strconv.Quote(fmt.Sprintf("/%s/%s", fullServName, methName)), ",") - g.P("}") - - g.P("handler := func(ctx ", contextPkg, ".Context, req interface{}) (interface{}, error) {") - g.P("result := base.GetProxyImpl().Invoke(invo)") - g.P("return result.Result(), result.Error()") - g.P("}") - - g.P("return interceptor(ctx, in, info, handler)") - g.P("}") - g.P() - return hname - } - streamType := unexport(servName) + methName + "Server" - g.P("func ", hname, "(srv interface{}, stream ", grpcPkg, ".ServerStream) error {") - if !method.GetClientStreaming() { - g.P("m := new(", inType, ")") - g.P("if err := stream.RecvMsg(m); err != nil { return err }") - g.P("return srv.(", servName, "Server).", methName, "(m, &", streamType, "{stream})") - } else { - g.P("return srv.(", servName, "Server).", methName, "(&", streamType, "{stream})") - } - g.P("}") - g.P() - - genSend := method.GetServerStreaming() - genSendAndClose := !method.GetServerStreaming() - genRecv := method.GetClientStreaming() - - // Stream auxiliary types and methods. - g.P("type ", servName, "_", methName, "Server interface {") - if genSend { - g.P("Send(*", outType, ") error") - } - if genSendAndClose { - g.P("SendAndClose(*", outType, ") error") - } - if genRecv { - g.P("Recv() (*", inType, ", error)") - } - g.P(grpcPkg, ".ServerStream") - g.P("}") - g.P() - - g.P("type ", streamType, " struct {") - g.P(grpcPkg, ".ServerStream") - g.P("}") - g.P() - - if genSend { - g.P("func (x *", streamType, ") Send(m *", outType, ") error {") - g.P("return x.ServerStream.SendMsg(m)") - g.P("}") - g.P() - } - if genSendAndClose { - g.P("func (x *", streamType, ") SendAndClose(m *", outType, ") error {") - g.P("return x.ServerStream.SendMsg(m)") - g.P("}") - g.P() - } - if genRecv { - g.P("func (x *", streamType, ") Recv() (*", inType, ", error) {") - g.P("m := new(", inType, ")") - g.P("if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err }") - g.P("return m, nil") - g.P("}") - g.P() - } - - return hname + methName := generator.CamelCase(method.GetName()) + hname := fmt.Sprintf("_DUBBO_%s_%s_Handler", servName, methName) + inType := g.typeName(method.GetInputType()) + outType := g.typeName(method.GetOutputType()) + + if !method.GetServerStreaming() && !method.GetClientStreaming() { + g.P("func ", hname, "(srv interface{}, ctx ", contextPkg, ".Context, dec func(interface{}) error, interceptor ", grpcPkg, ".UnaryServerInterceptor) (interface{}, error) {") + g.P("in := new(", inType, ")") + g.P("if err := dec(in); err != nil { return nil, err }") + + g.P("base := srv.(dgrpc.DubboGrpcService)") + g.P("args := []interface{}{}") + g.P("args = append(args, in)") + g.P(`invo := invocation.NewRPCInvocation("`, methName, `", args, nil)`) + + g.P("if interceptor == nil {") + g.P("result := base.GetProxyImpl().Invoke(invo)") + g.P("return result.Result(), result.Error()") + g.P("}") + + g.P("info := &", grpcPkg, ".UnaryServerInfo{") + g.P("Server: srv,") + g.P("FullMethod: ", strconv.Quote(fmt.Sprintf("/%s/%s", fullServName, methName)), ",") + g.P("}") + + g.P("handler := func(ctx ", contextPkg, ".Context, req interface{}) (interface{}, error) {") + g.P("result := base.GetProxyImpl().Invoke(invo)") + g.P("return result.Result(), result.Error()") + g.P("}") + + g.P("return interceptor(ctx, in, info, handler)") + g.P("}") + g.P() + return hname + } + streamType := unexport(servName) + methName + "Server" + g.P("func ", hname, "(srv interface{}, stream ", grpcPkg, ".ServerStream) error {") + if !method.GetClientStreaming() { + g.P("m := new(", inType, ")") + g.P("if err := stream.RecvMsg(m); err != nil { return err }") + g.P("return srv.(", servName, "Server).", methName, "(m, &", streamType, "{stream})") + } else { + g.P("return srv.(", servName, "Server).", methName, "(&", streamType, "{stream})") + } + g.P("}") + g.P() + + genSend := method.GetServerStreaming() + genSendAndClose := !method.GetServerStreaming() + genRecv := method.GetClientStreaming() + + // Stream auxiliary types and methods. + g.P("type ", servName, "_", methName, "Server interface {") + if genSend { + g.P("Send(*", outType, ") error") + } + if genSendAndClose { + g.P("SendAndClose(*", outType, ") error") + } + if genRecv { + g.P("Recv() (*", inType, ", error)") + } + g.P(grpcPkg, ".ServerStream") + g.P("}") + g.P() + + g.P("type ", streamType, " struct {") + g.P(grpcPkg, ".ServerStream") + g.P("}") + g.P() + + if genSend { + g.P("func (x *", streamType, ") Send(m *", outType, ") error {") + g.P("return x.ServerStream.SendMsg(m)") + g.P("}") + g.P() + } + if genSendAndClose { + g.P("func (x *", streamType, ") SendAndClose(m *", outType, ") error {") + g.P("return x.ServerStream.SendMsg(m)") + g.P("}") + g.P() + } + if genRecv { + g.P("func (x *", streamType, ") Recv() (*", inType, ", error) {") + g.P("m := new(", inType, ")") + g.P("if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err }") + g.P("return m, nil") + g.P("}") + g.P() + } + + return hname }