reflect/protoreflect: add helper methods to FieldDescriptor
Added API:
FieldDescriptor.IsExtension
FieldDescriptor.IsList
FieldDescriptor.MapKey
FieldDescriptor.MapValue
FieldDescriptor.ContainingOneof
FieldDescriptor.ContainingMessage
Deprecated API (to be removed in subsequent CL):
FieldDescriptor.Oneof
FieldDescriptor.Extendee
These methods help cleanup several common usage patterns.
Change-Id: I9a3ffabc2edb2173c536509b22f330f98bba7cf3
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/176977
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/internal/fileinit/desc.go b/internal/fileinit/desc.go
index 2729da6..8854cab 100644
--- a/internal/fileinit/desc.go
+++ b/internal/fileinit/desc.go
@@ -431,23 +431,43 @@
func (fd *fieldDesc) Options() pref.ProtoMessage {
return unmarshalOptions(descopts.Field, fd.options)
}
-func (fd *fieldDesc) Number() pref.FieldNumber { return fd.number }
-func (fd *fieldDesc) Cardinality() pref.Cardinality { return fd.cardinality }
-func (fd *fieldDesc) Kind() pref.Kind { return fd.kind }
-func (fd *fieldDesc) HasJSONName() bool { return fd.hasJSONName }
-func (fd *fieldDesc) JSONName() string { return fd.jsonName }
-func (fd *fieldDesc) IsPacked() bool { return fd.isPacked }
-func (fd *fieldDesc) IsWeak() bool { return fd.isWeak }
-func (fd *fieldDesc) IsMap() bool { return fd.isMap }
+func (fd *fieldDesc) Number() pref.FieldNumber { return fd.number }
+func (fd *fieldDesc) Cardinality() pref.Cardinality { return fd.cardinality }
+func (fd *fieldDesc) Kind() pref.Kind { return fd.kind }
+func (fd *fieldDesc) HasJSONName() bool { return fd.hasJSONName }
+func (fd *fieldDesc) JSONName() string { return fd.jsonName }
+func (fd *fieldDesc) IsPacked() bool { return fd.isPacked }
+func (fd *fieldDesc) IsExtension() bool { return false }
+func (fd *fieldDesc) IsWeak() bool { return fd.isWeak }
+func (fd *fieldDesc) IsList() bool { return fd.cardinality == pref.Repeated && !fd.IsMap() }
+func (fd *fieldDesc) IsMap() bool { return fd.isMap }
+func (fd *fieldDesc) MapKey() pref.FieldDescriptor {
+ if !fd.isMap {
+ return nil
+ }
+ return fd.Message().Fields().ByNumber(1)
+}
+func (fd *fieldDesc) MapValue() pref.FieldDescriptor {
+ if !fd.isMap {
+ return nil
+ }
+ return fd.Message().Fields().ByNumber(2)
+}
func (fd *fieldDesc) HasDefault() bool { return fd.defVal.has }
func (fd *fieldDesc) Default() pref.Value { return fd.defVal.get() }
func (fd *fieldDesc) DefaultEnumValue() pref.EnumValueDescriptor { return fd.defVal.enum }
-func (fd *fieldDesc) Oneof() pref.OneofDescriptor { return fd.oneofType }
-func (fd *fieldDesc) Extendee() pref.MessageDescriptor { return nil }
-func (fd *fieldDesc) Enum() pref.EnumDescriptor { return fd.enumType }
-func (fd *fieldDesc) Message() pref.MessageDescriptor { return fd.messageType }
-func (fd *fieldDesc) Format(s fmt.State, r rune) { pfmt.FormatDesc(s, r, fd) }
-func (fd *fieldDesc) ProtoType(pref.FieldDescriptor) {}
+func (fd *fieldDesc) ContainingOneof() pref.OneofDescriptor { return fd.oneofType }
+func (fd *fieldDesc) ContainingMessage() pref.MessageDescriptor {
+ return fd.parent.(pref.MessageDescriptor)
+}
+func (fd *fieldDesc) Enum() pref.EnumDescriptor { return fd.enumType }
+func (fd *fieldDesc) Message() pref.MessageDescriptor { return fd.messageType }
+func (fd *fieldDesc) Format(s fmt.State, r rune) { pfmt.FormatDesc(s, r, fd) }
+func (fd *fieldDesc) ProtoType(pref.FieldDescriptor) {}
+
+// TODO: Remove this.
+func (fd *fieldDesc) Oneof() pref.OneofDescriptor { return fd.oneofType }
+func (fd *fieldDesc) Extendee() pref.MessageDescriptor { return nil }
func (od *oneofDesc) Options() pref.ProtoMessage {
return unmarshalOptions(descopts.Oneof, od.options)
@@ -505,13 +525,17 @@
func (xd *extensionDesc) HasJSONName() bool { return xd.lazyInit().hasJSONName }
func (xd *extensionDesc) JSONName() string { return xd.lazyInit().jsonName }
func (xd *extensionDesc) IsPacked() bool { return xd.lazyInit().isPacked }
+func (xd *extensionDesc) IsExtension() bool { return true }
func (xd *extensionDesc) IsWeak() bool { return false }
+func (xd *extensionDesc) IsList() bool { return xd.Cardinality() == pref.Repeated }
func (xd *extensionDesc) IsMap() bool { return false }
+func (xd *extensionDesc) MapKey() pref.FieldDescriptor { return nil }
+func (xd *extensionDesc) MapValue() pref.FieldDescriptor { return nil }
func (xd *extensionDesc) HasDefault() bool { return xd.lazyInit().defVal.has }
func (xd *extensionDesc) Default() pref.Value { return xd.lazyInit().defVal.get() }
func (xd *extensionDesc) DefaultEnumValue() pref.EnumValueDescriptor { return xd.lazyInit().defVal.enum }
-func (xd *extensionDesc) Oneof() pref.OneofDescriptor { return nil }
-func (xd *extensionDesc) Extendee() pref.MessageDescriptor { return xd.extendedType }
+func (xd *extensionDesc) ContainingOneof() pref.OneofDescriptor { return nil }
+func (xd *extensionDesc) ContainingMessage() pref.MessageDescriptor { return xd.extendedType }
func (xd *extensionDesc) Enum() pref.EnumDescriptor { return xd.lazyInit().enumType }
func (xd *extensionDesc) Message() pref.MessageDescriptor { return xd.lazyInit().messageType }
func (xd *extensionDesc) Format(s fmt.State, r rune) { pfmt.FormatDesc(s, r, xd) }
@@ -531,6 +555,10 @@
return xd.legacyDesc
}
+// TODO: Remove this.
+func (xd *extensionDesc) Oneof() pref.OneofDescriptor { return nil }
+func (xd *extensionDesc) Extendee() pref.MessageDescriptor { return xd.extendedType }
+
type (
serviceDesc struct {
baseDesc
diff --git a/internal/fileinit/fileinit_test.go b/internal/fileinit/fileinit_test.go
index ac1c5e2..dd58fd0 100644
--- a/internal/fileinit/fileinit_test.go
+++ b/internal/fileinit/fileinit_test.go
@@ -88,7 +88,7 @@
f(field)
switch field.Kind() {
case protoreflect.MessageKind, protoreflect.GroupKind:
- if field.Cardinality() == protoreflect.Repeated {
+ if field.IsList() {
for i, list := 0, value.List(); i < list.Len(); i++ {
visitFields(list.Get(i).Message(), f)
}