Skip to content

Commit a556a4b

Browse files
authored
Found and fixed a bug in FieldDescriptor.Cardinality implementation (#270)
Updates the descriptor implementation tests to check a few other attributes, which uncovered a bug in the `Cardinality` method, which should report "required" for editions fields where `features.field_presence == LEGACY_REQUIRED`.
1 parent ddfc09b commit a556a4b

File tree

2 files changed

+15
-0
lines changed

2 files changed

+15
-0
lines changed

linker/descriptors.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,14 @@ func (f *fldDescriptor) Cardinality() protoreflect.Cardinality {
10471047
case descriptorpb.FieldDescriptorProto_LABEL_REQUIRED:
10481048
return protoreflect.Required
10491049
case descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL:
1050+
if f.Syntax() == protoreflect.Editions {
1051+
// Editions does not use label to indicate required. It instead
1052+
// uses a feature, and label is always optional.
1053+
fieldPresence := descriptorpb.FeatureSet_FieldPresence(resolveFeature(f, fieldPresenceField).Enum())
1054+
if fieldPresence == descriptorpb.FeatureSet_LEGACY_REQUIRED {
1055+
return protoreflect.Required
1056+
}
1057+
}
10501058
return protoreflect.Optional
10511059
default:
10521060
return 0
@@ -1055,6 +1063,8 @@ func (f *fldDescriptor) Cardinality() protoreflect.Cardinality {
10551063

10561064
func (f *fldDescriptor) Kind() protoreflect.Kind {
10571065
if f.proto.GetType() == descriptorpb.FieldDescriptorProto_TYPE_MESSAGE && f.Syntax() == protoreflect.Editions {
1066+
// In editions, "group encoding" (aka "delimited encoding") is toggled
1067+
// via a feature. So we report group kind when that feature is enabled.
10581068
messageEncoding := resolveFeature(f, messageEncodingField)
10591069
if descriptorpb.FeatureSet_MessageEncoding(messageEncoding.Enum()) == descriptorpb.FeatureSet_DELIMITED {
10601070
return protoreflect.GroupKind

linker/descriptors_ext_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,16 @@ func checkAttributesInFields(t *testing.T, exp, actual protoreflect.ExtensionDes
148148
if !assert.Equal(t, expFld.Name(), actFld.Name(), "%s: field name at index %d", where, i) {
149149
continue
150150
}
151+
assert.Equal(t, expFld.Number(), actFld.Number(), "%s: field number at index %d (%s)", where, i, expFld.Name())
152+
assert.Equal(t, expFld.Cardinality(), actFld.Cardinality(), "%s: field cardinality at index %d (%s)", where, i, expFld.Name())
151153
assert.Equal(t, expFld.Kind(), actFld.Kind(), "%s: field kind at index %d (%s)", where, i, expFld.Name())
152154
assert.Equal(t, expFld.IsList(), actFld.IsList(), "%s: field is list at index %d (%s)", where, i, expFld.Name())
153155
assert.Equal(t, expFld.IsMap(), actFld.IsMap(), "%s: field is map at index %d (%s)", where, i, expFld.Name())
154156
assert.Equal(t, expFld.JSONName(), actFld.JSONName(), "%s: field json name at index %d (%s)", where, i, expFld.Name())
155157
assert.Equal(t, expFld.HasJSONName(), actFld.HasJSONName(), "%s: field has json name at index %d (%s)", where, i, expFld.Name())
158+
assert.Equal(t, expFld.IsExtension(), actFld.IsExtension(), "%s: field is extension at index %d (%s)", where, i, expFld.Name())
159+
assert.Equal(t, expFld.IsPacked(), actFld.IsPacked(), "%s: field is packed at index %d (%s)", where, i, expFld.Name())
160+
assert.Equal(t, expFld.ContainingOneof() == nil, actFld.ContainingOneof() == nil, "%s: field containing oneof at index %d (%s)", where, i, expFld.Name())
156161

157162
// default values
158163

0 commit comments

Comments
 (0)