Explorar el Código

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>
Damien Neil hace 7 años
padre
commit
3de06c0868

+ 1 - 1
internal/cmd/generate-types/main.go

@@ -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
 		})

+ 5 - 0
reflect/protoreflect/type.go

@@ -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
 

+ 1 - 0
reflect/prototype/placeholder_type.go

@@ -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) }

+ 8 - 8
reflect/prototype/protofile_list_gen.go

@@ -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
 	})

+ 12 - 1
reflect/prototype/protofile_type.go

@@ -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 }

+ 3 - 0
reflect/prototype/standalone_type.go

@@ -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 }

+ 12 - 2
reflect/prototype/type_test.go

@@ -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")},