From 8d9af285403e1acdb3b235d3dcca77099325f417 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Mon, 4 May 2020 12:07:49 -0700 Subject: [PATCH] protoc-gen-go/grpc: make grpc identical to v1.3.5 (#1113) Even through the grpc package is excluded from our compatibility agreement, the v1.4.0 release accidentally reverted the package to an older revision. Update this code to be identical to the v1.3.5 release (barring non-semantic documentation changes). Fixes #1111 --- protoc-gen-go/grpc/grpc.go | 79 +++++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 5 deletions(-) diff --git a/protoc-gen-go/grpc/grpc.go b/protoc-gen-go/grpc/grpc.go index 88e20d7af9..40cba163b5 100644 --- a/protoc-gen-go/grpc/grpc.go +++ b/protoc-gen-go/grpc/grpc.go @@ -1,4 +1,4 @@ -// Copyright 2015 The Go Authors. All rights reserved. +// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -23,13 +23,15 @@ import ( // It is incremented whenever an incompatibility between the generated code and // the grpc package is introduced; the generated code references // a constant, grpc.SupportPackageIsVersionN (where N is generatedCodeVersion). -const generatedCodeVersion = 4 +const generatedCodeVersion = 6 // 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" ) func init() { @@ -86,7 +88,7 @@ func (g *grpc) Generate(file *generator.FileDescriptor) { g.P("// Reference imports to suppress errors if they are not otherwise used.") g.P("var _ ", contextPkg, ".Context") - g.P("var _ ", grpcPkg, ".ClientConn") + g.P("var _ ", grpcPkg, ".ClientConnInterface") g.P() // Assert version compatibility. @@ -140,6 +142,10 @@ func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.Servi g.P("type ", servName, "Client interface {") 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("}") @@ -147,7 +153,7 @@ func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.Servi // Client structure. g.P("type ", unexport(servName), "Client struct {") - g.P("cc *", grpcPkg, ".ClientConn") + g.P("cc ", grpcPkg, ".ClientConnInterface") g.P("}") g.P() @@ -155,7 +161,7 @@ func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.Servi if deprecated { g.P(deprecationComment) } - g.P("func New", servName, "Client (cc *", grpcPkg, ".ClientConn) ", servName, "Client {") + g.P("func New", servName, "Client (cc ", grpcPkg, ".ClientConnInterface) ", servName, "Client {") g.P("return &", unexport(servName), "Client{cc}") g.P("}") g.P() @@ -187,11 +193,21 @@ func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.Servi g.P("type ", serverType, " interface {") 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.generateServerSignature(servName, method)) } g.P("}") g.P() + // Server Unimplemented struct for forward compatibility. + if deprecated { + g.P(deprecationComment) + } + g.generateUnimplementedServer(servName, service) + // Server registration. if deprecated { g.P(deprecationComment) @@ -245,6 +261,35 @@ func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.Servi g.P() } +// generateUnimplementedServer creates the unimplemented server struct +func (g *grpc) generateUnimplementedServer(servName string, service *pb.ServiceDescriptorProto) { + serverType := servName + "Server" + g.P("// Unimplemented", serverType, " can be embedded to have forward compatible implementations.") + g.P("type Unimplemented", serverType, " struct {") + g.P("}") + g.P() + // UnimplementedServer's concrete methods + for _, method := range service.Method { + g.generateServerMethodConcrete(servName, method) + } + g.P() +} + +// generateServerMethodConcrete returns unimplemented methods which ensure forward compatibility +func (g *grpc) generateServerMethodConcrete(servName string, method *pb.MethodDescriptorProto) { + header := g.generateServerSignatureWithParamNames(servName, method) + g.P("func (*Unimplemented", servName, "Server) ", header, " {") + var nilArg string + if !method.GetServerStreaming() && !method.GetClientStreaming() { + nilArg = "nil, " + } + methName := generator.CamelCase(method.GetName()) + statusPkg := string(g.gen.AddImport(statusPkgPath)) + codePkg := string(g.gen.AddImport(codePkgPath)) + g.P("return ", nilArg, statusPkg, `.Errorf(`, codePkg, `.Unimplemented, "method `, methName, ` not implemented")`) + g.P("}") +} + // generateClientSignature returns the client-side signature for a method. func (g *grpc) generateClientSignature(servName string, method *pb.MethodDescriptorProto) string { origMethName := method.GetName() @@ -344,6 +389,30 @@ func (g *grpc) generateClientMethod(servName, fullServName, serviceDescVar strin } } +// generateServerSignatureWithParamNames returns the server-side signature for a method with parameter names. +func (g *grpc) generateServerSignatureWithParamNames(servName string, method *pb.MethodDescriptorProto) string { + origMethName := method.GetName() + methName := generator.CamelCase(origMethName) + if reservedClientName[methName] { + methName += "_" + } + + var reqArgs []string + ret := "error" + if !method.GetServerStreaming() && !method.GetClientStreaming() { + reqArgs = append(reqArgs, "ctx "+contextPkg+".Context") + ret = "(*" + g.typeName(method.GetOutputType()) + ", error)" + } + if !method.GetClientStreaming() { + reqArgs = append(reqArgs, "req *"+g.typeName(method.GetInputType())) + } + if method.GetServerStreaming() || method.GetClientStreaming() { + reqArgs = append(reqArgs, "srv "+servName+"_"+generator.CamelCase(origMethName)+"Server") + } + + return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret +} + // generateServerSignature returns the server-side signature for a method. func (g *grpc) generateServerSignature(servName string, method *pb.MethodDescriptorProto) string { origMethName := method.GetName()