From 0facb742c9dcbc99667de77a4b74b842f9aa0bb3 Mon Sep 17 00:00:00 2001 From: Trung-Hai Bui Date: Thu, 17 Nov 2022 21:30:15 +0800 Subject: [PATCH] desc/builder: fix missing detached leading comments (#539) --- .gitignore | 3 ++ desc/builder/builder.go | 2 +- desc/builder/builder_test.go | 87 ++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 02a29a0f..4fd86225 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ internal/testprotos/protoc coverage.out + +# Generated file for Goland workspace +.idea \ No newline at end of file diff --git a/desc/builder/builder.go b/desc/builder/builder.go index 5ece1ed6..a8053996 100644 --- a/desc/builder/builder.go +++ b/desc/builder/builder.go @@ -146,7 +146,7 @@ func addCommentsTo(sourceInfo *dpb.SourceCodeInfo, path []int32, c *Comments) { var detached []string if len(c.LeadingDetachedComments) > 0 { - detached := make([]string, len(c.LeadingDetachedComments)) + detached = make([]string, len(c.LeadingDetachedComments)) copy(detached, c.LeadingDetachedComments) } diff --git a/desc/builder/builder_test.go b/desc/builder/builder_test.go index f9e4d913..e9e0cc64 100644 --- a/desc/builder/builder_test.go +++ b/desc/builder/builder_test.go @@ -13,6 +13,7 @@ import ( "github.com/golang/protobuf/ptypes/any" "github.com/golang/protobuf/ptypes/empty" "github.com/golang/protobuf/ptypes/timestamp" + "github.com/jhump/protoreflect/desc/protoparse" "github.com/jhump/protoreflect/desc" "github.com/jhump/protoreflect/dynamic" @@ -455,6 +456,92 @@ func TestBuildersFromDescriptors_PreserveComments(t *testing.T) { testutil.Eq(t, count, descCount) } +func TestBuilder_PreserveAllCommentsAfterBuild(t *testing.T) { + files := map[string]string{"test.proto": ` +syntax = "proto3"; + +// Leading detached comment for SimpleEnum + +// Leading comment for SimpleEnum +enum SimpleEnum { +// Trailing comment for SimpleEnum + + // Leading detached comment for VALUE0 + + // Leading comment for VALUE0 + VALUE0 = 0; // Trailing comment for VALUE0 +} + +// Leading detached comment for SimpleMessage + +// Leading comment for SimpleMessage +message SimpleMessage { +// Trailing comment for SimpleMessage + + // Leading detached comment for field1 + + // Leading comment for field1 + optional SimpleEnum field1 = 1; // Trailing comment for field1 +} +`} + + pa := &protoparse.Parser{ + Accessor: protoparse.FileContentsFromMap(files), + IncludeSourceCodeInfo: true, + } + fds, err := pa.ParseFiles("test.proto") + testutil.Ok(t, err) + + fb, err := FromFile(fds[0]) + testutil.Ok(t, err) + + fd, err := fb.Build() + testutil.Ok(t, err) + + var checkDescriptorComments func(d desc.Descriptor) + checkDescriptorComments = func(d desc.Descriptor) { + // fmt.Println(d.GetFullyQualifiedName(), d.GetSourceInfo().GetLeadingDetachedComments(), d.GetSourceInfo().GetLeadingComments(), d.GetSourceInfo().GetTrailingComments()) + switch d := d.(type) { + case *desc.FileDescriptor: + for _, ch := range d.GetMessageTypes() { + checkDescriptorComments(ch) + } + for _, ch := range d.GetEnumTypes() { + checkDescriptorComments(ch) + } + // files don't have comments, so bail out before check below + return + case *desc.MessageDescriptor: + if d.IsMapEntry() { + // map entry messages have no comments (and neither do their child fields) + return + } + for _, ch := range d.GetFields() { + checkDescriptorComments(ch) + } + case *desc.FieldDescriptor: + if d.GetType() == dpb.FieldDescriptorProto_TYPE_GROUP { + // groups comments are on the message, not hte field; so bail out before check below + return + } + case *desc.EnumDescriptor: + for _, ch := range d.GetValues() { + checkDescriptorComments(ch) + } + } + testutil.Eq(t, 1, len(d.GetSourceInfo().GetLeadingDetachedComments()), + "wrong number of leading detached comments for %s", d.GetFullyQualifiedName()) + testutil.Eq(t, fmt.Sprintf(" Leading detached comment for %s\n", d.GetName()), d.GetSourceInfo().GetLeadingDetachedComments()[0], + "wrong leading detached comment for descriptor %s", d.GetFullyQualifiedName()) + testutil.Eq(t, fmt.Sprintf(" Leading comment for %s\n", d.GetName()), d.GetSourceInfo().GetLeadingComments(), + "wrong leading comment for descriptor %s", d.GetFullyQualifiedName()) + testutil.Eq(t, fmt.Sprintf(" Trailing comment for %s\n", d.GetName()), d.GetSourceInfo().GetTrailingComments(), + "wrong trailing comment for descriptor %s", d.GetFullyQualifiedName()) + } + + checkDescriptorComments(fd) +} + func loadProtoset(path string) (*desc.FileDescriptor, error) { var fds dpb.FileDescriptorSet f, err := os.Open(path)