Skip to content

Commit 5340254

Browse files
authored
Update protoc to v22.0 (#100)
This repo uses `protoc` for verification -- to make sure that things like options interpretation and source code info match what the reference compiler produces. This updates the version of `protoc` used to the latest release v22.0. This uncovered discrepancies: changes/fixes in `protoc` that required changes to protocompile code to match. This includes a very minor change to the canonical binary format for options and more significant improvements to comment attribution in source code info.
1 parent 2c27603 commit 5340254

15 files changed

+447
-304
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ UNAME_OS := $(shell uname -s)
1616
UNAME_ARCH := $(shell uname -m)
1717

1818
# NB: this must be kept in sync with constant in internal/benchmarks.
19-
PROTOC_VERSION ?= 21.7
19+
PROTOC_VERSION ?= 22.0
2020
PROTOC_DIR := $(abspath ./internal/testdata/protoc/$(PROTOC_VERSION))
2121
PROTOC := $(PROTOC_DIR)/bin/protoc
2222

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require (
66
github.com/google/go-cmp v0.5.9
77
github.com/stretchr/testify v1.8.1
88
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
9-
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8
9+
google.golang.org/protobuf v1.28.2-0.20230222093303-bc1253ad3743
1010
)
1111

1212
require (

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cO
1818
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
1919
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
2020
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
21-
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 h1:KR8+MyP7/qOlV+8Af01LtjL04bu7on42eVsxT4EyBQk=
22-
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
21+
google.golang.org/protobuf v1.28.2-0.20230222093303-bc1253ad3743 h1:yqElulDvOF26oZ2O+2/aoX7mQ8DY/6+p39neytrycd8=
22+
google.golang.org/protobuf v1.28.2-0.20230222093303-bc1253ad3743/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
2323
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
2424
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
2525
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

internal/benchmarks/benchmark_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ import (
5151

5252
const (
5353
// NB: this must be kept in sync with PROTOC_VERSION in Makefile.
54-
protocVersion = "21.7"
54+
protocVersion = "22.0"
5555

5656
googleapisCommit = "cb6fbe8784479b22af38c09a5039d8983e894566"
5757
)

internal/testdata/all.protoset

903 Bytes
Binary file not shown.

internal/testdata/desc_test_comments.proto

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,14 @@ message /* detached message name */ /* request with a capital R */ Request // tr
5858
// this is a custom option
5959
option (testprotos.mfubar) = false;
6060

61-
optional double dbl = 1;
62-
optional float flt = 2;
61+
optional double dbl = 1; /* trailing comment for dbl */ /* detached comment */ /* leading comment for flt */ optional float flt = 2;
6362

64-
option no_standard_descriptor_accessor = false;
63+
option no_standard_descriptor_accessor = false; /* weird trailing comment
64+
for the option that gets
65+
classified as detached
66+
since it's on the same
67+
line as the following
68+
element */ option deprecated=true;
6569

6670
// Leading comment...
6771
optional string str = 3;
@@ -76,8 +80,7 @@ message /* detached message name */ /* request with a capital R */ Request // tr
7680

7781
MARIO = 1 [(testprotos.evfubars) = -314, (testprotos.evfubar) = 278];
7882
LUIGI = 2 [ (testprotos.evfubaruf) = 100, /* swoosh! */ (testprotos.evfubaru)=200];
79-
PEACH = 3;
80-
BOWSER = 4;
83+
PEACH = 3; /* peach trailer */ /* bowser leader */ BOWSER = 4;
8184

8285
option (testprotos.efubars) = -321;
8386

@@ -128,7 +131,14 @@ Request
128131
}
129132
// after extend block
130133

131-
message /* name leading comment */ AnEmptyMessage /* name trailing comment */ { /* trailer for AnEmptyMessage */ }
134+
message /* name leading comment */ AnEmptyMessage /* name trailing comment */ { /* detached comment inside AnEmptyMessage */ }
135+
136+
/*
137+
* Tests javadoc style comment, where every line in block comment has leading
138+
* asterisk that should be stripped.
139+
*/
140+
message AnotherEmptyMessage { /* trailer for AnotherEmptyMessage */
141+
}
132142

133143
// Service comment
134144
service /* service name */ RpcService {
@@ -141,6 +151,10 @@ service /* service name */ RpcService {
141151
option(testprotos.sfubar).name= "bob";
142152
option deprecated = false; // DEPRECATED!
143153

154+
/**
155+
* Another javadoc-style comment.
156+
* This one has the double-asterisk on first line, like javadoc.
157+
*/
144158
option (testprotos.sfubare) = VALUE;
145159

146160
// Method comment
878 Bytes
Binary file not shown.

internal/testdata/desc_test_options.proto

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,9 @@ extend google.protobuf.FileOptions {
6868
}
6969

7070
// a file option!
71-
option (flfubar) = "foobar"; // line comment with no trailing newline
71+
// TODO: After https://github.com/protocolbuffers/protobuf/pull/12082 makes it into
72+
// a protoc release, remove the newline at the end of the file to make the
73+
// following comment true. (For now, we need the newline in order for protoc
74+
// to produce source code info we can match with protocompile since we don't
75+
// have the same bug.)
76+
option (flfubar) = "foobar"; // line comment with no trailing newline
Binary file not shown.
878 Bytes
Binary file not shown.
934 Bytes
Binary file not shown.

options/options.go

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,14 +784,66 @@ func (interp *interpreter) interpretOptions(fqn string, element, opts proto.Mess
784784
return nil, nil
785785
}
786786

787+
// isKnownField returns true if the given option is for a known field of the
788+
// given options message descriptor and will be serialized using the expected
789+
// wire type for that known field.
787790
func isKnownField(desc protoreflect.MessageDescriptor, opt *interpretedOption) bool {
788791
var num int32
789792
if len(opt.pathPrefix) > 0 {
790793
num = opt.pathPrefix[0]
791794
} else {
792795
num = opt.number
793796
}
794-
return desc.Fields().ByNumber(protoreflect.FieldNumber(num)) != nil
797+
fd := desc.Fields().ByNumber(protoreflect.FieldNumber(num))
798+
if fd == nil {
799+
return false
800+
}
801+
802+
// Before the full wire type check, we do a quick check that will usually pass
803+
// and allow us to short-circuit the logic below.
804+
if fd.IsList() == opt.repeated && fd.Kind() == opt.kind {
805+
return true
806+
}
807+
808+
// We figure out the wire type this interpreted field will use when serialized.
809+
var wireType protowire.Type
810+
switch {
811+
case len(opt.pathPrefix) > 0:
812+
// If path prefix exists, this field is nested inside a message.
813+
// And messages use bytes wire type.
814+
wireType = protowire.BytesType
815+
case opt.repeated && opt.packed && canPack(opt.kind):
816+
// Packed repeated numeric scalars use bytes wire type.
817+
wireType = protowire.BytesType
818+
default:
819+
wireType = wireTypeForKind(opt.kind)
820+
}
821+
822+
// And then we see if the wire type we just determined is compatible with
823+
// the field descriptor we found.
824+
if fd.IsList() && canPack(fd.Kind()) && wireType == protowire.BytesType {
825+
// Even if fd.IsPacked() is false, bytes type is still accepted for
826+
// repeated scalar numerics, so that changing a repeated field from
827+
// packed to not-packed (or vice versa) is a compatible change.
828+
return true
829+
}
830+
return wireType == wireTypeForKind(fd.Kind())
831+
}
832+
833+
func wireTypeForKind(kind protoreflect.Kind) protowire.Type {
834+
switch kind {
835+
case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind:
836+
return protowire.BytesType
837+
case protoreflect.GroupKind:
838+
return protowire.StartGroupType
839+
case protoreflect.Fixed32Kind, protoreflect.Sfixed32Kind, protoreflect.FloatKind:
840+
return protowire.Fixed32Type
841+
case protoreflect.Fixed64Kind, protoreflect.Sfixed64Kind, protoreflect.DoubleKind:
842+
return protowire.Fixed64Type
843+
default:
844+
// everything else uses varint
845+
return protowire.VarintType
846+
}
795847
}
796848

797849
func cloneInto(dest proto.Message, src proto.Message, res linker.Resolver) error {

sourceinfo/source_code_info.go

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -651,17 +651,8 @@ func (sci *sourceCodeInfo) maybeDonate(prevInfo ast.NodeInfo, info ast.NodeInfo,
651651
// nothing to donate
652652
return ast.EmptyComments, nil
653653
}
654-
if !sci.extraComments {
655-
// Mirroring protoc for now: if tokens on the same line, attribution
656-
// is ambiguous so drop everything.
657-
// This condition can be dropped (and we can stop dropping comments)
658-
// once this PR is released:
659-
// https://github.com/protocolbuffers/protobuf/pull/10660
660-
if prevInfo.End().Line == info.Start().Line {
661-
return ast.EmptyComments, nil
662-
}
663-
}
664-
if lead[0].Index(0).Start().Line > prevInfo.End().Line+1 {
654+
firstCommentPos := lead[0].Index(0)
655+
if firstCommentPos.Start().Line > prevInfo.End().Line+1 {
665656
// first comment is detached from previous token, so can't be a trailing comment
666657
return ast.EmptyComments, lead
667658
}
@@ -671,16 +662,26 @@ func (sci *sourceCodeInfo) maybeDonate(prevInfo ast.NodeInfo, info ast.NodeInfo,
671662
}
672663
// there is only one element in lead
673664
comment := lead[0]
674-
if comment.Index(comment.Len()-1).End().Line < info.Start().Line-1 {
665+
lastCommentPos := comment.Index(comment.Len() - 1)
666+
if lastCommentPos.End().Line < info.Start().Line-1 {
675667
// there is a blank line between the comments and subsequent token, so
676668
// we can donate the comment to previous token
677669
return comment, nil
678670
}
679-
if txt := info.RawText(); len(txt) == 1 && strings.ContainsAny(txt, "}]),;") {
680-
// token is a symbol for the end of a scope, which doesn't need a leading comment
671+
if txt := info.RawText(); txt == "" || (len(txt) == 1 && strings.ContainsAny(txt, "}]),;")) {
672+
// token is a symbol for the end of a scope or EOF, which doesn't need a leading comment
673+
if !sci.extraComments && txt != "" &&
674+
firstCommentPos.Start().Line == prevInfo.End().Line &&
675+
lastCommentPos.End().Line == info.Start().Line {
676+
// protoc does not donate if prev and next token are on the same line since it's
677+
// ambiguous which one should get the comment; so we mirror that here
678+
return ast.EmptyComments, lead
679+
}
680+
// But with extra comments, we always donate in this situation in order to capture
681+
// more comments. Because otherwise, these comments are lost since these symbols
682+
// don't map to a location in source code info.
681683
return comment, nil
682684
}
683-
684685
// cannot donate
685686
return ast.EmptyComments, lead
686687
}
@@ -697,14 +698,6 @@ func (sci *sourceCodeInfo) maybeAttach(prevInfo ast.NodeInfo, info ast.NodeInfo,
697698
attachedToPrevious := comment.Index(0).Start().Line == prevInfo.End().Line
698699
attachedToNext := comment.Index(comment.Len()-1).End().Line == info.Start().Line
699700
if attachedToPrevious && attachedToNext {
700-
if !sci.extraComments {
701-
// Mirroring protoc for now: if comment starts on line of previous token
702-
// and ends on line of next, attribution is ambiguous so drop everything.
703-
// This condition can be dropped (and we can stop dropping comments)
704-
// once this PR is released:
705-
// https://github.com/protocolbuffers/protobuf/pull/10660
706-
return nil, ast.EmptyComments
707-
}
708701
// Since attachment is ambiguous, leave it detached.
709702
return lead, ast.EmptyComments
710703
}
@@ -787,9 +780,10 @@ func (sci *sourceCodeInfo) combineComments(comments comments) string {
787780
for _, l := range lines {
788781
if first {
789782
first = false
790-
} else {
791-
buf.WriteByte('\n')
783+
buf.WriteString(l)
784+
continue
792785
}
786+
buf.WriteByte('\n')
793787

794788
// strip a prefix of whitespace followed by '*'
795789
j := 0
@@ -805,7 +799,7 @@ func (sci *sourceCodeInfo) combineComments(comments comments) string {
805799
case l[j] == '*':
806800
l = l[j+1:]
807801
case j > 0:
808-
l = " " + l[j:]
802+
l = l[j:]
809803
}
810804

811805
buf.WriteString(l)

0 commit comments

Comments
 (0)