protoc-gen-go: indicate deprecated fields in documentation

Tools in the Go ecosystem treat code documented with "Deprecated:"
as special for purposes of warning users not to use them.  When a file,
message, field, enum, enum value, service, or method is marked as
deprecated, the generator will emit "// Deprecated: Do not use."
comments on all relevant exported Go package information related to
the deprecated element.

This is an outline of how deprecation of each element effects the generated proto:
* file - a comment is added to the top of the generated proto.
* message - a comment is added above its type definition.
* field, enum, or enum value - a comment is added inline with the defintion.
* field - an additional comment is added above the field Getter.
* service - a comment is added above generated Client interface and New method.
* service - a comment is added above generated Server interface and Registration method.
* method - a comment is added above the generated method definition.

Fixes #396.
diff --git a/protoc-gen-go/generator/generator.go b/protoc-gen-go/generator/generator.go
index a49189b..c5e9314 100644
--- a/protoc-gen-go/generator/generator.go
+++ b/protoc-gen-go/generator/generator.go
@@ -1330,7 +1330,11 @@
 // Generate the header, including package definition
 func (g *Generator) generateHeader() {
 	g.P("// Code generated by protoc-gen-go. DO NOT EDIT.")
-	g.P("// source: ", g.file.Name)
+	if g.file.GetOptions().GetDeprecated() {
+		g.P("// ", g.file.Name, " is a deprecated file.")
+	} else {
+		g.P("// source: ", g.file.Name)
+	}
 	g.P()
 
 	name := g.file.PackageName()
@@ -1374,6 +1378,10 @@
 	g.P()
 }
 
+// deprecationComment is the standard comment added to deprecated
+// messages, fields, enums, and enum values.
+var deprecationComment = "// Deprecated: Do not use."
+
 // PrintComments prints any comments from the source .proto file.
 // The path is a comma-separated list of integers.
 // It returns an indication of whether any comments were printed.
@@ -1488,8 +1496,12 @@
 	ccTypeName := CamelCaseSlice(typeName)
 	ccPrefix := enum.prefix()
 
+	deprecatedEnum := ""
+	if enum.GetOptions().GetDeprecated() {
+		deprecatedEnum = deprecationComment
+	}
 	g.PrintComments(enum.path)
-	g.P("type ", Annotate(enum.file, enum.path, ccTypeName), " int32")
+	g.P("type ", Annotate(enum.file, enum.path, ccTypeName), " int32", deprecatedEnum)
 	g.file.addExport(enum, enumSymbol{ccTypeName, enum.proto3()})
 	g.P("const (")
 	g.In()
@@ -1497,8 +1509,13 @@
 		etorPath := fmt.Sprintf("%s,%d,%d", enum.path, enumValuePath, i)
 		g.PrintComments(etorPath)
 
+		deprecatedValue := ""
+		if e.GetOptions().GetDeprecated() {
+			deprecatedValue = deprecationComment
+		}
+
 		name := ccPrefix + *e.Name
-		g.P(Annotate(enum.file, etorPath, name), " ", ccTypeName, " = ", e.Number)
+		g.P(Annotate(enum.file, etorPath, name), " ", ccTypeName, " = ", e.Number, " ", deprecatedValue)
 		g.file.addExport(enum, constOrVarSymbol{name, "const", ccTypeName})
 	}
 	g.Out()
@@ -1839,7 +1856,18 @@
 	oneofTypeName := make(map[*descriptor.FieldDescriptorProto]string) // without star
 	oneofInsertPoints := make(map[int32]int)                           // oneof_index => offset of g.Buffer
 
-	g.PrintComments(message.path)
+	comments := g.PrintComments(message.path)
+
+	// Guarantee deprecation comments appear after user-provided comments.
+	if message.GetOptions().GetDeprecated() {
+		if comments {
+			// Convention: Separate deprecation comments from original
+			// comments with an empty line.
+			g.P("//")
+		}
+		g.P(deprecationComment)
+	}
+
 	g.P("type ", Annotate(message.file, message.path, ccTypeName), " struct {")
 	g.In()
 
@@ -1965,9 +1993,14 @@
 			continue
 		}
 
+		fieldDeprecated := ""
+		if field.GetOptions().GetDeprecated() {
+			fieldDeprecated = deprecationComment
+		}
+
 		fieldFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i)
 		g.PrintComments(fieldFullPath)
-		g.P(Annotate(message.file, fieldFullPath, fieldName), "\t", typename, "\t`", tag, "`")
+		g.P(Annotate(message.file, fieldFullPath, fieldName), "\t", typename, "\t`", tag, "`", fieldDeprecated)
 		g.RecordTypeUse(field.GetTypeName())
 	}
 	g.P("XXX_NoUnkeyedLiteral\tstruct{} `json:\"-\"`") // prevent unkeyed struct literals
@@ -2252,6 +2285,10 @@
 			})
 		}
 
+		if field.GetOptions().GetDeprecated() {
+			g.P(deprecationComment)
+		}
+
 		g.P("func (m *", ccTypeName, ") ", Annotate(message.file, fieldFullPath, mname), "() "+typename+" {")
 		g.In()
 		def, hasDef := defNames[field]
diff --git a/protoc-gen-go/grpc/grpc.go b/protoc-gen-go/grpc/grpc.go
index 2660e47..f11aa1b 100644
--- a/protoc-gen-go/grpc/grpc.go
+++ b/protoc-gen-go/grpc/grpc.go
@@ -138,11 +138,15 @@
 
 // reservedClientName records whether a client name is reserved on the client side.
 var reservedClientName = map[string]bool{
-// TODO: do we need any in gRPC?
+	// TODO: do we need any in gRPC?
 }
 
 func unexport(s string) string { return strings.ToLower(s[:1]) + s[1:] }
 
+// deprecationComment is the standard comment added to deprecated
+// messages, fields, enums, and enum values.
+var deprecationComment = "// Deprecated: Do not use."
+
 // generateService generates all the code for the named service.
 func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int) {
 	path := fmt.Sprintf("6,%d", index) // 6 means service.
@@ -153,12 +157,16 @@
 		fullServName = pkg + "." + fullServName
 	}
 	servName := generator.CamelCase(origServName)
+	deprecated := service.GetOptions().GetDeprecated()
 
 	g.P()
 	g.P("// Client API for ", servName, " service")
 	g.P()
 
 	// Client interface.
+	if deprecated {
+		g.P(deprecationComment)
+	}
 	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.
@@ -174,6 +182,9 @@
 	g.P()
 
 	// NewClient factory.
+	if deprecated {
+		g.P(deprecationComment)
+	}
 	g.P("func New", servName, "Client (cc *", grpcPkg, ".ClientConn) ", servName, "Client {")
 	g.P("return &", unexport(servName), "Client{cc}")
 	g.P("}")
@@ -200,6 +211,9 @@
 	g.P()
 
 	// Server interface.
+	if deprecated {
+		g.P(deprecationComment)
+	}
 	serverType := servName + "Server"
 	g.P("type ", serverType, " interface {")
 	for i, method := range service.Method {
@@ -210,6 +224,9 @@
 	g.P()
 
 	// Server registration.
+	if deprecated {
+		g.P(deprecationComment)
+	}
 	g.P("func Register", servName, "Server(s *", grpcPkg, ".Server, srv ", serverType, ") {")
 	g.P("s.RegisterService(&", serviceDescVar, `, srv)`)
 	g.P("}")
@@ -283,6 +300,9 @@
 	inType := g.typeName(method.GetInputType())
 	outType := g.typeName(method.GetOutputType())
 
+	if method.GetOptions().GetDeprecated() {
+		g.P(deprecationComment)
+	}
 	g.P("func (c *", unexport(servName), "Client) ", g.generateClientSignature(servName, method), "{")
 	if !method.GetServerStreaming() && !method.GetClientStreaming() {
 		g.P("out := new(", outType, ")")
diff --git a/protoc-gen-go/testdata/Makefile b/protoc-gen-go/testdata/Makefile
index a0bf9fe..945e7d0 100644
--- a/protoc-gen-go/testdata/Makefile
+++ b/protoc-gen-go/testdata/Makefile
@@ -51,6 +51,17 @@
 	gofmt -w my_test/test.pb.go
 	diff -w my_test/test.pb.go my_test/test.pb.go.golden
 
+	make -B deprecated/deprecated.pb.go
+	sed -i -e '/return.*fileDescriptor/d' deprecated/deprecated.pb.go
+	sed -i -e '/^var fileDescriptor/,/^}/d' deprecated/deprecated.pb.go
+	sed -i -e '/proto.RegisterFile.*fileDescriptor/d' deprecated/deprecated.pb.go
+	gofmt -w deprecated/deprecated.pb.go
+	diff -w deprecated/deprecated.pb.go deprecated/deprecated.pb.go.golden
+
+
+deprecated/deprecated.pb.go: deprecated/deprecated.proto
+	protoc --go_out=plugins=grpc,import_path=Mdeprecated/deprecated.proto=github.com/golang/protobuf/protoc-gen-go/testdata/deprecated:. $<
+
 nuke:	clean
 
 testbuild:	regenerate
diff --git a/protoc-gen-go/testdata/deprecated/deprecated.pb.go b/protoc-gen-go/testdata/deprecated/deprecated.pb.go
new file mode 100644
index 0000000..1cdbe42
--- /dev/null
+++ b/protoc-gen-go/testdata/deprecated/deprecated.pb.go
@@ -0,0 +1,207 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// deprecated/deprecated.proto is a deprecated file.
+
+/*
+Package deprecated is a generated protocol buffer package.
+
+package deprecated contains only deprecated messages and services.
+
+It is generated from these files:
+	deprecated/deprecated.proto
+
+It has these top-level messages:
+	DeprecatedRequest
+	DeprecatedResponse
+*/
+package deprecated
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+import (
+	context "golang.org/x/net/context"
+	grpc "google.golang.org/grpc"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+// DeprecatedEnum contains deprecated values.
+type DeprecatedEnum int32 // Deprecated: Do not use.
+const (
+	// DEPRECATED is the iota value of this enum.
+	DeprecatedEnum_DEPRECATED DeprecatedEnum = 0 // Deprecated: Do not use.
+)
+
+var DeprecatedEnum_name = map[int32]string{
+	0: "DEPRECATED",
+}
+var DeprecatedEnum_value = map[string]int32{
+	"DEPRECATED": 0,
+}
+
+func (x DeprecatedEnum) String() string {
+	return proto.EnumName(DeprecatedEnum_name, int32(x))
+}
+
+// DeprecatedRequest is a request to DeprecatedCall.
+//
+// Deprecated: Do not use.
+type DeprecatedRequest struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *DeprecatedRequest) Reset()         { *m = DeprecatedRequest{} }
+func (m *DeprecatedRequest) String() string { return proto.CompactTextString(m) }
+func (*DeprecatedRequest) ProtoMessage()    {}
+func (m *DeprecatedRequest) Unmarshal(b []byte) error {
+	return xxx_messageInfo_DeprecatedRequest.Unmarshal(m, b)
+}
+func (m *DeprecatedRequest) Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_DeprecatedRequest.Marshal(b, m, deterministic)
+}
+func (dst *DeprecatedRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DeprecatedRequest.Merge(dst, src)
+}
+func (m *DeprecatedRequest) XXX_Size() int {
+	return xxx_messageInfo_DeprecatedRequest.Size(m)
+}
+func (m *DeprecatedRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_DeprecatedRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DeprecatedRequest proto.InternalMessageInfo
+
+// Deprecated: Do not use.
+type DeprecatedResponse struct {
+	// DeprecatedField contains a DeprecatedEnum.
+	DeprecatedField      DeprecatedEnum `protobuf:"varint,1,opt,name=deprecated_field,json=deprecatedField,enum=deprecated.DeprecatedEnum" json:"deprecated_field,omitempty"` // Deprecated: Do not use.
+	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
+	XXX_unrecognized     []byte         `json:"-"`
+	XXX_sizecache        int32          `json:"-"`
+}
+
+func (m *DeprecatedResponse) Reset()         { *m = DeprecatedResponse{} }
+func (m *DeprecatedResponse) String() string { return proto.CompactTextString(m) }
+func (*DeprecatedResponse) ProtoMessage()    {}
+func (m *DeprecatedResponse) Unmarshal(b []byte) error {
+	return xxx_messageInfo_DeprecatedResponse.Unmarshal(m, b)
+}
+func (m *DeprecatedResponse) Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_DeprecatedResponse.Marshal(b, m, deterministic)
+}
+func (dst *DeprecatedResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DeprecatedResponse.Merge(dst, src)
+}
+func (m *DeprecatedResponse) XXX_Size() int {
+	return xxx_messageInfo_DeprecatedResponse.Size(m)
+}
+func (m *DeprecatedResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_DeprecatedResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DeprecatedResponse proto.InternalMessageInfo
+
+// Deprecated: Do not use.
+func (m *DeprecatedResponse) GetDeprecatedField() DeprecatedEnum {
+	if m != nil {
+		return m.DeprecatedField
+	}
+	return DeprecatedEnum_DEPRECATED
+}
+
+func init() {
+	proto.RegisterType((*DeprecatedRequest)(nil), "deprecated.DeprecatedRequest")
+	proto.RegisterType((*DeprecatedResponse)(nil), "deprecated.DeprecatedResponse")
+	proto.RegisterEnum("deprecated.DeprecatedEnum", DeprecatedEnum_name, DeprecatedEnum_value)
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// Client API for DeprecatedService service
+
+// Deprecated: Do not use.
+type DeprecatedServiceClient interface {
+	// DeprecatedCall takes a DeprecatedRequest and returns a DeprecatedResponse.
+	DeprecatedCall(ctx context.Context, in *DeprecatedRequest, opts ...grpc.CallOption) (*DeprecatedResponse, error)
+}
+
+type deprecatedServiceClient struct {
+	cc *grpc.ClientConn
+}
+
+// Deprecated: Do not use.
+func NewDeprecatedServiceClient(cc *grpc.ClientConn) DeprecatedServiceClient {
+	return &deprecatedServiceClient{cc}
+}
+
+// Deprecated: Do not use.
+func (c *deprecatedServiceClient) DeprecatedCall(ctx context.Context, in *DeprecatedRequest, opts ...grpc.CallOption) (*DeprecatedResponse, error) {
+	out := new(DeprecatedResponse)
+	err := grpc.Invoke(ctx, "/deprecated.DeprecatedService/DeprecatedCall", in, out, c.cc, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// Server API for DeprecatedService service
+
+// Deprecated: Do not use.
+type DeprecatedServiceServer interface {
+	// DeprecatedCall takes a DeprecatedRequest and returns a DeprecatedResponse.
+	DeprecatedCall(context.Context, *DeprecatedRequest) (*DeprecatedResponse, error)
+}
+
+// Deprecated: Do not use.
+func RegisterDeprecatedServiceServer(s *grpc.Server, srv DeprecatedServiceServer) {
+	s.RegisterService(&_DeprecatedService_serviceDesc, srv)
+}
+
+func _DeprecatedService_DeprecatedCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(DeprecatedRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(DeprecatedServiceServer).DeprecatedCall(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/deprecated.DeprecatedService/DeprecatedCall",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(DeprecatedServiceServer).DeprecatedCall(ctx, req.(*DeprecatedRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+var _DeprecatedService_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "deprecated.DeprecatedService",
+	HandlerType: (*DeprecatedServiceServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "DeprecatedCall",
+			Handler:    _DeprecatedService_DeprecatedCall_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "deprecated/deprecated.proto",
+}
diff --git a/protoc-gen-go/testdata/deprecated/deprecated.pb.go.golden b/protoc-gen-go/testdata/deprecated/deprecated.pb.go.golden
new file mode 100644
index 0000000..1cdbe42
--- /dev/null
+++ b/protoc-gen-go/testdata/deprecated/deprecated.pb.go.golden
@@ -0,0 +1,207 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// deprecated/deprecated.proto is a deprecated file.
+
+/*
+Package deprecated is a generated protocol buffer package.
+
+package deprecated contains only deprecated messages and services.
+
+It is generated from these files:
+	deprecated/deprecated.proto
+
+It has these top-level messages:
+	DeprecatedRequest
+	DeprecatedResponse
+*/
+package deprecated
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+import (
+	context "golang.org/x/net/context"
+	grpc "google.golang.org/grpc"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+// DeprecatedEnum contains deprecated values.
+type DeprecatedEnum int32 // Deprecated: Do not use.
+const (
+	// DEPRECATED is the iota value of this enum.
+	DeprecatedEnum_DEPRECATED DeprecatedEnum = 0 // Deprecated: Do not use.
+)
+
+var DeprecatedEnum_name = map[int32]string{
+	0: "DEPRECATED",
+}
+var DeprecatedEnum_value = map[string]int32{
+	"DEPRECATED": 0,
+}
+
+func (x DeprecatedEnum) String() string {
+	return proto.EnumName(DeprecatedEnum_name, int32(x))
+}
+
+// DeprecatedRequest is a request to DeprecatedCall.
+//
+// Deprecated: Do not use.
+type DeprecatedRequest struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *DeprecatedRequest) Reset()         { *m = DeprecatedRequest{} }
+func (m *DeprecatedRequest) String() string { return proto.CompactTextString(m) }
+func (*DeprecatedRequest) ProtoMessage()    {}
+func (m *DeprecatedRequest) Unmarshal(b []byte) error {
+	return xxx_messageInfo_DeprecatedRequest.Unmarshal(m, b)
+}
+func (m *DeprecatedRequest) Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_DeprecatedRequest.Marshal(b, m, deterministic)
+}
+func (dst *DeprecatedRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DeprecatedRequest.Merge(dst, src)
+}
+func (m *DeprecatedRequest) XXX_Size() int {
+	return xxx_messageInfo_DeprecatedRequest.Size(m)
+}
+func (m *DeprecatedRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_DeprecatedRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DeprecatedRequest proto.InternalMessageInfo
+
+// Deprecated: Do not use.
+type DeprecatedResponse struct {
+	// DeprecatedField contains a DeprecatedEnum.
+	DeprecatedField      DeprecatedEnum `protobuf:"varint,1,opt,name=deprecated_field,json=deprecatedField,enum=deprecated.DeprecatedEnum" json:"deprecated_field,omitempty"` // Deprecated: Do not use.
+	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
+	XXX_unrecognized     []byte         `json:"-"`
+	XXX_sizecache        int32          `json:"-"`
+}
+
+func (m *DeprecatedResponse) Reset()         { *m = DeprecatedResponse{} }
+func (m *DeprecatedResponse) String() string { return proto.CompactTextString(m) }
+func (*DeprecatedResponse) ProtoMessage()    {}
+func (m *DeprecatedResponse) Unmarshal(b []byte) error {
+	return xxx_messageInfo_DeprecatedResponse.Unmarshal(m, b)
+}
+func (m *DeprecatedResponse) Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_DeprecatedResponse.Marshal(b, m, deterministic)
+}
+func (dst *DeprecatedResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DeprecatedResponse.Merge(dst, src)
+}
+func (m *DeprecatedResponse) XXX_Size() int {
+	return xxx_messageInfo_DeprecatedResponse.Size(m)
+}
+func (m *DeprecatedResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_DeprecatedResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DeprecatedResponse proto.InternalMessageInfo
+
+// Deprecated: Do not use.
+func (m *DeprecatedResponse) GetDeprecatedField() DeprecatedEnum {
+	if m != nil {
+		return m.DeprecatedField
+	}
+	return DeprecatedEnum_DEPRECATED
+}
+
+func init() {
+	proto.RegisterType((*DeprecatedRequest)(nil), "deprecated.DeprecatedRequest")
+	proto.RegisterType((*DeprecatedResponse)(nil), "deprecated.DeprecatedResponse")
+	proto.RegisterEnum("deprecated.DeprecatedEnum", DeprecatedEnum_name, DeprecatedEnum_value)
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// Client API for DeprecatedService service
+
+// Deprecated: Do not use.
+type DeprecatedServiceClient interface {
+	// DeprecatedCall takes a DeprecatedRequest and returns a DeprecatedResponse.
+	DeprecatedCall(ctx context.Context, in *DeprecatedRequest, opts ...grpc.CallOption) (*DeprecatedResponse, error)
+}
+
+type deprecatedServiceClient struct {
+	cc *grpc.ClientConn
+}
+
+// Deprecated: Do not use.
+func NewDeprecatedServiceClient(cc *grpc.ClientConn) DeprecatedServiceClient {
+	return &deprecatedServiceClient{cc}
+}
+
+// Deprecated: Do not use.
+func (c *deprecatedServiceClient) DeprecatedCall(ctx context.Context, in *DeprecatedRequest, opts ...grpc.CallOption) (*DeprecatedResponse, error) {
+	out := new(DeprecatedResponse)
+	err := grpc.Invoke(ctx, "/deprecated.DeprecatedService/DeprecatedCall", in, out, c.cc, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// Server API for DeprecatedService service
+
+// Deprecated: Do not use.
+type DeprecatedServiceServer interface {
+	// DeprecatedCall takes a DeprecatedRequest and returns a DeprecatedResponse.
+	DeprecatedCall(context.Context, *DeprecatedRequest) (*DeprecatedResponse, error)
+}
+
+// Deprecated: Do not use.
+func RegisterDeprecatedServiceServer(s *grpc.Server, srv DeprecatedServiceServer) {
+	s.RegisterService(&_DeprecatedService_serviceDesc, srv)
+}
+
+func _DeprecatedService_DeprecatedCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(DeprecatedRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(DeprecatedServiceServer).DeprecatedCall(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/deprecated.DeprecatedService/DeprecatedCall",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(DeprecatedServiceServer).DeprecatedCall(ctx, req.(*DeprecatedRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+var _DeprecatedService_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "deprecated.DeprecatedService",
+	HandlerType: (*DeprecatedServiceServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "DeprecatedCall",
+			Handler:    _DeprecatedService_DeprecatedCall_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "deprecated/deprecated.proto",
+}
diff --git a/protoc-gen-go/testdata/deprecated/deprecated.proto b/protoc-gen-go/testdata/deprecated/deprecated.proto
new file mode 100644
index 0000000..5ee932a
--- /dev/null
+++ b/protoc-gen-go/testdata/deprecated/deprecated.proto
@@ -0,0 +1,67 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2018 The Go Authors.  All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+// package deprecated contains only deprecated messages and services.
+package deprecated;
+
+option deprecated = true; // file-level deprecation
+
+// DeprecatedRequest is a request to DeprecatedCall.
+message DeprecatedRequest {
+  option deprecated = true;
+}
+
+message DeprecatedResponse {
+  // comment for DeprecatedResponse is omitted to guarantee deprecation
+  // message doesn't append unnecessary comments.
+  option deprecated = true;
+  // DeprecatedField contains a DeprecatedEnum.
+  DeprecatedEnum deprecated_field = 1 [deprecated=true];
+}
+
+// DeprecatedEnum contains deprecated values.
+enum DeprecatedEnum {
+  option deprecated = true;
+  // DEPRECATED is the iota value of this enum.
+  DEPRECATED = 0 [deprecated=true];
+}
+
+// DeprecatedService is for making DeprecatedCalls
+service DeprecatedService {
+  option deprecated = true;
+
+  // DeprecatedCall takes a DeprecatedRequest and returns a DeprecatedResponse.
+  rpc DeprecatedCall(DeprecatedRequest) returns (DeprecatedResponse) {
+    option deprecated = true;
+  }
+}
\ No newline at end of file