From 03e0357934d908a6d677c99b87dafeac03e433d1 Mon Sep 17 00:00:00 2001 From: Mladen Todorovic Date: Thu, 21 Dec 2023 18:37:08 +0100 Subject: [PATCH] Add support for trailing comments in generated code --- protoc-gen-gogo/generator/generator.go | 72 +++++++++++++++++--------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/protoc-gen-gogo/generator/generator.go b/protoc-gen-gogo/generator/generator.go index 48fd721aea..b0a717bc71 100644 --- a/protoc-gen-gogo/generator/generator.go +++ b/protoc-gen-gogo/generator/generator.go @@ -35,9 +35,9 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* - The code generator for the plugin for the Google protocol buffer compiler. - It generates Go code from the protocol buffer description files read by the - main routine. +The code generator for the plugin for the Google protocol buffer compiler. +It generates Go code from the protocol buffer description files read by the +main routine. */ package generator @@ -987,7 +987,7 @@ func wrapImported(file *FileDescriptor, g *Generator) (sl []*ImportedDescriptor) func extractComments(file *FileDescriptor) { file.comments = make(map[string]*descriptor.SourceCodeInfo_Location) for _, loc := range file.GetSourceCodeInfo().GetLocation() { - if loc.LeadingComments == nil { + if loc.LeadingComments == nil && loc.TrailingComments == nil { continue } var p []string @@ -1321,22 +1321,39 @@ func (g *Generator) PrintComments(path string) bool { if !g.writeOutput { return false } - if c, ok := g.makeComments(path); ok { + if c, ok := g.makeLeadingComments(path); ok { g.P(c) return true } return false } -// makeComments generates the comment string for the field, no "\n" at the end -func (g *Generator) makeComments(path string) (string, bool) { +// makeLeadingComments generates the comment string for the field, no "\n" at the end +func (g *Generator) makeLeadingComments(path string) (string, bool) { loc, ok := g.file.comments[path] - if !ok { + comments := strings.TrimSuffix(loc.GetLeadingComments(), "\n") + if !ok || comments == "" { + return "", false + } + w := new(bytes.Buffer) + nl := "" + for _, line := range strings.Split(comments, "\n") { + fmt.Fprintf(w, "%s//%s", nl, line) + nl = "\n" + } + return w.String(), true +} + +// makeTrailingComments generates the trailing comment string for the field, no "\n" at the end +func (g *Generator) makeTrailingComments(path string) (string, bool) { + loc, ok := g.file.comments[path] + comments := strings.TrimSuffix(loc.GetTrailingComments(), "\n") + if !ok || comments == "" { return "", false } w := new(bytes.Buffer) nl := "" - for _, line := range strings.Split(strings.TrimSuffix(loc.GetLeadingComments(), "\n"), "\n") { + for _, line := range strings.Split(comments, "\n") { fmt.Fprintf(w, "%s//%s", nl, line) nl = "\n" } @@ -1597,6 +1614,7 @@ func (g *Generator) generateEnum(enum *EnumDescriptor) { // The tag is a string like "varint,2,opt,name=fieldname,def=7" that // identifies details of the field for the protocol buffer marshaling and unmarshaling // code. The fields are: +// // wire encoding // protocol tag number // opt,req,rep for optional, required, or repeated @@ -1605,6 +1623,7 @@ func (g *Generator) generateEnum(enum *EnumDescriptor) { // enum= the name of the enum type if it is an enum-typed field. // proto3 if this field is in a proto3 message // def= string representation of the default value, if any. +// // The default value must be in a representation that can be used at run-time // to generate the default value. Thus bools become 0 and 1, for instance. func (g *Generator) goTag(message *Descriptor, field *descriptor.FieldDescriptorProto, wiretype string) string { @@ -2171,17 +2190,18 @@ func (f *fieldCommon) getGoType() string { // simpleField is not weak, not a oneof, not an extension. Can be required, optional or repeated. type simpleField struct { fieldCommon - protoTypeName string // Proto type name, empty if primitive, e.g. ".google.protobuf.Duration" - protoType descriptor.FieldDescriptorProto_Type // Actual type enum value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64 - deprecated string // Deprecation comment, if any, e.g. "// Deprecated: Do not use." - getterDef string // Default for getters, e.g. "nil", `""` or "Default_MessageType_FieldName" - protoDef string // Default value as defined in the proto file, e.g "yoshi" or "5" - comment string // The full comment for the field, e.g. "// Useful information" + protoTypeName string // Proto type name, empty if primitive, e.g. ".google.protobuf.Duration" + protoType descriptor.FieldDescriptorProto_Type // Actual type enum value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64 + deprecated string // Deprecation comment, if any, e.g. "// Deprecated: Do not use." + getterDef string // Default for getters, e.g. "nil", `""` or "Default_MessageType_FieldName" + protoDef string // Default value as defined in the proto file, e.g "yoshi" or "5" + comment string // The full comment for the field, e.g. "// Useful information" + trailingComment string // The trailing comment for the field, e.g. "fieldName fieldType // Useful information" } // decl prints the declaration of the field in the struct (if any). func (f *simpleField) decl(g *Generator, mc *msgCtx) { - g.P(f.comment, Annotate(mc.message.file, f.fullPath, f.goName), "\t", f.goType, "\t`", f.tags, "`", f.deprecated) + g.P(f.comment, Annotate(mc.message.file, f.fullPath, f.goName), "\t", f.goType, "\t`", f.tags, "`", f.deprecated, " ", f.trailingComment) } // getter prints the getter for the field. @@ -3003,8 +3023,7 @@ func (g *Generator) generateMessage(message *Descriptor) { // This is the first field of a oneof we haven't seen before. // Generate the union field. oneofFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageOneofPath, *field.OneofIndex) - - c, ok := g.makeComments(oneofFullPath) + c, ok := g.makeLeadingComments(oneofFullPath) if ok { c += "\n//\n" } @@ -3102,10 +3121,12 @@ func (g *Generator) generateMessage(message *Descriptor) { } fieldFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i) - c, ok := g.makeComments(fieldFullPath) + c, ok := g.makeLeadingComments(fieldFullPath) if ok { c += "\n" } + tc, _ := g.makeTrailingComments(fieldFullPath) + rf := simpleField{ fieldCommon: fieldCommon{ goName: fieldName, @@ -3116,12 +3137,13 @@ func (g *Generator) generateMessage(message *Descriptor) { fullPath: fieldFullPath, protoField: field, }, - protoTypeName: field.GetTypeName(), - protoType: *field.Type, - deprecated: fieldDeprecated, - getterDef: dvalue, - protoDef: field.GetDefaultValue(), - comment: c, + protoTypeName: field.GetTypeName(), + protoType: *field.Type, + deprecated: fieldDeprecated, + getterDef: dvalue, + protoDef: field.GetDefaultValue(), + comment: c, + trailingComment: tc, } var pf topLevelField = &rf