reflect: add Index method to descriptor

Useful for dealing with SourceCodeInfo location paths, which identify
entities by their index.

Change-Id: I2034fc06b14c9b29b26e356fad21e106f63fbd14
Reviewed-on: https://go-review.googlesource.com/134115
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
This commit is contained in:
Damien Neil 2018-09-07 09:39:44 -07:00
parent c84688961e
commit 3de06c0868
7 changed files with 42 additions and 12 deletions

View File

@ -114,7 +114,7 @@ var listTypesTemplate = template.Must(template.New("").Funcs(template.FuncMap{
panic("already initialized")
}
t.{{$nameMeta}} = &metas[i]
t.inheritedMeta.init(nb, parent, t.Name, {{printf "%v" (eq . "EnumValue")}})
t.inheritedMeta.init(nb, parent, i, t.Name, {{printf "%v" (eq . "EnumValue")}})
}
p.typs = ts
})

View File

@ -45,6 +45,11 @@ type Descriptor interface {
// Support for this functionality is optional and may return (nil, false).
Parent() (Descriptor, bool)
// Index returns the the index of this descriptor within its parent.
// It returns 0 if the descriptor does not have a parent or if the parent
// is unknown.
Index() int
// Syntax is the protobuf syntax.
Syntax() Syntax // e.g., Proto2 or Proto3

View File

@ -27,6 +27,7 @@ var (
type placeholderName pref.FullName
func (t placeholderName) Parent() (pref.Descriptor, bool) { return nil, false }
func (t placeholderName) Index() int { return 0 }
func (t placeholderName) Syntax() pref.Syntax { return 0 }
func (t placeholderName) Name() pref.Name { return pref.FullName(t).Name() }
func (t placeholderName) FullName() pref.FullName { return pref.FullName(t) }

View File

@ -33,7 +33,7 @@ func (p *messagesMeta) lazyInit(parent protoreflect.Descriptor, ts []Message) *m
panic("already initialized")
}
t.messageMeta = &metas[i]
t.inheritedMeta.init(nb, parent, t.Name, false)
t.inheritedMeta.init(nb, parent, i, t.Name, false)
}
p.typs = ts
})
@ -83,7 +83,7 @@ func (p *fieldsMeta) lazyInit(parent protoreflect.Descriptor, ts []Field) *field
panic("already initialized")
}
t.fieldMeta = &metas[i]
t.inheritedMeta.init(nb, parent, t.Name, false)
t.inheritedMeta.init(nb, parent, i, t.Name, false)
}
p.typs = ts
})
@ -166,7 +166,7 @@ func (p *oneofsMeta) lazyInit(parent protoreflect.Descriptor, ts []Oneof) *oneof
panic("already initialized")
}
t.oneofMeta = &metas[i]
t.inheritedMeta.init(nb, parent, t.Name, false)
t.inheritedMeta.init(nb, parent, i, t.Name, false)
}
p.typs = ts
})
@ -212,7 +212,7 @@ func (p *extensionsMeta) lazyInit(parent protoreflect.Descriptor, ts []Extension
panic("already initialized")
}
t.extensionMeta = &metas[i]
t.inheritedMeta.init(nb, parent, t.Name, false)
t.inheritedMeta.init(nb, parent, i, t.Name, false)
}
p.typs = ts
})
@ -258,7 +258,7 @@ func (p *enumsMeta) lazyInit(parent protoreflect.Descriptor, ts []Enum) *enums {
panic("already initialized")
}
t.enumMeta = &metas[i]
t.inheritedMeta.init(nb, parent, t.Name, false)
t.inheritedMeta.init(nb, parent, i, t.Name, false)
}
p.typs = ts
})
@ -306,7 +306,7 @@ func (p *enumValuesMeta) lazyInit(parent protoreflect.Descriptor, ts []EnumValue
panic("already initialized")
}
t.enumValueMeta = &metas[i]
t.inheritedMeta.init(nb, parent, t.Name, true)
t.inheritedMeta.init(nb, parent, i, t.Name, true)
}
p.typs = ts
})
@ -370,7 +370,7 @@ func (p *servicesMeta) lazyInit(parent protoreflect.Descriptor, ts []Service) *s
panic("already initialized")
}
t.serviceMeta = &metas[i]
t.inheritedMeta.init(nb, parent, t.Name, false)
t.inheritedMeta.init(nb, parent, i, t.Name, false)
}
p.typs = ts
})
@ -416,7 +416,7 @@ func (p *methodsMeta) lazyInit(parent protoreflect.Descriptor, ts []Method) *met
panic("already initialized")
}
t.methodMeta = &metas[i]
t.inheritedMeta.init(nb, parent, t.Name, false)
t.inheritedMeta.init(nb, parent, i, t.Name, false)
}
p.typs = ts
})

View File

@ -17,6 +17,7 @@ import (
// inheritedMeta is information inherited from the parent.
type inheritedMeta struct {
parent pref.Descriptor
index int
syntax pref.Syntax
fullName pref.FullName
@ -24,7 +25,7 @@ type inheritedMeta struct {
opts descriptorOptionsMeta
}
func (m *inheritedMeta) init(nb *nameBuilder, parent pref.Descriptor, name pref.Name, child bool) {
func (m *inheritedMeta) init(nb *nameBuilder, parent pref.Descriptor, index int, name pref.Name, child bool) {
// Most descriptors are namespaced as a child of their parent.
// However, EnumValues are the exception in that they are namespaced
// as a sibling of the parent Enum type.
@ -34,6 +35,7 @@ func (m *inheritedMeta) init(nb *nameBuilder, parent pref.Descriptor, name pref.
}
m.parent = parent
m.index = index
m.syntax = parent.Syntax()
m.fullName = nb.Append(prefix, name)
}
@ -58,6 +60,7 @@ func newFile(f *File) fileDesc {
return fileDesc{f}
}
func (t fileDesc) Parent() (pref.Descriptor, bool) { return nil, false }
func (t fileDesc) Index() int { return 0 }
func (t fileDesc) Syntax() pref.Syntax { return t.f.Syntax }
func (t fileDesc) Name() pref.Name { return t.f.Package.Name() }
func (t fileDesc) FullName() pref.FullName { return t.f.Package }
@ -164,6 +167,7 @@ type messageMeta struct {
type messageDesc struct{ m *Message }
func (t messageDesc) Parent() (pref.Descriptor, bool) { return t.m.parent, true }
func (t messageDesc) Index() int { return t.m.index }
func (t messageDesc) Syntax() pref.Syntax { return t.m.syntax }
func (t messageDesc) Name() pref.Name { return t.m.Name }
func (t messageDesc) FullName() pref.FullName { return t.m.fullName }
@ -194,6 +198,7 @@ type fieldMeta struct {
type fieldDesc struct{ f *Field }
func (t fieldDesc) Parent() (pref.Descriptor, bool) { return t.f.parent, true }
func (t fieldDesc) Index() int { return t.f.index }
func (t fieldDesc) Syntax() pref.Syntax { return t.f.syntax }
func (t fieldDesc) Name() pref.Name { return t.f.Name }
func (t fieldDesc) FullName() pref.FullName { return t.f.fullName }
@ -278,6 +283,7 @@ type oneofMeta struct {
type oneofDesc struct{ o *Oneof }
func (t oneofDesc) Parent() (pref.Descriptor, bool) { return t.o.parent, true }
func (t oneofDesc) Index() int { return t.o.index }
func (t oneofDesc) Syntax() pref.Syntax { return t.o.syntax }
func (t oneofDesc) Name() pref.Name { return t.o.Name }
func (t oneofDesc) FullName() pref.FullName { return t.o.fullName }
@ -301,6 +307,7 @@ type extensionDesc struct{ x *Extension }
func (t extensionDesc) Parent() (pref.Descriptor, bool) { return t.x.parent, true }
func (t extensionDesc) Syntax() pref.Syntax { return t.x.syntax }
func (t extensionDesc) Index() int { return t.x.index }
func (t extensionDesc) Name() pref.Name { return t.x.Name }
func (t extensionDesc) FullName() pref.FullName { return t.x.fullName }
func (t extensionDesc) IsPlaceholder() bool { return false }
@ -334,6 +341,7 @@ type enumMeta struct {
type enumDesc struct{ e *Enum }
func (t enumDesc) Parent() (pref.Descriptor, bool) { return t.e.parent, true }
func (t enumDesc) Index() int { return t.e.index }
func (t enumDesc) Syntax() pref.Syntax { return t.e.syntax }
func (t enumDesc) Name() pref.Name { return t.e.Name }
func (t enumDesc) FullName() pref.FullName { return t.e.fullName }
@ -351,6 +359,7 @@ type enumValueMeta struct {
type enumValueDesc struct{ v *EnumValue }
func (t enumValueDesc) Parent() (pref.Descriptor, bool) { return t.v.parent, true }
func (t enumValueDesc) Index() int { return t.v.index }
func (t enumValueDesc) Syntax() pref.Syntax { return t.v.syntax }
func (t enumValueDesc) Name() pref.Name { return t.v.Name }
func (t enumValueDesc) FullName() pref.FullName { return t.v.fullName }
@ -370,6 +379,7 @@ type serviceMeta struct {
type serviceDesc struct{ s *Service }
func (t serviceDesc) Parent() (pref.Descriptor, bool) { return t.s.parent, true }
func (t serviceDesc) Index() int { return t.s.index }
func (t serviceDesc) Syntax() pref.Syntax { return t.s.syntax }
func (t serviceDesc) Name() pref.Name { return t.s.Name }
func (t serviceDesc) FullName() pref.FullName { return t.s.fullName }
@ -390,6 +400,7 @@ type methodMeta struct {
type methodDesc struct{ m *Method }
func (t methodDesc) Parent() (pref.Descriptor, bool) { return t.m.parent, true }
func (t methodDesc) Index() int { return t.m.index }
func (t methodDesc) Syntax() pref.Syntax { return t.m.syntax }
func (t methodDesc) Name() pref.Name { return t.m.Name }
func (t methodDesc) FullName() pref.FullName { return t.m.fullName }

View File

@ -14,6 +14,7 @@ import (
type standaloneMessage struct{ m *StandaloneMessage }
func (t standaloneMessage) Parent() (pref.Descriptor, bool) { return nil, false }
func (t standaloneMessage) Index() int { return 0 }
func (t standaloneMessage) Syntax() pref.Syntax { return t.m.Syntax }
func (t standaloneMessage) Name() pref.Name { return t.m.FullName.Name() }
func (t standaloneMessage) FullName() pref.FullName { return t.m.FullName }
@ -35,6 +36,7 @@ func (t standaloneMessage) ProtoInternal(pragma.DoNotImplement) {}
type standaloneEnum struct{ e *StandaloneEnum }
func (t standaloneEnum) Parent() (pref.Descriptor, bool) { return nil, false }
func (t standaloneEnum) Index() int { return 0 }
func (t standaloneEnum) Syntax() pref.Syntax { return t.e.Syntax }
func (t standaloneEnum) Name() pref.Name { return t.e.FullName.Name() }
func (t standaloneEnum) FullName() pref.FullName { return t.e.FullName }
@ -49,6 +51,7 @@ func (t standaloneEnum) ProtoInternal(pragma.DoNotImplement) {}
type standaloneExtension struct{ x *StandaloneExtension }
func (t standaloneExtension) Parent() (pref.Descriptor, bool) { return nil, false }
func (t standaloneExtension) Index() int { return 0 }
func (t standaloneExtension) Syntax() pref.Syntax { return t.x.Syntax }
func (t standaloneExtension) Name() pref.Name { return t.x.FullName.Name() }
func (t standaloneExtension) FullName() pref.FullName { return t.x.FullName }

View File

@ -336,6 +336,7 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
type M = map[string]interface{}
want := M{
"Parent": nil,
"Index": 0,
"Syntax": pref.Proto2,
"Name": pref.Name("test"),
"FullName": pref.FullName("test"),
@ -346,6 +347,7 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
"Len": 3,
"Get:0": M{
"Parent": M{"FullName": pref.FullName("test")},
"Index": 0,
"Syntax": pref.Proto2,
"Name": pref.Name("A"),
"FullName": pref.FullName("test.A"),
@ -355,6 +357,7 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
"Len": 2,
"ByNumber:1": M{
"Parent": M{"FullName": pref.FullName("test.A")},
"Index": 0,
"Name": pref.Name("key"),
"FullName": pref.FullName("test.A.key"),
"Number": pref.FieldNumber(1),
@ -372,6 +375,7 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
},
"ByNumber:2": M{
"Parent": M{"FullName": pref.FullName("test.A")},
"Index": 1,
"Name": pref.Name("value"),
"FullName": pref.FullName("test.A.value"),
"Number": pref.FieldNumber(2),
@ -397,12 +401,14 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
"Extensions": M{"Len": 0},
},
"ByName:B": M{
"Name": pref.Name("B"),
"Name": pref.Name("B"),
"Index": 1,
"Fields": M{
"Len": 6,
"ByJSONName:field_one": nil,
"ByJSONName:fieldOne": M{
"Name": pref.Name("field_one"),
"Index": 0,
"JSONName": "fieldOne",
"Default": "hello",
"OneofType": M{"Name": pref.Name("O1"), "IsPlaceholder": false},
@ -410,6 +416,7 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
"ByJSONName:fieldTwo": nil,
"ByJSONName:Field2": M{
"Name": pref.Name("field_two"),
"Index": 1,
"JSONName": "Field2",
"Default": pref.EnumNumber(1),
"OneofType": M{"Name": pref.Name("O2"), "IsPlaceholder": false},
@ -444,6 +451,7 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
"ByName:O0": nil,
"ByName:O1": M{
"FullName": pref.FullName("test.B.O1"),
"Index": 0,
"Fields": M{
"Len": 1,
"Get:0": M{"FullName": pref.FullName("test.B.field_one")},
@ -451,6 +459,7 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
},
"Get:1": M{
"FullName": pref.FullName("test.B.O2"),
"Index": 1,
"Fields": M{
"Len": 2,
"ByName:field_two": M{"Name": pref.Name("field_two")},
@ -475,7 +484,8 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
},
},
"Get:2": M{
"Name": pref.Name("C"),
"Name": pref.Name("C"),
"Index": 2,
"Messages": M{
"Len": 1,
"Get:0": M{"FullName": pref.FullName("test.C.A")},