Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

protoc-gen-go: indicate deprecated fields in documentation #506

Merged
merged 1 commit into from
Feb 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 42 additions & 5 deletions protoc-gen-go/generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -1330,7 +1330,11 @@ func (g *Generator) generate(file *FileDescriptor) {
// 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()
Expand Down Expand Up @@ -1374,6 +1378,10 @@ func (g *Generator) generateHeader() {
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.
Expand Down Expand Up @@ -1488,17 +1496,26 @@ func (g *Generator) generateEnum(enum *EnumDescriptor) {
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()
for i, e := range enum.Value {
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()
Expand Down Expand Up @@ -1839,7 +1856,18 @@ func (g *Generator) generateMessage(message *Descriptor) {
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()

Expand Down Expand Up @@ -1965,9 +1993,14 @@ func (g *Generator) generateMessage(message *Descriptor) {
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
Expand Down Expand Up @@ -2252,6 +2285,10 @@ func (g *Generator) generateMessage(message *Descriptor) {
})
}

if field.GetOptions().GetDeprecated() {
g.P(deprecationComment)
}

g.P("func (m *", ccTypeName, ") ", Annotate(message.file, fieldFullPath, mname), "() "+typename+" {")
g.In()
def, hasDef := defNames[field]
Expand Down
22 changes: 21 additions & 1 deletion protoc-gen-go/grpc/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,15 @@ func (g *grpc) GenerateImports(file *generator.FileDescriptor) {

// 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.
Expand All @@ -153,12 +157,16 @@ func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.Servi
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.
Expand All @@ -174,6 +182,9 @@ func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.Servi
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("}")
Expand All @@ -200,6 +211,9 @@ func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.Servi
g.P()

// Server interface.
if deprecated {
g.P(deprecationComment)
}
serverType := servName + "Server"
g.P("type ", serverType, " interface {")
for i, method := range service.Method {
Expand All @@ -210,6 +224,9 @@ func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.Servi
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("}")
Expand Down Expand Up @@ -283,6 +300,9 @@ func (g *grpc) generateClientMethod(servName, fullServName, serviceDescVar strin
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, ")")
Expand Down
11 changes: 11 additions & 0 deletions protoc-gen-go/testdata/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ golden:
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
Expand Down
207 changes: 207 additions & 0 deletions protoc-gen-go/testdata/deprecated/deprecated.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading