Skip to content

Commit

Permalink
Found and fixed a bug in FieldDescriptor.Cardinality implementation (b…
Browse files Browse the repository at this point in the history
…ufbuild#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`.

(cherry picked from commit a556a4b)
  • Loading branch information
jhump authored and kralicky committed Apr 12, 2024
1 parent 80b3549 commit 65d0d4b
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 0 deletions.
10 changes: 10 additions & 0 deletions linker/descriptors.go
Original file line number Diff line number Diff line change
Expand Up @@ -1200,6 +1200,14 @@ func (f *fldDescriptor) Cardinality() protoreflect.Cardinality {
case descriptorpb.FieldDescriptorProto_LABEL_REQUIRED:
return protoreflect.Required
case descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL:
if f.Syntax() == protoreflect.Editions {
// Editions does not use label to indicate required. It instead
// uses a feature, and label is always optional.
fieldPresence := descriptorpb.FeatureSet_FieldPresence(resolveFeature(f, fieldPresenceField).Enum())
if fieldPresence == descriptorpb.FeatureSet_LEGACY_REQUIRED {
return protoreflect.Required
}
}
return protoreflect.Optional
default:
return 0
Expand All @@ -1208,6 +1216,8 @@ func (f *fldDescriptor) Cardinality() protoreflect.Cardinality {

func (f *fldDescriptor) Kind() protoreflect.Kind {
if f.proto.GetType() == descriptorpb.FieldDescriptorProto_TYPE_MESSAGE && f.Syntax() == protoreflect.Editions {
// In editions, "group encoding" (aka "delimited encoding") is toggled
// via a feature. So we report group kind when that feature is enabled.
messageEncoding := resolveFeature(f, messageEncodingField)
if descriptorpb.FeatureSet_MessageEncoding(messageEncoding.Enum()) == descriptorpb.FeatureSet_DELIMITED {
return protoreflect.GroupKind
Expand Down
5 changes: 5 additions & 0 deletions linker/descriptors_ext_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,16 @@ func checkAttributesInFields(t *testing.T, exp, actual protoreflect.ExtensionDes
if !assert.Equal(t, expFld.Name(), actFld.Name(), "%s: field name at index %d", where, i) {
continue
}
assert.Equal(t, expFld.Number(), actFld.Number(), "%s: field number at index %d (%s)", where, i, expFld.Name())
assert.Equal(t, expFld.Cardinality(), actFld.Cardinality(), "%s: field cardinality at index %d (%s)", where, i, expFld.Name())
assert.Equal(t, expFld.Kind(), actFld.Kind(), "%s: field kind at index %d (%s)", where, i, expFld.Name())
assert.Equal(t, expFld.IsList(), actFld.IsList(), "%s: field is list at index %d (%s)", where, i, expFld.Name())
assert.Equal(t, expFld.IsMap(), actFld.IsMap(), "%s: field is map at index %d (%s)", where, i, expFld.Name())
assert.Equal(t, expFld.JSONName(), actFld.JSONName(), "%s: field json name at index %d (%s)", where, i, expFld.Name())
assert.Equal(t, expFld.HasJSONName(), actFld.HasJSONName(), "%s: field has json name at index %d (%s)", where, i, expFld.Name())
assert.Equal(t, expFld.IsExtension(), actFld.IsExtension(), "%s: field is extension at index %d (%s)", where, i, expFld.Name())
assert.Equal(t, expFld.IsPacked(), actFld.IsPacked(), "%s: field is packed at index %d (%s)", where, i, expFld.Name())
assert.Equal(t, expFld.ContainingOneof() == nil, actFld.ContainingOneof() == nil, "%s: field containing oneof at index %d (%s)", where, i, expFld.Name())

// default values

Expand Down

0 comments on commit 65d0d4b

Please sign in to comment.