mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-03-09 13:13:32 +00:00
reflect/protoreflect: add Descriptor.Options method
Add a method to fetch descriptor options. Since options are proto messages (e.g., google.protobuf.FieldOptions), and proto message packages depend on the protoreflect package, returning the actual option type would cause a dependency cycle. Instead, we return an interface value which can be type asserted to the appropriate concrete type. Add options support to the prototype package. Some of the prototype constructors included fields (such as Field.IsPacked) which represent information from the options (such as google.protobuf.FieldOptions.packed). To avoid confusion about the canonical source of information, drop these fields in favor of the options. Drop the unimplemented Descriptor.DescriptorOptionsProto. Change-Id: I66579b6a7d10d99eb6977402a247306a78913e74 Reviewed-on: https://go-review.googlesource.com/c/144277 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
This commit is contained in:
parent
90fe996bd1
commit
204f1c0ad8
@ -10,6 +10,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/golang/protobuf/v2/protogen"
|
||||
)
|
||||
|
||||
@ -56,7 +57,7 @@ func genService(gen *protogen.Plugin, file *protogen.File, g *protogen.Generated
|
||||
g.P("// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.")
|
||||
|
||||
// Client interface.
|
||||
if serviceOptions(gen, service).GetDeprecated() {
|
||||
if service.Desc.Options().(*descpb.ServiceOptions).GetDeprecated() {
|
||||
g.P("//")
|
||||
g.P(deprecationComment)
|
||||
}
|
||||
@ -77,7 +78,7 @@ func genService(gen *protogen.Plugin, file *protogen.File, g *protogen.Generated
|
||||
g.P()
|
||||
|
||||
// NewClient factory.
|
||||
if serviceOptions(gen, service).GetDeprecated() {
|
||||
if service.Desc.Options().(*descpb.ServiceOptions).GetDeprecated() {
|
||||
g.P(deprecationComment)
|
||||
}
|
||||
g.P("func New", clientName, " (cc *", ident("grpc.ClientConn"), ") ", clientName, " {")
|
||||
@ -102,7 +103,7 @@ func genService(gen *protogen.Plugin, file *protogen.File, g *protogen.Generated
|
||||
// Server interface.
|
||||
serverType := service.GoName + "Server"
|
||||
g.P("// ", serverType, " is the server API for ", service.GoName, " service.")
|
||||
if serviceOptions(gen, service).GetDeprecated() {
|
||||
if service.Desc.Options().(*descpb.ServiceOptions).GetDeprecated() {
|
||||
g.P("//")
|
||||
g.P(deprecationComment)
|
||||
}
|
||||
@ -117,7 +118,7 @@ func genService(gen *protogen.Plugin, file *protogen.File, g *protogen.Generated
|
||||
g.P()
|
||||
|
||||
// Server registration.
|
||||
if serviceOptions(gen, service).GetDeprecated() {
|
||||
if service.Desc.Options().(*descpb.ServiceOptions).GetDeprecated() {
|
||||
g.P(deprecationComment)
|
||||
}
|
||||
serviceDescVar := "_" + service.GoName + "_serviceDesc"
|
||||
@ -189,7 +190,7 @@ func genClientMethod(gen *protogen.Plugin, file *protogen.File, g *protogen.Gene
|
||||
service := method.ParentService
|
||||
sname := fmt.Sprintf("/%s/%s", service.Desc.FullName(), method.Desc.Name())
|
||||
|
||||
if methodOptions(gen, method).GetDeprecated() {
|
||||
if method.Desc.Options().(*descpb.MethodOptions).GetDeprecated() {
|
||||
g.P(deprecationComment)
|
||||
}
|
||||
g.P("func (c *", unexport(service.GoName), "Client) ", clientSignature(g, method), "{")
|
||||
|
@ -1,116 +0,0 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file contains functions for fetching the options for a protoreflect descriptor.
|
||||
//
|
||||
// TODO: Replace this with the appropriate protoreflect API, once it exists.
|
||||
|
||||
package internal_gengogrpc
|
||||
|
||||
import (
|
||||
"github.com/golang/protobuf/proto"
|
||||
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/golang/protobuf/v2/protogen"
|
||||
"github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
)
|
||||
|
||||
// serviceOptions returns the options for a service.
|
||||
func serviceOptions(gen *protogen.Plugin, service *protogen.Service) *descpb.ServiceOptions {
|
||||
d := getDescriptorProto(gen, service.Desc, service.Location.Path)
|
||||
if d == nil {
|
||||
return nil
|
||||
}
|
||||
return d.(*descpb.ServiceDescriptorProto).GetOptions()
|
||||
}
|
||||
|
||||
// methodOptions returns the options for a method.
|
||||
func methodOptions(gen *protogen.Plugin, method *protogen.Method) *descpb.MethodOptions {
|
||||
d := getDescriptorProto(gen, method.Desc, method.Location.Path)
|
||||
if d == nil {
|
||||
return nil
|
||||
}
|
||||
return d.(*descpb.MethodDescriptorProto).GetOptions()
|
||||
}
|
||||
|
||||
func getDescriptorProto(gen *protogen.Plugin, desc protoreflect.Descriptor, path []int32) proto.Message {
|
||||
var p proto.Message
|
||||
// Look up the FileDescriptorProto.
|
||||
for {
|
||||
if fdesc, ok := desc.(protoreflect.FileDescriptor); ok {
|
||||
file, ok := gen.FileByName(fdesc.Path())
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
p = file.Proto
|
||||
break
|
||||
}
|
||||
var ok bool
|
||||
desc, ok = desc.Parent()
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
const (
|
||||
// field numbers in FileDescriptorProto
|
||||
filePackageField = 2 // package
|
||||
fileMessageField = 4 // message_type
|
||||
fileEnumField = 5 // enum_type
|
||||
fileServiceField = 6 // service
|
||||
fileExtensionField = 7 // extension
|
||||
// field numbers in DescriptorProto
|
||||
messageFieldField = 2 // field
|
||||
messageMessageField = 3 // nested_type
|
||||
messageEnumField = 4 // enum_type
|
||||
messageExtensionField = 6 // extension
|
||||
messageOneofField = 8 // oneof_decl
|
||||
// field numbers in EnumDescriptorProto
|
||||
enumValueField = 2 // value
|
||||
// field numbers in ServiceDescriptorProto
|
||||
serviceMethodField = 2 // method
|
||||
)
|
||||
for len(path) > 1 {
|
||||
switch d := p.(type) {
|
||||
case *descpb.FileDescriptorProto:
|
||||
switch path[0] {
|
||||
case fileMessageField:
|
||||
p = d.MessageType[path[1]]
|
||||
case fileEnumField:
|
||||
p = d.EnumType[path[1]]
|
||||
case fileServiceField:
|
||||
p = d.Service[path[1]]
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
case *descpb.DescriptorProto:
|
||||
switch path[0] {
|
||||
case messageFieldField:
|
||||
p = d.Field[path[1]]
|
||||
case messageMessageField:
|
||||
p = d.NestedType[path[1]]
|
||||
case messageEnumField:
|
||||
p = d.EnumType[path[1]]
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
case *descpb.EnumDescriptorProto:
|
||||
switch path[0] {
|
||||
case enumValueField:
|
||||
p = d.Value[path[1]]
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
case *descpb.ServiceDescriptorProto:
|
||||
switch path[0] {
|
||||
case serviceMethodField:
|
||||
p = d.Method[path[1]]
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
path = path[2:]
|
||||
}
|
||||
return p
|
||||
}
|
@ -237,13 +237,13 @@ func genEnum(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, enum
|
||||
g.PrintLeadingComments(enum.Location)
|
||||
g.Annotate(enum.GoIdent.GoName, enum.Location)
|
||||
g.P("type ", enum.GoIdent, " int32",
|
||||
deprecationComment(enumOptions(gen, enum).GetDeprecated()))
|
||||
deprecationComment(enum.Desc.Options().(*descpb.EnumOptions).GetDeprecated()))
|
||||
g.P("const (")
|
||||
for _, value := range enum.Values {
|
||||
g.PrintLeadingComments(value.Location)
|
||||
g.Annotate(value.GoIdent.GoName, value.Location)
|
||||
g.P(value.GoIdent, " ", enum.GoIdent, " = ", value.Desc.Number(),
|
||||
deprecationComment(enumValueOptions(gen, value).GetDeprecated()))
|
||||
deprecationComment(value.Desc.Options().(*descpb.EnumValueOptions).GetDeprecated()))
|
||||
}
|
||||
g.P(")")
|
||||
g.P()
|
||||
@ -333,7 +333,7 @@ func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, me
|
||||
}
|
||||
|
||||
hasComment := g.PrintLeadingComments(message.Location)
|
||||
if messageOptions(gen, message).GetDeprecated() {
|
||||
if message.Desc.Options().(*descpb.MessageOptions).GetDeprecated() {
|
||||
if hasComment {
|
||||
g.P("//")
|
||||
}
|
||||
@ -371,13 +371,13 @@ func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, me
|
||||
}
|
||||
g.Annotate(message.GoIdent.GoName+"."+field.GoName, field.Location)
|
||||
g.P(field.GoName, " ", goType, " `", strings.Join(tags, " "), "`",
|
||||
deprecationComment(fieldOptions(gen, field).GetDeprecated()))
|
||||
deprecationComment(field.Desc.Options().(*descpb.FieldOptions).GetDeprecated()))
|
||||
}
|
||||
g.P("XXX_NoUnkeyedLiteral struct{} `json:\"-\"`")
|
||||
|
||||
if message.Desc.ExtensionRanges().Len() > 0 {
|
||||
var tags []string
|
||||
if messageOptions(gen, message).GetMessageSetWireFormat() {
|
||||
if message.Desc.Options().(*descpb.MessageOptions).GetMessageSetWireFormat() {
|
||||
tags = append(tags, `protobuf_messageset:"1"`)
|
||||
}
|
||||
tags = append(tags, `json:"-"`)
|
||||
@ -413,7 +413,7 @@ func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, me
|
||||
|
||||
// ExtensionRangeArray
|
||||
if extranges := message.Desc.ExtensionRanges(); extranges.Len() > 0 {
|
||||
if messageOptions(gen, message).GetMessageSetWireFormat() {
|
||||
if message.Desc.Options().(*descpb.MessageOptions).GetMessageSetWireFormat() {
|
||||
g.P("func (m *", message.GoIdent, ") MarshalJSON() ([]byte, error) {")
|
||||
g.P("return ", protogen.GoIdent{
|
||||
GoImportPath: protoPackage,
|
||||
@ -545,7 +545,7 @@ func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, me
|
||||
}
|
||||
goType, pointer := fieldGoType(g, field)
|
||||
defaultValue := fieldDefaultValue(g, message, field)
|
||||
if fieldOptions(gen, field).GetDeprecated() {
|
||||
if field.Desc.Options().(*descpb.FieldOptions).GetDeprecated() {
|
||||
g.P(deprecationComment(true))
|
||||
}
|
||||
g.Annotate(message.GoIdent.GoName+".Get"+field.GoName, field.Location)
|
||||
@ -836,7 +836,7 @@ func genExtension(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo,
|
||||
|
||||
func isExtensionMessageSetElement(gen *protogen.Plugin, extension *protogen.Extension) bool {
|
||||
return extension.ParentMessage != nil &&
|
||||
messageOptions(gen, extension.ExtendedType).GetMessageSetWireFormat() &&
|
||||
extension.ExtendedType.Desc.Options().(*descpb.MessageOptions).GetMessageSetWireFormat() &&
|
||||
extension.Desc.Name() == "message_set_extension"
|
||||
}
|
||||
|
||||
|
@ -1,122 +0,0 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file contains functions for fetching the options for a protoreflect descriptor.
|
||||
//
|
||||
// TODO: Replace this with the appropriate protoreflect API, once it exists.
|
||||
|
||||
package internal_gengo
|
||||
|
||||
import (
|
||||
"github.com/golang/protobuf/proto"
|
||||
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/golang/protobuf/v2/protogen"
|
||||
"github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
)
|
||||
|
||||
// messageOptions returns the MessageOptions for a message.
|
||||
func messageOptions(gen *protogen.Plugin, message *protogen.Message) *descpb.MessageOptions {
|
||||
d := getDescriptorProto(gen, message.Desc, message.Location.Path)
|
||||
if d == nil {
|
||||
return nil
|
||||
}
|
||||
return d.(*descpb.DescriptorProto).GetOptions()
|
||||
}
|
||||
|
||||
// fieldOptions returns the FieldOptions for a message.
|
||||
func fieldOptions(gen *protogen.Plugin, field *protogen.Field) *descpb.FieldOptions {
|
||||
d := getDescriptorProto(gen, field.Desc, field.Location.Path)
|
||||
if d == nil {
|
||||
return nil
|
||||
}
|
||||
return d.(*descpb.FieldDescriptorProto).GetOptions()
|
||||
}
|
||||
|
||||
// enumOptions returns the EnumOptions for an enum
|
||||
func enumOptions(gen *protogen.Plugin, enum *protogen.Enum) *descpb.EnumOptions {
|
||||
d := getDescriptorProto(gen, enum.Desc, enum.Location.Path)
|
||||
if d == nil {
|
||||
return nil
|
||||
}
|
||||
return d.(*descpb.EnumDescriptorProto).GetOptions()
|
||||
}
|
||||
|
||||
// enumValueOptions returns the EnumValueOptions for an enum value
|
||||
func enumValueOptions(gen *protogen.Plugin, value *protogen.EnumValue) *descpb.EnumValueOptions {
|
||||
d := getDescriptorProto(gen, value.Desc, value.Location.Path)
|
||||
if d == nil {
|
||||
return nil
|
||||
}
|
||||
return d.(*descpb.EnumValueDescriptorProto).GetOptions()
|
||||
}
|
||||
|
||||
func getDescriptorProto(gen *protogen.Plugin, desc protoreflect.Descriptor, path []int32) proto.Message {
|
||||
var p proto.Message
|
||||
// Look up the FileDescriptorProto.
|
||||
for {
|
||||
if fdesc, ok := desc.(protoreflect.FileDescriptor); ok {
|
||||
file, ok := gen.FileByName(fdesc.Path())
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
p = file.Proto
|
||||
break
|
||||
}
|
||||
var ok bool
|
||||
desc, ok = desc.Parent()
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
const (
|
||||
// field numbers in FileDescriptorProto
|
||||
filePackageField = 2 // package
|
||||
fileMessageField = 4 // message_type
|
||||
fileEnumField = 5 // enum_type
|
||||
fileExtensionField = 7 // extension
|
||||
// field numbers in DescriptorProto
|
||||
messageFieldField = 2 // field
|
||||
messageMessageField = 3 // nested_type
|
||||
messageEnumField = 4 // enum_type
|
||||
messageExtensionField = 6 // extension
|
||||
messageOneofField = 8 // oneof_decl
|
||||
// field numbers in EnumDescriptorProto
|
||||
enumValueField = 2 // value
|
||||
)
|
||||
for len(path) > 1 {
|
||||
switch d := p.(type) {
|
||||
case *descpb.FileDescriptorProto:
|
||||
switch path[0] {
|
||||
case fileMessageField:
|
||||
p = d.MessageType[path[1]]
|
||||
case fileEnumField:
|
||||
p = d.EnumType[path[1]]
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
case *descpb.DescriptorProto:
|
||||
switch path[0] {
|
||||
case messageFieldField:
|
||||
p = d.Field[path[1]]
|
||||
case messageMessageField:
|
||||
p = d.NestedType[path[1]]
|
||||
case messageEnumField:
|
||||
p = d.EnumType[path[1]]
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
case *descpb.EnumDescriptorProto:
|
||||
switch path[0] {
|
||||
case enumValueField:
|
||||
p = d.Value[path[1]]
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
path = path[2:]
|
||||
}
|
||||
return p
|
||||
}
|
@ -17,6 +17,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
protoV1 "github.com/golang/protobuf/proto"
|
||||
descriptorV1 "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/golang/protobuf/v2/internal/encoding/pack"
|
||||
"github.com/golang/protobuf/v2/internal/encoding/wire"
|
||||
"github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
@ -227,7 +229,7 @@ func (fs fields) messageDescriptor(name protoreflect.FullName) prototype.Message
|
||||
protoreflect.Sfixed32Kind, protoreflect.Fixed32Kind, protoreflect.FloatKind,
|
||||
protoreflect.Sfixed64Kind, protoreflect.Fixed64Kind, protoreflect.DoubleKind:
|
||||
f.Cardinality = protoreflect.Repeated
|
||||
f.IsPacked = true
|
||||
f.Options = &descriptorV1.FieldOptions{Packed: protoV1.Bool(true)}
|
||||
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||
s := name.Append(protoreflect.Name(fmt.Sprintf("M%d", n)))
|
||||
f.MessageType = prototype.PlaceholderMessage(s)
|
||||
|
@ -67,7 +67,7 @@ func TestFields(t *testing.T) {
|
||||
Name: "M20",
|
||||
Fields: []ptype.Field{
|
||||
{Name: "f30", Number: 30, Cardinality: pref.Optional, Kind: pref.MessageKind, MessageType: ptype.PlaceholderMessage("M.M10.M20.M30")},
|
||||
{Name: "f31", Number: 31, Cardinality: pref.Repeated, IsPacked: true, Kind: pref.Int32Kind},
|
||||
{Name: "f31", Number: 31, Cardinality: pref.Repeated, Kind: pref.Int32Kind},
|
||||
},
|
||||
Messages: []ptype.Message{{
|
||||
Name: "M30",
|
||||
@ -87,6 +87,7 @@ func TestFields(t *testing.T) {
|
||||
return x.FullName() == y.FullName()
|
||||
}),
|
||||
cmpopts.IgnoreFields(ptype.Field{}, "Default"),
|
||||
cmpopts.IgnoreFields(ptype.Field{}, "Options"),
|
||||
cmpopts.IgnoreUnexported(ptype.Message{}, ptype.Field{}),
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
descriptorV1 "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
ptype "github.com/golang/protobuf/v2/reflect/prototype"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
@ -21,16 +22,16 @@ var msgDesc = func() pref.MessageDescriptor {
|
||||
Syntax: pref.Proto2,
|
||||
FullName: "Message",
|
||||
Fields: []ptype.Field{
|
||||
{Name: "F1", Number: 1, Cardinality: pref.Repeated, Kind: pref.BoolKind, IsPacked: true},
|
||||
{Name: "F2", Number: 2, Cardinality: pref.Repeated, Kind: pref.Int64Kind, IsPacked: true},
|
||||
{Name: "F3", Number: 3, Cardinality: pref.Repeated, Kind: pref.Sint64Kind, IsPacked: true},
|
||||
{Name: "F4", Number: 4, Cardinality: pref.Repeated, Kind: pref.Uint64Kind, IsPacked: true},
|
||||
{Name: "F5", Number: 5, Cardinality: pref.Repeated, Kind: pref.Fixed32Kind, IsPacked: true},
|
||||
{Name: "F6", Number: 6, Cardinality: pref.Repeated, Kind: pref.Sfixed32Kind, IsPacked: true},
|
||||
{Name: "F7", Number: 7, Cardinality: pref.Repeated, Kind: pref.FloatKind, IsPacked: true},
|
||||
{Name: "F8", Number: 8, Cardinality: pref.Repeated, Kind: pref.Fixed64Kind, IsPacked: true},
|
||||
{Name: "F9", Number: 9, Cardinality: pref.Repeated, Kind: pref.Sfixed64Kind, IsPacked: true},
|
||||
{Name: "F10", Number: 10, Cardinality: pref.Repeated, Kind: pref.DoubleKind, IsPacked: true},
|
||||
{Name: "F1", Number: 1, Cardinality: pref.Repeated, Kind: pref.BoolKind, Options: packedOpt(true)},
|
||||
{Name: "F2", Number: 2, Cardinality: pref.Repeated, Kind: pref.Int64Kind, Options: packedOpt(true)},
|
||||
{Name: "F3", Number: 3, Cardinality: pref.Repeated, Kind: pref.Sint64Kind, Options: packedOpt(true)},
|
||||
{Name: "F4", Number: 4, Cardinality: pref.Repeated, Kind: pref.Uint64Kind, Options: packedOpt(true)},
|
||||
{Name: "F5", Number: 5, Cardinality: pref.Repeated, Kind: pref.Fixed32Kind, Options: packedOpt(true)},
|
||||
{Name: "F6", Number: 6, Cardinality: pref.Repeated, Kind: pref.Sfixed32Kind, Options: packedOpt(true)},
|
||||
{Name: "F7", Number: 7, Cardinality: pref.Repeated, Kind: pref.FloatKind, Options: packedOpt(true)},
|
||||
{Name: "F8", Number: 8, Cardinality: pref.Repeated, Kind: pref.Fixed64Kind, Options: packedOpt(true)},
|
||||
{Name: "F9", Number: 9, Cardinality: pref.Repeated, Kind: pref.Sfixed64Kind, Options: packedOpt(true)},
|
||||
{Name: "F10", Number: 10, Cardinality: pref.Repeated, Kind: pref.DoubleKind, Options: packedOpt(true)},
|
||||
{Name: "F11", Number: 11, Cardinality: pref.Optional, Kind: pref.StringKind},
|
||||
{Name: "F12", Number: 12, Cardinality: pref.Optional, Kind: pref.BytesKind},
|
||||
{Name: "F13", Number: 13, Cardinality: pref.Optional, Kind: pref.MessageKind, MessageType: ptype.PlaceholderMessage("Message")},
|
||||
@ -42,6 +43,10 @@ var msgDesc = func() pref.MessageDescriptor {
|
||||
return mtyp
|
||||
}()
|
||||
|
||||
func packedOpt(b bool) *descriptorV1.FieldOptions {
|
||||
return &descriptorV1.FieldOptions{Packed: &b}
|
||||
}
|
||||
|
||||
// dhex decodes a hex-string and returns the bytes and panics if s is invalid.
|
||||
func dhex(s string) []byte {
|
||||
b, err := hex.DecodeString(s)
|
||||
|
@ -13,6 +13,8 @@ import (
|
||||
"sync"
|
||||
"unicode"
|
||||
|
||||
protoV1 "github.com/golang/protobuf/proto"
|
||||
descriptorV1 "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/golang/protobuf/v2/internal/encoding/text"
|
||||
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
ptype "github.com/golang/protobuf/v2/reflect/prototype"
|
||||
@ -179,6 +181,9 @@ func (ms *messageDescSet) parseField(tag, tagKey, tagVal string, t reflect.Type,
|
||||
t = t.Elem()
|
||||
}
|
||||
|
||||
f.Options = &descriptorV1.FieldOptions{
|
||||
Packed: protoV1.Bool(false),
|
||||
}
|
||||
for len(tag) > 0 {
|
||||
i := strings.IndexByte(tag, ',')
|
||||
if i < 0 {
|
||||
@ -251,9 +256,9 @@ func (ms *messageDescSet) parseField(tag, tagKey, tagVal string, t reflect.Type,
|
||||
case strings.HasPrefix(s, "json="):
|
||||
f.JSONName = s[len("json="):]
|
||||
case s == "packed":
|
||||
f.IsPacked = true
|
||||
*f.Options.Packed = true
|
||||
case strings.HasPrefix(s, "weak="):
|
||||
f.IsWeak = true
|
||||
f.Options.Weak = protoV1.Bool(true)
|
||||
f.MessageType = ptype.PlaceholderMessage(pref.FullName(s[len("weak="):]))
|
||||
case strings.HasPrefix(s, "def="):
|
||||
// The default tag is special in that everything afterwards is the
|
||||
@ -333,9 +338,9 @@ func (ms *messageDescSet) parseField(tag, tagKey, tagVal string, t reflect.Type,
|
||||
f.MessageType = mv.ProtoReflect().Type()
|
||||
} else if t.Kind() == reflect.Map {
|
||||
m := &ptype.StandaloneMessage{
|
||||
Syntax: parent.Syntax,
|
||||
FullName: parent.FullName.Append(mapEntryName(f.Name)),
|
||||
IsMapEntry: true,
|
||||
Syntax: parent.Syntax,
|
||||
FullName: parent.FullName.Append(mapEntryName(f.Name)),
|
||||
Options: &descriptorV1.MessageOptions{MapEntry: protoV1.Bool(true)},
|
||||
Fields: []ptype.Field{
|
||||
ms.parseField(tagKey, "", "", t.Key(), nil),
|
||||
ms.parseField(tagVal, "", "", t.Elem(), nil),
|
||||
|
@ -99,6 +99,8 @@ func TestLegacy(t *testing.T) {
|
||||
switch name {
|
||||
case "Index":
|
||||
// Ignore index since legacy descriptors have no parent.
|
||||
case "Options":
|
||||
// Ignore descriptor options since protos are not cmperable.
|
||||
case "Messages", "Enums":
|
||||
// Ignore nested message and enum declarations since
|
||||
// legacy descriptors are all created standalone.
|
||||
|
@ -14,6 +14,8 @@ import (
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
protoV1 "github.com/golang/protobuf/proto"
|
||||
descriptorV1 "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
ptype "github.com/golang/protobuf/v2/reflect/prototype"
|
||||
)
|
||||
@ -461,7 +463,7 @@ func TestMapScalars(t *testing.T) {
|
||||
{Name: "key", Number: 1, Cardinality: pref.Optional, Kind: keyKind},
|
||||
{Name: "value", Number: 2, Cardinality: pref.Optional, Kind: valKind},
|
||||
},
|
||||
IsMapEntry: true,
|
||||
Options: &descriptorV1.MessageOptions{MapEntry: protoV1.Bool(true)},
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -104,57 +104,30 @@ type Descriptor interface {
|
||||
// Support for this functionality is optional and may return (nil, false).
|
||||
DescriptorProto() (Message, bool)
|
||||
|
||||
// DescriptorOptions is a helper for accessing the proto options specified
|
||||
// on any of the descriptor types. It is functionally equivalent to
|
||||
// accessing the "options" field in the descriptor and providing a set of
|
||||
// efficient lookup methods.
|
||||
// Options returns the descriptor options. The caller must not modify
|
||||
// the returned value.
|
||||
//
|
||||
// Support for this functionality is optional and may return (nil, false).
|
||||
DescriptorOptions() (DescriptorOptions, bool)
|
||||
|
||||
doNotImplement
|
||||
}
|
||||
|
||||
// DescriptorOptions is a wrapper around proto options.
|
||||
//
|
||||
// The proto message type for each descriptor type is as follows:
|
||||
// +---------------------+----------------------------------+
|
||||
// | Go type | Proto message type |
|
||||
// +---------------------+----------------------------------+
|
||||
// | FileDescriptor | google.protobuf.FileOptions |
|
||||
// | MessageDescriptor | google.protobuf.MessageOptions |
|
||||
// | FieldDescriptor | google.protobuf.FieldOptions |
|
||||
// | OneofDescriptor | google.protobuf.OneofOptions |
|
||||
// | EnumDescriptor | google.protobuf.EnumOptions |
|
||||
// | EnumValueDescriptor | google.protobuf.EnumValueOptions |
|
||||
// | ServiceDescriptor | google.protobuf.ServiceOptions |
|
||||
// | MethodDescriptor | google.protobuf.MethodOptions |
|
||||
// +---------------------+----------------------------------+
|
||||
//
|
||||
// The values returned by Get, ByName, and ByNumber are considered frozen and
|
||||
// mutating operations must not be performed on values returned by them.
|
||||
type DescriptorOptions interface {
|
||||
// Len reports the total number of option fields,
|
||||
// including both fields declared in the options proto and extensions, and
|
||||
// including fields that are declared but not set in the proto file.
|
||||
Len() int
|
||||
|
||||
// Get returns the ith field. It panics if out of bounds.
|
||||
// The FieldDescriptor is guaranteed to be non-nil, while the Value
|
||||
// may be invalid if the proto file did not specify this option.
|
||||
Get(i int) (FieldDescriptor, Value)
|
||||
|
||||
// ByName looks a field up by full name and
|
||||
// returns (nil, Value{}) if not found.
|
||||
// To avoid a dependency cycle, this function returns an interface value.
|
||||
// The proto message type returned for each descriptor type is as follows:
|
||||
// +---------------------+------------------------------------------+
|
||||
// | Go type | Proto message type |
|
||||
// +---------------------+------------------------------------------+
|
||||
// | FileDescriptor | google.protobuf.FileOptions |
|
||||
// | MessageDescriptor | google.protobuf.MessageOptions |
|
||||
// | FieldDescriptor | google.protobuf.FieldOptions |
|
||||
// | OneofDescriptor | google.protobuf.OneofOptions |
|
||||
// | EnumDescriptor | google.protobuf.EnumOptions |
|
||||
// | EnumValueDescriptor | google.protobuf.EnumValueOptions |
|
||||
// | ServiceDescriptor | google.protobuf.ServiceOptions |
|
||||
// | MethodDescriptor | google.protobuf.MethodOptions |
|
||||
// +---------------------+------------------------------------------+
|
||||
//
|
||||
// As a special-case, non-extension fields in the options type can be
|
||||
// directly accessed by the field name alone (e.g., "map_entry" may be used
|
||||
// instead of "google.protobuf.MessageOptions.map_entry").
|
||||
ByName(s FullName) (FieldDescriptor, Value)
|
||||
|
||||
// ByNumber looks a field up by the field number and
|
||||
// returns (nil, Value{}) if not found.
|
||||
ByNumber(n FieldNumber) (FieldDescriptor, Value)
|
||||
// This method will never return a nil interface value, although the
|
||||
// concrete value contained in the interface may be nil (e.g.,
|
||||
// (*descpb.FileOptions)(nil)).
|
||||
//
|
||||
// TODO: Return ProtoMessage instead of interface{}.
|
||||
Options() interface{}
|
||||
|
||||
doNotImplement
|
||||
}
|
||||
|
@ -1,29 +0,0 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package prototype
|
||||
|
||||
import (
|
||||
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
)
|
||||
|
||||
// TODO: This cannot be implemented without proto.Unmarshal.
|
||||
|
||||
type descriptorFileMeta struct{}
|
||||
|
||||
func (p *descriptorFileMeta) lazyInit(t fileDesc) (pref.Message, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
type descriptorSubMeta struct{}
|
||||
|
||||
func (p *descriptorSubMeta) lazyInit(t pref.Descriptor) (pref.Message, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
type descriptorOptionsMeta struct{}
|
||||
|
||||
func (p *descriptorOptionsMeta) lazyInit(t pref.Descriptor) (pref.DescriptorOptions, bool) {
|
||||
return nil, false
|
||||
}
|
@ -7,6 +7,7 @@ package prototype
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
descriptorV1 "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/golang/protobuf/v2/internal/pragma"
|
||||
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
)
|
||||
@ -26,21 +27,21 @@ 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) }
|
||||
func (t placeholderName) IsPlaceholder() bool { return true }
|
||||
func (t placeholderName) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t placeholderName) DescriptorOptions() (pref.DescriptorOptions, bool) { return nil, false }
|
||||
func (t placeholderName) ProtoInternal(pragma.DoNotImplement) {}
|
||||
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) }
|
||||
func (t placeholderName) IsPlaceholder() bool { return true }
|
||||
func (t placeholderName) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t placeholderName) ProtoInternal(pragma.DoNotImplement) {}
|
||||
|
||||
type placeholderFile struct {
|
||||
path string
|
||||
placeholderName
|
||||
}
|
||||
|
||||
func (t placeholderFile) Options() interface{} { return (*descriptorV1.FileOptions)(nil) }
|
||||
func (t placeholderFile) Path() string { return t.path }
|
||||
func (t placeholderFile) Package() pref.FullName { return t.FullName() }
|
||||
func (t placeholderFile) Imports() pref.FileImports { return &emptyFiles }
|
||||
@ -56,6 +57,7 @@ type placeholderMessage struct {
|
||||
placeholderName
|
||||
}
|
||||
|
||||
func (t placeholderMessage) Options() interface{} { return (*descriptorV1.MessageOptions)(nil) }
|
||||
func (t placeholderMessage) IsMapEntry() bool { return false }
|
||||
func (t placeholderMessage) Fields() pref.FieldDescriptors { return &emptyFields }
|
||||
func (t placeholderMessage) Oneofs() pref.OneofDescriptors { return &emptyOneofs }
|
||||
@ -71,6 +73,7 @@ type placeholderEnum struct {
|
||||
placeholderName
|
||||
}
|
||||
|
||||
func (t placeholderEnum) Options() interface{} { return (*descriptorV1.EnumOptions)(nil) }
|
||||
func (t placeholderEnum) Values() pref.EnumValueDescriptors { return &emptyEnumValues }
|
||||
func (t placeholderEnum) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t placeholderEnum) ProtoType(pref.EnumDescriptor) {}
|
||||
|
@ -14,6 +14,7 @@
|
||||
package prototype
|
||||
|
||||
import (
|
||||
descriptorV1 "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
)
|
||||
|
||||
@ -35,15 +36,15 @@ import (
|
||||
|
||||
// File is a constructor for protoreflect.FileDescriptor.
|
||||
type File struct {
|
||||
Syntax protoreflect.Syntax
|
||||
Path string
|
||||
Package protoreflect.FullName
|
||||
Imports []protoreflect.FileImport
|
||||
|
||||
Syntax protoreflect.Syntax
|
||||
Path string
|
||||
Package protoreflect.FullName
|
||||
Imports []protoreflect.FileImport
|
||||
Messages []Message
|
||||
Enums []Enum
|
||||
Extensions []Extension
|
||||
Services []Service
|
||||
Options *descriptorV1.FileOptions
|
||||
|
||||
*fileMeta
|
||||
}
|
||||
@ -72,14 +73,13 @@ func NewFile(t *File) (protoreflect.FileDescriptor, error) {
|
||||
// Message is a constructor for protoreflect.MessageDescriptor.
|
||||
type Message struct {
|
||||
Name protoreflect.Name
|
||||
IsMapEntry bool
|
||||
Fields []Field
|
||||
Oneofs []Oneof
|
||||
ExtensionRanges [][2]protoreflect.FieldNumber
|
||||
|
||||
Messages []Message
|
||||
Enums []Enum
|
||||
Extensions []Extension
|
||||
Messages []Message
|
||||
Enums []Enum
|
||||
Extensions []Extension
|
||||
Options *descriptorV1.MessageOptions
|
||||
|
||||
*messageMeta
|
||||
}
|
||||
@ -91,19 +91,19 @@ type Field struct {
|
||||
Cardinality protoreflect.Cardinality
|
||||
Kind protoreflect.Kind
|
||||
JSONName string
|
||||
IsPacked bool
|
||||
IsWeak bool
|
||||
Default protoreflect.Value
|
||||
OneofName protoreflect.Name
|
||||
MessageType protoreflect.MessageDescriptor
|
||||
EnumType protoreflect.EnumDescriptor
|
||||
Options *descriptorV1.FieldOptions
|
||||
|
||||
*fieldMeta
|
||||
}
|
||||
|
||||
// Oneof is a constructor for protoreflect.OneofDescriptor.
|
||||
type Oneof struct {
|
||||
Name protoreflect.Name
|
||||
Name protoreflect.Name
|
||||
Options *descriptorV1.OneofOptions
|
||||
|
||||
*oneofMeta
|
||||
}
|
||||
@ -114,27 +114,29 @@ type Extension struct {
|
||||
Number protoreflect.FieldNumber
|
||||
Cardinality protoreflect.Cardinality
|
||||
Kind protoreflect.Kind
|
||||
IsPacked bool
|
||||
Default protoreflect.Value
|
||||
MessageType protoreflect.MessageDescriptor
|
||||
EnumType protoreflect.EnumDescriptor
|
||||
ExtendedType protoreflect.MessageDescriptor
|
||||
Options *descriptorV1.FieldOptions
|
||||
|
||||
*extensionMeta
|
||||
}
|
||||
|
||||
// Enum is a constructor for protoreflect.EnumDescriptor.
|
||||
type Enum struct {
|
||||
Name protoreflect.Name
|
||||
Values []EnumValue
|
||||
Name protoreflect.Name
|
||||
Values []EnumValue
|
||||
Options *descriptorV1.EnumOptions
|
||||
|
||||
*enumMeta
|
||||
}
|
||||
|
||||
// EnumValue is a constructor for protoreflect.EnumValueDescriptor.
|
||||
type EnumValue struct {
|
||||
Name protoreflect.Name
|
||||
Number protoreflect.EnumNumber
|
||||
Name protoreflect.Name
|
||||
Number protoreflect.EnumNumber
|
||||
Options *descriptorV1.EnumValueOptions
|
||||
|
||||
*enumValueMeta
|
||||
}
|
||||
@ -143,6 +145,7 @@ type EnumValue struct {
|
||||
type Service struct {
|
||||
Name protoreflect.Name
|
||||
Methods []Method
|
||||
Options *descriptorV1.ServiceOptions
|
||||
|
||||
*serviceMeta
|
||||
}
|
||||
@ -154,6 +157,7 @@ type Method struct {
|
||||
OutputType protoreflect.MessageDescriptor
|
||||
IsStreamingClient bool
|
||||
IsStreamingServer bool
|
||||
Options *descriptorV1.MethodOptions
|
||||
|
||||
*methodMeta
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ func NewFileFromDescriptorProto(fd *descriptorV1.FileDescriptorProto, r *protore
|
||||
}
|
||||
f.Path = fd.GetName()
|
||||
f.Package = protoreflect.FullName(fd.GetPackage())
|
||||
f.Options = fd.GetOptions()
|
||||
|
||||
f.Imports = make([]protoreflect.FileImport, len(fd.GetDependency()))
|
||||
for _, i := range fd.GetPublicDependency() {
|
||||
@ -119,25 +120,15 @@ func messagesFromDescriptorProto(mds []*descriptorV1.DescriptorProto, syntax pro
|
||||
for _, md := range mds {
|
||||
var m Message
|
||||
m.Name = protoreflect.Name(md.GetName())
|
||||
m.IsMapEntry = md.GetOptions().GetMapEntry()
|
||||
m.Options = md.GetOptions()
|
||||
for _, fd := range md.GetField() {
|
||||
var f Field
|
||||
f.Name = protoreflect.Name(fd.GetName())
|
||||
f.Number = protoreflect.FieldNumber(fd.GetNumber())
|
||||
f.Cardinality = protoreflect.Cardinality(fd.GetLabel())
|
||||
f.Kind = protoreflect.Kind(fd.GetType())
|
||||
f.Options = fd.GetOptions()
|
||||
f.JSONName = fd.GetJsonName()
|
||||
if opts := fd.GetOptions(); opts != nil && opts.Packed != nil {
|
||||
f.IsPacked = *opts.Packed
|
||||
} else {
|
||||
// https://developers.google.com/protocol-buffers/docs/proto3:
|
||||
// "In proto3, repeated fields of scalar numeric types use packed
|
||||
// encoding by default."
|
||||
f.IsPacked = (syntax == protoreflect.Proto3 &&
|
||||
f.Cardinality == protoreflect.Repeated &&
|
||||
isScalarNumeric[f.Kind])
|
||||
}
|
||||
f.IsWeak = fd.GetOptions().GetWeak()
|
||||
if fd.DefaultValue != nil {
|
||||
f.Default, err = parseDefault(fd.GetDefaultValue(), f.Kind)
|
||||
if err != nil {
|
||||
@ -157,7 +148,7 @@ func messagesFromDescriptorProto(mds []*descriptorV1.DescriptorProto, syntax pro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f.IsWeak && !f.EnumType.IsPlaceholder() {
|
||||
if f.Options.GetWeak() && !f.EnumType.IsPlaceholder() {
|
||||
f.EnumType = PlaceholderEnum(f.EnumType.FullName())
|
||||
}
|
||||
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||
@ -165,16 +156,20 @@ func messagesFromDescriptorProto(mds []*descriptorV1.DescriptorProto, syntax pro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f.IsWeak && !f.MessageType.IsPlaceholder() {
|
||||
if f.Options.GetWeak() && !f.MessageType.IsPlaceholder() {
|
||||
f.MessageType = PlaceholderMessage(f.MessageType.FullName())
|
||||
}
|
||||
}
|
||||
m.Fields = append(m.Fields, f)
|
||||
}
|
||||
for _, od := range md.GetOneofDecl() {
|
||||
m.Oneofs = append(m.Oneofs, Oneof{Name: protoreflect.Name(od.GetName())})
|
||||
m.Oneofs = append(m.Oneofs, Oneof{
|
||||
Name: protoreflect.Name(od.GetName()),
|
||||
Options: od.Options,
|
||||
})
|
||||
}
|
||||
for _, xr := range md.GetExtensionRange() {
|
||||
// TODO: Extension range options.
|
||||
m.ExtensionRanges = append(m.ExtensionRanges, [2]protoreflect.FieldNumber{
|
||||
protoreflect.FieldNumber(xr.GetStart()),
|
||||
protoreflect.FieldNumber(xr.GetEnd()),
|
||||
@ -199,31 +194,16 @@ func messagesFromDescriptorProto(mds []*descriptorV1.DescriptorProto, syntax pro
|
||||
return ms, nil
|
||||
}
|
||||
|
||||
var isScalarNumeric = map[protoreflect.Kind]bool{
|
||||
protoreflect.BoolKind: true,
|
||||
protoreflect.EnumKind: true,
|
||||
protoreflect.Int32Kind: true,
|
||||
protoreflect.Sint32Kind: true,
|
||||
protoreflect.Uint32Kind: true,
|
||||
protoreflect.Int64Kind: true,
|
||||
protoreflect.Sint64Kind: true,
|
||||
protoreflect.Uint64Kind: true,
|
||||
protoreflect.Sfixed32Kind: true,
|
||||
protoreflect.Fixed32Kind: true,
|
||||
protoreflect.FloatKind: true,
|
||||
protoreflect.Sfixed64Kind: true,
|
||||
protoreflect.Fixed64Kind: true,
|
||||
protoreflect.DoubleKind: true,
|
||||
}
|
||||
|
||||
func enumsFromDescriptorProto(eds []*descriptorV1.EnumDescriptorProto, r *protoregistry.Files) (es []Enum, err error) {
|
||||
for _, ed := range eds {
|
||||
var e Enum
|
||||
e.Name = protoreflect.Name(ed.GetName())
|
||||
e.Options = ed.GetOptions()
|
||||
for _, vd := range ed.GetValue() {
|
||||
e.Values = append(e.Values, EnumValue{
|
||||
Name: protoreflect.Name(vd.GetName()),
|
||||
Number: protoreflect.EnumNumber(vd.GetNumber()),
|
||||
Name: protoreflect.Name(vd.GetName()),
|
||||
Number: protoreflect.EnumNumber(vd.GetNumber()),
|
||||
Options: vd.Options,
|
||||
})
|
||||
}
|
||||
es = append(es, e)
|
||||
@ -238,12 +218,7 @@ func extensionsFromDescriptorProto(xds []*descriptorV1.FieldDescriptorProto, r *
|
||||
x.Number = protoreflect.FieldNumber(xd.GetNumber())
|
||||
x.Cardinality = protoreflect.Cardinality(xd.GetLabel())
|
||||
x.Kind = protoreflect.Kind(xd.GetType())
|
||||
// TODO: When a proto3 file extends a proto2 message (permitted only for
|
||||
// extending descriptor options), does the extension have proto2 or proto3
|
||||
// semantics? If the latter, repeated, scalar, numeric, proto3 extension
|
||||
// fields should default to packed. If the former, perhaps the extension syntax
|
||||
// should be protoreflect.Proto2.
|
||||
x.IsPacked = xd.GetOptions().GetPacked()
|
||||
x.Options = xd.GetOptions()
|
||||
if xd.DefaultValue != nil {
|
||||
x.Default, err = parseDefault(xd.GetDefaultValue(), x.Kind)
|
||||
if err != nil {
|
||||
@ -275,9 +250,11 @@ func servicesFromDescriptorProto(sds []*descriptorV1.ServiceDescriptorProto, r *
|
||||
for _, sd := range sds {
|
||||
var s Service
|
||||
s.Name = protoreflect.Name(sd.GetName())
|
||||
s.Options = sd.GetOptions()
|
||||
for _, md := range sd.GetMethod() {
|
||||
var m Method
|
||||
m.Name = protoreflect.Name(md.GetName())
|
||||
m.Options = md.GetOptions()
|
||||
m.InputType, err = findMessageDescriptor(md.GetInputType(), r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
descriptorV1 "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/golang/protobuf/v2/internal/pragma"
|
||||
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
)
|
||||
@ -20,9 +21,6 @@ type inheritedMeta struct {
|
||||
index int
|
||||
syntax pref.Syntax
|
||||
fullName pref.FullName
|
||||
|
||||
desc descriptorSubMeta
|
||||
opts descriptorOptionsMeta
|
||||
}
|
||||
|
||||
func (m *inheritedMeta) init(nb *nameBuilder, parent pref.Descriptor, index int, name pref.Name, child bool) {
|
||||
@ -41,9 +39,6 @@ func (m *inheritedMeta) init(nb *nameBuilder, parent pref.Descriptor, index int,
|
||||
}
|
||||
|
||||
type fileMeta struct {
|
||||
desc descriptorFileMeta
|
||||
opts descriptorOptionsMeta
|
||||
|
||||
ms messagesMeta
|
||||
es enumsMeta
|
||||
xs extensionsMeta
|
||||
@ -59,25 +54,25 @@ func newFile(f *File) fileDesc {
|
||||
f.fileMeta = new(fileMeta)
|
||||
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 }
|
||||
func (t fileDesc) IsPlaceholder() bool { return false }
|
||||
func (t fileDesc) DescriptorProto() (pref.Message, bool) { return t.f.desc.lazyInit(t) }
|
||||
func (t fileDesc) DescriptorOptions() (pref.DescriptorOptions, bool) { return t.f.opts.lazyInit(t) }
|
||||
func (t fileDesc) Path() string { return t.f.Path }
|
||||
func (t fileDesc) Package() pref.FullName { return t.f.Package }
|
||||
func (t fileDesc) Imports() pref.FileImports { return (*fileImports)(&t.f.Imports) }
|
||||
func (t fileDesc) Messages() pref.MessageDescriptors { return t.f.ms.lazyInit(t, t.f.Messages) }
|
||||
func (t fileDesc) Enums() pref.EnumDescriptors { return t.f.es.lazyInit(t, t.f.Enums) }
|
||||
func (t fileDesc) Extensions() pref.ExtensionDescriptors { return t.f.xs.lazyInit(t, t.f.Extensions) }
|
||||
func (t fileDesc) Services() pref.ServiceDescriptors { return t.f.ss.lazyInit(t, t.f.Services) }
|
||||
func (t fileDesc) DescriptorByName(s pref.FullName) pref.Descriptor { return t.f.ds.lookup(t, s) }
|
||||
func (t fileDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t fileDesc) ProtoType(pref.FileDescriptor) {}
|
||||
func (t fileDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
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 }
|
||||
func (t fileDesc) IsPlaceholder() bool { return false }
|
||||
func (t fileDesc) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t fileDesc) Options() interface{} { return t.f.Options }
|
||||
func (t fileDesc) Path() string { return t.f.Path }
|
||||
func (t fileDesc) Package() pref.FullName { return t.f.Package }
|
||||
func (t fileDesc) Imports() pref.FileImports { return (*fileImports)(&t.f.Imports) }
|
||||
func (t fileDesc) Messages() pref.MessageDescriptors { return t.f.ms.lazyInit(t, t.f.Messages) }
|
||||
func (t fileDesc) Enums() pref.EnumDescriptors { return t.f.es.lazyInit(t, t.f.Enums) }
|
||||
func (t fileDesc) Extensions() pref.ExtensionDescriptors { return t.f.xs.lazyInit(t, t.f.Extensions) }
|
||||
func (t fileDesc) Services() pref.ServiceDescriptors { return t.f.ss.lazyInit(t, t.f.Services) }
|
||||
func (t fileDesc) DescriptorByName(s pref.FullName) pref.Descriptor { return t.f.ds.lookup(t, s) }
|
||||
func (t fileDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t fileDesc) ProtoType(pref.FileDescriptor) {}
|
||||
func (t fileDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
|
||||
// descriptorsMeta is a lazily initialized map of all descriptors declared in
|
||||
// the file by full name.
|
||||
@ -166,25 +161,25 @@ 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 }
|
||||
func (t messageDesc) IsPlaceholder() bool { return false }
|
||||
func (t messageDesc) DescriptorProto() (pref.Message, bool) { return t.m.desc.lazyInit(t) }
|
||||
func (t messageDesc) DescriptorOptions() (pref.DescriptorOptions, bool) { return t.m.opts.lazyInit(t) }
|
||||
func (t messageDesc) IsMapEntry() bool { return t.m.IsMapEntry }
|
||||
func (t messageDesc) Fields() pref.FieldDescriptors { return t.m.fs.lazyInit(t, t.m.Fields) }
|
||||
func (t messageDesc) Oneofs() pref.OneofDescriptors { return t.m.os.lazyInit(t, t.m.Oneofs) }
|
||||
func (t messageDesc) RequiredNumbers() pref.FieldNumbers { return t.m.ns.lazyInit(t.m.Fields) }
|
||||
func (t messageDesc) ExtensionRanges() pref.FieldRanges { return (*ranges)(&t.m.ExtensionRanges) }
|
||||
func (t messageDesc) Messages() pref.MessageDescriptors { return t.m.ms.lazyInit(t, t.m.Messages) }
|
||||
func (t messageDesc) Enums() pref.EnumDescriptors { return t.m.es.lazyInit(t, t.m.Enums) }
|
||||
func (t messageDesc) Extensions() pref.ExtensionDescriptors { return t.m.xs.lazyInit(t, t.m.Extensions) }
|
||||
func (t messageDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t messageDesc) ProtoType(pref.MessageDescriptor) {}
|
||||
func (t messageDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
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 }
|
||||
func (t messageDesc) IsPlaceholder() bool { return false }
|
||||
func (t messageDesc) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t messageDesc) Options() interface{} { return t.m.Options }
|
||||
func (t messageDesc) IsMapEntry() bool { return t.m.Options.GetMapEntry() }
|
||||
func (t messageDesc) Fields() pref.FieldDescriptors { return t.m.fs.lazyInit(t, t.m.Fields) }
|
||||
func (t messageDesc) Oneofs() pref.OneofDescriptors { return t.m.os.lazyInit(t, t.m.Oneofs) }
|
||||
func (t messageDesc) RequiredNumbers() pref.FieldNumbers { return t.m.ns.lazyInit(t.m.Fields) }
|
||||
func (t messageDesc) ExtensionRanges() pref.FieldRanges { return (*ranges)(&t.m.ExtensionRanges) }
|
||||
func (t messageDesc) Messages() pref.MessageDescriptors { return t.m.ms.lazyInit(t, t.m.Messages) }
|
||||
func (t messageDesc) Enums() pref.EnumDescriptors { return t.m.es.lazyInit(t, t.m.Enums) }
|
||||
func (t messageDesc) Extensions() pref.ExtensionDescriptors { return t.m.xs.lazyInit(t, t.m.Extensions) }
|
||||
func (t messageDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t messageDesc) ProtoType(pref.MessageDescriptor) {}
|
||||
func (t messageDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
|
||||
type fieldMeta struct {
|
||||
inheritedMeta
|
||||
@ -197,35 +192,64 @@ 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 }
|
||||
func (t fieldDesc) IsPlaceholder() bool { return false }
|
||||
func (t fieldDesc) DescriptorProto() (pref.Message, bool) { return t.f.desc.lazyInit(t) }
|
||||
func (t fieldDesc) DescriptorOptions() (pref.DescriptorOptions, bool) { return t.f.opts.lazyInit(t) }
|
||||
func (t fieldDesc) Number() pref.FieldNumber { return t.f.Number }
|
||||
func (t fieldDesc) Cardinality() pref.Cardinality { return t.f.Cardinality }
|
||||
func (t fieldDesc) Kind() pref.Kind { return t.f.Kind }
|
||||
func (t fieldDesc) JSONName() string { return t.f.js.lazyInit(t.f) }
|
||||
func (t fieldDesc) IsPacked() bool { return t.f.IsPacked }
|
||||
func (t fieldDesc) IsMap() bool { return isMap(t) }
|
||||
func (t fieldDesc) IsWeak() bool { return t.f.IsWeak }
|
||||
func (t fieldDesc) Default() pref.Value { return t.f.dv.lazyInit(t, t.f.Default) }
|
||||
func (t fieldDesc) HasDefault() bool { return t.f.Default.IsValid() }
|
||||
func (t fieldDesc) OneofType() pref.OneofDescriptor { return t.f.ot.lazyInit(t, t.f.OneofName) }
|
||||
func (t fieldDesc) ExtendedType() pref.MessageDescriptor { return nil }
|
||||
func (t fieldDesc) MessageType() pref.MessageDescriptor { return t.f.mt.lazyInit(t, &t.f.MessageType) }
|
||||
func (t fieldDesc) EnumType() pref.EnumDescriptor { return t.f.et.lazyInit(t, &t.f.EnumType) }
|
||||
func (t fieldDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t fieldDesc) ProtoType(pref.FieldDescriptor) {}
|
||||
func (t fieldDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
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 }
|
||||
func (t fieldDesc) IsPlaceholder() bool { return false }
|
||||
func (t fieldDesc) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t fieldDesc) Options() interface{} { return t.f.Options }
|
||||
func (t fieldDesc) Number() pref.FieldNumber { return t.f.Number }
|
||||
func (t fieldDesc) Cardinality() pref.Cardinality { return t.f.Cardinality }
|
||||
func (t fieldDesc) Kind() pref.Kind { return t.f.Kind }
|
||||
func (t fieldDesc) JSONName() string { return t.f.js.lazyInit(t.f) }
|
||||
func (t fieldDesc) IsPacked() bool { return fieldIsPacked(t) }
|
||||
func (t fieldDesc) IsMap() bool { return isMap(t) }
|
||||
func (t fieldDesc) IsWeak() bool { return t.f.Options.GetWeak() }
|
||||
func (t fieldDesc) Default() pref.Value { return t.f.dv.lazyInit(t, t.f.Default) }
|
||||
func (t fieldDesc) HasDefault() bool { return t.f.Default.IsValid() }
|
||||
func (t fieldDesc) OneofType() pref.OneofDescriptor { return t.f.ot.lazyInit(t, t.f.OneofName) }
|
||||
func (t fieldDesc) ExtendedType() pref.MessageDescriptor { return nil }
|
||||
func (t fieldDesc) MessageType() pref.MessageDescriptor { return t.f.mt.lazyInit(t, &t.f.MessageType) }
|
||||
func (t fieldDesc) EnumType() pref.EnumDescriptor { return t.f.et.lazyInit(t, &t.f.EnumType) }
|
||||
func (t fieldDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t fieldDesc) ProtoType(pref.FieldDescriptor) {}
|
||||
func (t fieldDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
|
||||
func fieldIsPacked(t fieldDesc) bool {
|
||||
if t.f.Options != nil && t.f.Options.Packed != nil {
|
||||
return *t.f.Options.Packed
|
||||
}
|
||||
// https://developers.google.com/protocol-buffers/docs/proto3:
|
||||
// "In proto3, repeated fields of scalar numeric types use packed
|
||||
// encoding by default."
|
||||
return (t.f.syntax == pref.Proto3 &&
|
||||
t.f.Cardinality == pref.Repeated &&
|
||||
isScalarNumeric[t.f.Kind])
|
||||
}
|
||||
|
||||
var isScalarNumeric = map[pref.Kind]bool{
|
||||
pref.BoolKind: true,
|
||||
pref.EnumKind: true,
|
||||
pref.Int32Kind: true,
|
||||
pref.Sint32Kind: true,
|
||||
pref.Uint32Kind: true,
|
||||
pref.Int64Kind: true,
|
||||
pref.Sint64Kind: true,
|
||||
pref.Uint64Kind: true,
|
||||
pref.Sfixed32Kind: true,
|
||||
pref.Fixed32Kind: true,
|
||||
pref.FloatKind: true,
|
||||
pref.Sfixed64Kind: true,
|
||||
pref.Fixed64Kind: true,
|
||||
pref.DoubleKind: true,
|
||||
}
|
||||
|
||||
func isMap(t pref.FieldDescriptor) bool {
|
||||
if t.Cardinality() == pref.Repeated && t.Kind() == pref.MessageKind {
|
||||
if mt := t.MessageType(); mt != nil {
|
||||
return mt.IsMapEntry()
|
||||
return mt.Options().(*descriptorV1.MessageOptions).GetMapEntry()
|
||||
}
|
||||
}
|
||||
return false
|
||||
@ -283,18 +307,18 @@ 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 }
|
||||
func (t oneofDesc) IsPlaceholder() bool { return false }
|
||||
func (t oneofDesc) DescriptorProto() (pref.Message, bool) { return t.o.desc.lazyInit(t) }
|
||||
func (t oneofDesc) DescriptorOptions() (pref.DescriptorOptions, bool) { return t.o.opts.lazyInit(t) }
|
||||
func (t oneofDesc) Fields() pref.FieldDescriptors { return t.o.fs.lazyInit(t) }
|
||||
func (t oneofDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t oneofDesc) ProtoType(pref.OneofDescriptor) {}
|
||||
func (t oneofDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
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 }
|
||||
func (t oneofDesc) IsPlaceholder() bool { return false }
|
||||
func (t oneofDesc) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t oneofDesc) Options() interface{} { return t.o.Options }
|
||||
func (t oneofDesc) Fields() pref.FieldDescriptors { return t.o.fs.lazyInit(t) }
|
||||
func (t oneofDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t oneofDesc) ProtoType(pref.OneofDescriptor) {}
|
||||
func (t oneofDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
|
||||
type extensionMeta struct {
|
||||
inheritedMeta
|
||||
@ -306,24 +330,24 @@ type extensionMeta struct {
|
||||
}
|
||||
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 }
|
||||
func (t extensionDesc) DescriptorProto() (pref.Message, bool) { return t.x.desc.lazyInit(t) }
|
||||
func (t extensionDesc) DescriptorOptions() (pref.DescriptorOptions, bool) { return t.x.opts.lazyInit(t) }
|
||||
func (t extensionDesc) Number() pref.FieldNumber { return t.x.Number }
|
||||
func (t extensionDesc) Cardinality() pref.Cardinality { return t.x.Cardinality }
|
||||
func (t extensionDesc) Kind() pref.Kind { return t.x.Kind }
|
||||
func (t extensionDesc) JSONName() string { return "" }
|
||||
func (t extensionDesc) IsPacked() bool { return t.x.IsPacked }
|
||||
func (t extensionDesc) IsMap() bool { return false }
|
||||
func (t extensionDesc) IsWeak() bool { return false }
|
||||
func (t extensionDesc) Default() pref.Value { return t.x.dv.lazyInit(t, t.x.Default) }
|
||||
func (t extensionDesc) HasDefault() bool { return t.x.Default.IsValid() }
|
||||
func (t extensionDesc) OneofType() pref.OneofDescriptor { return nil }
|
||||
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 }
|
||||
func (t extensionDesc) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t extensionDesc) Options() interface{} { return t.x.Options }
|
||||
func (t extensionDesc) Number() pref.FieldNumber { return t.x.Number }
|
||||
func (t extensionDesc) Cardinality() pref.Cardinality { return t.x.Cardinality }
|
||||
func (t extensionDesc) Kind() pref.Kind { return t.x.Kind }
|
||||
func (t extensionDesc) JSONName() string { return "" }
|
||||
func (t extensionDesc) IsPacked() bool { return extIsPacked(t) }
|
||||
func (t extensionDesc) IsMap() bool { return false }
|
||||
func (t extensionDesc) IsWeak() bool { return false }
|
||||
func (t extensionDesc) Default() pref.Value { return t.x.dv.lazyInit(t, t.x.Default) }
|
||||
func (t extensionDesc) HasDefault() bool { return t.x.Default.IsValid() }
|
||||
func (t extensionDesc) OneofType() pref.OneofDescriptor { return nil }
|
||||
func (t extensionDesc) ExtendedType() pref.MessageDescriptor {
|
||||
return t.x.xt.lazyInit(t, &t.x.ExtendedType)
|
||||
}
|
||||
@ -335,6 +359,15 @@ func (t extensionDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t
|
||||
func (t extensionDesc) ProtoType(pref.FieldDescriptor) {}
|
||||
func (t extensionDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
|
||||
func extIsPacked(t extensionDesc) bool {
|
||||
// TODO: When a proto3 file extends a proto2 message (permitted only for
|
||||
// extending descriptor options), does the extension have proto2 or proto3
|
||||
// semantics? If the latter, repeated, scalar, numeric, proto3 extension
|
||||
// fields should default to packed. If the former, perhaps the extension syntax
|
||||
// should be protoreflect.Proto2.
|
||||
return t.x.Options.GetPacked()
|
||||
}
|
||||
|
||||
type enumMeta struct {
|
||||
inheritedMeta
|
||||
|
||||
@ -342,36 +375,36 @@ 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 }
|
||||
func (t enumDesc) IsPlaceholder() bool { return false }
|
||||
func (t enumDesc) DescriptorProto() (pref.Message, bool) { return t.e.desc.lazyInit(t) }
|
||||
func (t enumDesc) DescriptorOptions() (pref.DescriptorOptions, bool) { return t.e.opts.lazyInit(t) }
|
||||
func (t enumDesc) Values() pref.EnumValueDescriptors { return t.e.vs.lazyInit(t, t.e.Values) }
|
||||
func (t enumDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t enumDesc) ProtoType(pref.EnumDescriptor) {}
|
||||
func (t enumDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
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 }
|
||||
func (t enumDesc) IsPlaceholder() bool { return false }
|
||||
func (t enumDesc) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t enumDesc) Options() interface{} { return t.e.Options }
|
||||
func (t enumDesc) Values() pref.EnumValueDescriptors { return t.e.vs.lazyInit(t, t.e.Values) }
|
||||
func (t enumDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t enumDesc) ProtoType(pref.EnumDescriptor) {}
|
||||
func (t enumDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
|
||||
type enumValueMeta struct {
|
||||
inheritedMeta
|
||||
}
|
||||
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 }
|
||||
func (t enumValueDesc) IsPlaceholder() bool { return false }
|
||||
func (t enumValueDesc) DescriptorProto() (pref.Message, bool) { return t.v.desc.lazyInit(t) }
|
||||
func (t enumValueDesc) DescriptorOptions() (pref.DescriptorOptions, bool) { return t.v.opts.lazyInit(t) }
|
||||
func (t enumValueDesc) Number() pref.EnumNumber { return t.v.Number }
|
||||
func (t enumValueDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t enumValueDesc) ProtoType(pref.EnumValueDescriptor) {}
|
||||
func (t enumValueDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
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 }
|
||||
func (t enumValueDesc) IsPlaceholder() bool { return false }
|
||||
func (t enumValueDesc) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t enumValueDesc) Options() interface{} { return t.v.Options }
|
||||
func (t enumValueDesc) Number() pref.EnumNumber { return t.v.Number }
|
||||
func (t enumValueDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t enumValueDesc) ProtoType(pref.EnumValueDescriptor) {}
|
||||
func (t enumValueDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
|
||||
type serviceMeta struct {
|
||||
inheritedMeta
|
||||
@ -380,18 +413,18 @@ 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 }
|
||||
func (t serviceDesc) IsPlaceholder() bool { return false }
|
||||
func (t serviceDesc) DescriptorProto() (pref.Message, bool) { return t.s.desc.lazyInit(t) }
|
||||
func (t serviceDesc) DescriptorOptions() (pref.DescriptorOptions, bool) { return t.s.opts.lazyInit(t) }
|
||||
func (t serviceDesc) Methods() pref.MethodDescriptors { return t.s.ms.lazyInit(t, t.s.Methods) }
|
||||
func (t serviceDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t serviceDesc) ProtoType(pref.ServiceDescriptor) {}
|
||||
func (t serviceDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
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 }
|
||||
func (t serviceDesc) IsPlaceholder() bool { return false }
|
||||
func (t serviceDesc) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t serviceDesc) Options() interface{} { return t.s.Options }
|
||||
func (t serviceDesc) Methods() pref.MethodDescriptors { return t.s.ms.lazyInit(t, t.s.Methods) }
|
||||
func (t serviceDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t serviceDesc) ProtoType(pref.ServiceDescriptor) {}
|
||||
func (t serviceDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
|
||||
type methodMeta struct {
|
||||
inheritedMeta
|
||||
@ -401,21 +434,21 @@ 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 }
|
||||
func (t methodDesc) IsPlaceholder() bool { return false }
|
||||
func (t methodDesc) DescriptorProto() (pref.Message, bool) { return t.m.desc.lazyInit(t) }
|
||||
func (t methodDesc) DescriptorOptions() (pref.DescriptorOptions, bool) { return t.m.opts.lazyInit(t) }
|
||||
func (t methodDesc) InputType() pref.MessageDescriptor { return t.m.mit.lazyInit(t, &t.m.InputType) }
|
||||
func (t methodDesc) OutputType() pref.MessageDescriptor { return t.m.mot.lazyInit(t, &t.m.OutputType) }
|
||||
func (t methodDesc) IsStreamingClient() bool { return t.m.IsStreamingClient }
|
||||
func (t methodDesc) IsStreamingServer() bool { return t.m.IsStreamingServer }
|
||||
func (t methodDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t methodDesc) ProtoType(pref.MethodDescriptor) {}
|
||||
func (t methodDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
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 }
|
||||
func (t methodDesc) IsPlaceholder() bool { return false }
|
||||
func (t methodDesc) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t methodDesc) Options() interface{} { return t.m.Options }
|
||||
func (t methodDesc) InputType() pref.MessageDescriptor { return t.m.mit.lazyInit(t, &t.m.InputType) }
|
||||
func (t methodDesc) OutputType() pref.MessageDescriptor { return t.m.mot.lazyInit(t, &t.m.OutputType) }
|
||||
func (t methodDesc) IsStreamingClient() bool { return t.m.IsStreamingClient }
|
||||
func (t methodDesc) IsStreamingServer() bool { return t.m.IsStreamingServer }
|
||||
func (t methodDesc) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t methodDesc) ProtoType(pref.MethodDescriptor) {}
|
||||
func (t methodDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
|
||||
type defaultValue struct {
|
||||
once sync.Once
|
||||
|
@ -5,6 +5,7 @@
|
||||
package prototype
|
||||
|
||||
import (
|
||||
descriptorV1 "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/golang/protobuf/v2/internal/errors"
|
||||
"github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
)
|
||||
@ -17,10 +18,10 @@ import (
|
||||
type StandaloneMessage struct {
|
||||
Syntax protoreflect.Syntax
|
||||
FullName protoreflect.FullName
|
||||
IsMapEntry bool
|
||||
Fields []Field
|
||||
Oneofs []Oneof
|
||||
ExtensionRanges [][2]protoreflect.FieldNumber
|
||||
Options *descriptorV1.MessageOptions
|
||||
|
||||
fields fieldsMeta
|
||||
oneofs oneofsMeta
|
||||
@ -63,7 +64,7 @@ func NewMessages(ts []*StandaloneMessage) ([]protoreflect.MessageDescriptor, err
|
||||
for i, f := range t.Fields {
|
||||
// Resolve placeholder messages with a concrete standalone message.
|
||||
// If this fails, validateMessage will complain about it later.
|
||||
if !f.IsWeak && f.MessageType != nil && f.MessageType.IsPlaceholder() {
|
||||
if !f.Options.GetWeak() && f.MessageType != nil && f.MessageType.IsPlaceholder() {
|
||||
if m, ok := ms[f.MessageType.FullName()]; ok {
|
||||
t.Fields[i].MessageType = m
|
||||
}
|
||||
@ -84,6 +85,7 @@ type StandaloneEnum struct {
|
||||
Syntax protoreflect.Syntax
|
||||
FullName protoreflect.FullName
|
||||
Values []EnumValue
|
||||
Options *descriptorV1.EnumOptions
|
||||
|
||||
vals enumValuesMeta
|
||||
}
|
||||
@ -107,11 +109,11 @@ type StandaloneExtension struct {
|
||||
Number protoreflect.FieldNumber
|
||||
Cardinality protoreflect.Cardinality
|
||||
Kind protoreflect.Kind
|
||||
IsPacked bool
|
||||
Default protoreflect.Value
|
||||
MessageType protoreflect.MessageDescriptor
|
||||
EnumType protoreflect.EnumDescriptor
|
||||
ExtendedType protoreflect.MessageDescriptor
|
||||
Options *descriptorV1.FieldOptions
|
||||
|
||||
dv defaultValue
|
||||
}
|
||||
|
@ -13,64 +13,64 @@ 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 }
|
||||
func (t standaloneMessage) IsPlaceholder() bool { return false }
|
||||
func (t standaloneMessage) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t standaloneMessage) DescriptorOptions() (pref.DescriptorOptions, bool) { return nil, false }
|
||||
func (t standaloneMessage) IsMapEntry() bool { return t.m.IsMapEntry }
|
||||
func (t standaloneMessage) Fields() pref.FieldDescriptors { return t.m.fields.lazyInit(t, t.m.Fields) }
|
||||
func (t standaloneMessage) Oneofs() pref.OneofDescriptors { return t.m.oneofs.lazyInit(t, t.m.Oneofs) }
|
||||
func (t standaloneMessage) RequiredNumbers() pref.FieldNumbers { return t.m.nums.lazyInit(t.m.Fields) }
|
||||
func (t standaloneMessage) ExtensionRanges() pref.FieldRanges { return (*ranges)(&t.m.ExtensionRanges) }
|
||||
func (t standaloneMessage) Messages() pref.MessageDescriptors { return &emptyMessages }
|
||||
func (t standaloneMessage) Enums() pref.EnumDescriptors { return &emptyEnums }
|
||||
func (t standaloneMessage) Extensions() pref.ExtensionDescriptors { return &emptyExtensions }
|
||||
func (t standaloneMessage) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t standaloneMessage) ProtoType(pref.MessageDescriptor) {}
|
||||
func (t standaloneMessage) ProtoInternal(pragma.DoNotImplement) {}
|
||||
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 }
|
||||
func (t standaloneMessage) IsPlaceholder() bool { return false }
|
||||
func (t standaloneMessage) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t standaloneMessage) Options() interface{} { return t.m.Options }
|
||||
func (t standaloneMessage) IsMapEntry() bool { return t.m.Options.GetMapEntry() }
|
||||
func (t standaloneMessage) Fields() pref.FieldDescriptors { return t.m.fields.lazyInit(t, t.m.Fields) }
|
||||
func (t standaloneMessage) Oneofs() pref.OneofDescriptors { return t.m.oneofs.lazyInit(t, t.m.Oneofs) }
|
||||
func (t standaloneMessage) RequiredNumbers() pref.FieldNumbers { return t.m.nums.lazyInit(t.m.Fields) }
|
||||
func (t standaloneMessage) ExtensionRanges() pref.FieldRanges { return (*ranges)(&t.m.ExtensionRanges) }
|
||||
func (t standaloneMessage) Messages() pref.MessageDescriptors { return &emptyMessages }
|
||||
func (t standaloneMessage) Enums() pref.EnumDescriptors { return &emptyEnums }
|
||||
func (t standaloneMessage) Extensions() pref.ExtensionDescriptors { return &emptyExtensions }
|
||||
func (t standaloneMessage) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t standaloneMessage) ProtoType(pref.MessageDescriptor) {}
|
||||
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 }
|
||||
func (t standaloneEnum) IsPlaceholder() bool { return false }
|
||||
func (t standaloneEnum) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t standaloneEnum) DescriptorOptions() (pref.DescriptorOptions, bool) { return nil, false }
|
||||
func (t standaloneEnum) Values() pref.EnumValueDescriptors { return t.e.vals.lazyInit(t, t.e.Values) }
|
||||
func (t standaloneEnum) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t standaloneEnum) ProtoType(pref.EnumDescriptor) {}
|
||||
func (t standaloneEnum) ProtoInternal(pragma.DoNotImplement) {}
|
||||
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 }
|
||||
func (t standaloneEnum) IsPlaceholder() bool { return false }
|
||||
func (t standaloneEnum) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t standaloneEnum) Options() interface{} { return t.e.Options }
|
||||
func (t standaloneEnum) Values() pref.EnumValueDescriptors { return t.e.vals.lazyInit(t, t.e.Values) }
|
||||
func (t standaloneEnum) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t standaloneEnum) ProtoType(pref.EnumDescriptor) {}
|
||||
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 }
|
||||
func (t standaloneExtension) IsPlaceholder() bool { return false }
|
||||
func (t standaloneExtension) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t standaloneExtension) DescriptorOptions() (pref.DescriptorOptions, bool) { return nil, false }
|
||||
func (t standaloneExtension) Number() pref.FieldNumber { return t.x.Number }
|
||||
func (t standaloneExtension) Cardinality() pref.Cardinality { return t.x.Cardinality }
|
||||
func (t standaloneExtension) Kind() pref.Kind { return t.x.Kind }
|
||||
func (t standaloneExtension) JSONName() string { return "" }
|
||||
func (t standaloneExtension) IsPacked() bool { return t.x.IsPacked }
|
||||
func (t standaloneExtension) IsMap() bool { return false }
|
||||
func (t standaloneExtension) IsWeak() bool { return false }
|
||||
func (t standaloneExtension) Default() pref.Value { return t.x.dv.lazyInit(t, t.x.Default) }
|
||||
func (t standaloneExtension) HasDefault() bool { return t.x.Default.IsValid() }
|
||||
func (t standaloneExtension) OneofType() pref.OneofDescriptor { return nil }
|
||||
func (t standaloneExtension) MessageType() pref.MessageDescriptor { return t.x.MessageType }
|
||||
func (t standaloneExtension) EnumType() pref.EnumDescriptor { return t.x.EnumType }
|
||||
func (t standaloneExtension) ExtendedType() pref.MessageDescriptor { return t.x.ExtendedType }
|
||||
func (t standaloneExtension) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t standaloneExtension) ProtoType(pref.FieldDescriptor) {}
|
||||
func (t standaloneExtension) ProtoInternal(pragma.DoNotImplement) {}
|
||||
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 }
|
||||
func (t standaloneExtension) IsPlaceholder() bool { return false }
|
||||
func (t standaloneExtension) DescriptorProto() (pref.Message, bool) { return nil, false }
|
||||
func (t standaloneExtension) Options() interface{} { return t.x.Options }
|
||||
func (t standaloneExtension) Number() pref.FieldNumber { return t.x.Number }
|
||||
func (t standaloneExtension) Cardinality() pref.Cardinality { return t.x.Cardinality }
|
||||
func (t standaloneExtension) Kind() pref.Kind { return t.x.Kind }
|
||||
func (t standaloneExtension) JSONName() string { return "" }
|
||||
func (t standaloneExtension) IsPacked() bool { return t.x.Options.GetPacked() }
|
||||
func (t standaloneExtension) IsMap() bool { return false }
|
||||
func (t standaloneExtension) IsWeak() bool { return false }
|
||||
func (t standaloneExtension) Default() pref.Value { return t.x.dv.lazyInit(t, t.x.Default) }
|
||||
func (t standaloneExtension) HasDefault() bool { return t.x.Default.IsValid() }
|
||||
func (t standaloneExtension) OneofType() pref.OneofDescriptor { return nil }
|
||||
func (t standaloneExtension) MessageType() pref.MessageDescriptor { return t.x.MessageType }
|
||||
func (t standaloneExtension) EnumType() pref.EnumDescriptor { return t.x.EnumType }
|
||||
func (t standaloneExtension) ExtendedType() pref.MessageDescriptor { return t.x.ExtendedType }
|
||||
func (t standaloneExtension) Format(s fmt.State, r rune) { formatDesc(s, r, t) }
|
||||
func (t standaloneExtension) ProtoType(pref.FieldDescriptor) {}
|
||||
func (t standaloneExtension) ProtoInternal(pragma.DoNotImplement) {}
|
||||
|
@ -109,12 +109,17 @@ func TestFile(t *testing.T) {
|
||||
Syntax: pref.Proto2,
|
||||
Path: "path/to/file.proto",
|
||||
Package: "test",
|
||||
Options: &descriptorV1.FileOptions{Deprecated: protoV1.Bool(true)},
|
||||
Messages: []Message{{
|
||||
Name: "A", // "test.A"
|
||||
IsMapEntry: true,
|
||||
Name: "A", // "test.A"
|
||||
Options: &descriptorV1.MessageOptions{
|
||||
MapEntry: protoV1.Bool(true),
|
||||
Deprecated: protoV1.Bool(true),
|
||||
},
|
||||
Fields: []Field{{
|
||||
Name: "key", // "test.A.key"
|
||||
Number: 1,
|
||||
Options: &descriptorV1.FieldOptions{Deprecated: protoV1.Bool(true)},
|
||||
Cardinality: pref.Optional,
|
||||
Kind: pref.StringKind,
|
||||
}, {
|
||||
@ -161,7 +166,7 @@ func TestFile(t *testing.T) {
|
||||
Number: 5,
|
||||
Cardinality: pref.Repeated,
|
||||
Kind: pref.Int32Kind,
|
||||
IsPacked: true,
|
||||
Options: &descriptorV1.FieldOptions{Packed: protoV1.Bool(true)},
|
||||
}, {
|
||||
Name: "field_six", // "test.B.field_six"
|
||||
Number: 6,
|
||||
@ -169,7 +174,14 @@ func TestFile(t *testing.T) {
|
||||
Kind: pref.BytesKind,
|
||||
}},
|
||||
Oneofs: []Oneof{
|
||||
{Name: "O1"}, // "test.B.O1"
|
||||
{
|
||||
Name: "O1", // "test.B.O1"
|
||||
Options: &descriptorV1.OneofOptions{
|
||||
UninterpretedOption: []*descriptorV1.UninterpretedOption{
|
||||
{StringValue: []byte("option")},
|
||||
},
|
||||
},
|
||||
},
|
||||
{Name: "O2"}, // "test.B.O2"
|
||||
},
|
||||
ExtensionRanges: [][2]pref.FieldNumber{{1000, 2000}, {3000, 3001}},
|
||||
@ -188,32 +200,42 @@ func TestFile(t *testing.T) {
|
||||
Number: 1000,
|
||||
Cardinality: pref.Repeated,
|
||||
Kind: pref.MessageKind,
|
||||
IsPacked: false,
|
||||
Options: &descriptorV1.FieldOptions{Packed: protoV1.Bool(false)},
|
||||
MessageType: PlaceholderMessage("test.C"),
|
||||
ExtendedType: PlaceholderMessage("test.B"),
|
||||
}},
|
||||
}},
|
||||
Enums: []Enum{{
|
||||
Name: "E1", // "test.E1"
|
||||
Values: []EnumValue{{Name: "FOO", Number: 0}, {Name: "BAR", Number: 1}},
|
||||
Name: "E1", // "test.E1"
|
||||
Options: &descriptorV1.EnumOptions{Deprecated: protoV1.Bool(true)},
|
||||
Values: []EnumValue{
|
||||
{
|
||||
Name: "FOO",
|
||||
Number: 0,
|
||||
Options: &descriptorV1.EnumValueOptions{Deprecated: protoV1.Bool(true)},
|
||||
},
|
||||
{Name: "BAR", Number: 1},
|
||||
},
|
||||
}},
|
||||
Extensions: []Extension{{
|
||||
Name: "X", // "test.X"
|
||||
Number: 1000,
|
||||
Cardinality: pref.Repeated,
|
||||
Kind: pref.MessageKind,
|
||||
IsPacked: true,
|
||||
Options: &descriptorV1.FieldOptions{Packed: protoV1.Bool(true)},
|
||||
MessageType: PlaceholderMessage("test.C"),
|
||||
ExtendedType: PlaceholderMessage("test.B"),
|
||||
}},
|
||||
Services: []Service{{
|
||||
Name: "S", // "test.S"
|
||||
Name: "S", // "test.S"
|
||||
Options: &descriptorV1.ServiceOptions{Deprecated: protoV1.Bool(true)},
|
||||
Methods: []Method{{
|
||||
Name: "M", // "test.S.M"
|
||||
InputType: PlaceholderMessage("test.A"),
|
||||
OutputType: PlaceholderMessage("test.C.A"),
|
||||
IsStreamingClient: true,
|
||||
IsStreamingServer: true,
|
||||
Options: &descriptorV1.MethodOptions{Deprecated: protoV1.Bool(true)},
|
||||
}},
|
||||
}},
|
||||
}
|
||||
@ -226,14 +248,19 @@ func TestFile(t *testing.T) {
|
||||
Syntax: protoV1.String("proto2"),
|
||||
Name: protoV1.String("path/to/file.proto"),
|
||||
Package: protoV1.String("test"),
|
||||
Options: &descriptorV1.FileOptions{Deprecated: protoV1.Bool(true)},
|
||||
MessageType: []*descriptorV1.DescriptorProto{{
|
||||
Name: protoV1.String("A"),
|
||||
Options: &descriptorV1.MessageOptions{MapEntry: protoV1.Bool(true)},
|
||||
Name: protoV1.String("A"),
|
||||
Options: &descriptorV1.MessageOptions{
|
||||
MapEntry: protoV1.Bool(true),
|
||||
Deprecated: protoV1.Bool(true),
|
||||
},
|
||||
Field: []*descriptorV1.FieldDescriptorProto{{
|
||||
Name: protoV1.String("key"),
|
||||
Number: protoV1.Int32(1),
|
||||
Label: descriptorV1.FieldDescriptorProto_Label(pref.Optional).Enum(),
|
||||
Type: descriptorV1.FieldDescriptorProto_Type(pref.StringKind).Enum(),
|
||||
Name: protoV1.String("key"),
|
||||
Number: protoV1.Int32(1),
|
||||
Options: &descriptorV1.FieldOptions{Deprecated: protoV1.Bool(true)},
|
||||
Label: descriptorV1.FieldDescriptorProto_Label(pref.Optional).Enum(),
|
||||
Type: descriptorV1.FieldDescriptorProto_Type(pref.StringKind).Enum(),
|
||||
}, {
|
||||
Name: protoV1.String("value"),
|
||||
Number: protoV1.Int32(2),
|
||||
@ -286,7 +313,14 @@ func TestFile(t *testing.T) {
|
||||
Type: descriptorV1.FieldDescriptorProto_Type(pref.BytesKind).Enum(),
|
||||
}},
|
||||
OneofDecl: []*descriptorV1.OneofDescriptorProto{
|
||||
{Name: protoV1.String("O1")},
|
||||
{
|
||||
Name: protoV1.String("O1"),
|
||||
Options: &descriptorV1.OneofOptions{
|
||||
UninterpretedOption: []*descriptorV1.UninterpretedOption{
|
||||
{StringValue: []byte("option")},
|
||||
},
|
||||
},
|
||||
},
|
||||
{Name: protoV1.String("O2")},
|
||||
},
|
||||
ExtensionRange: []*descriptorV1.DescriptorProto_ExtensionRange{
|
||||
@ -322,9 +356,14 @@ func TestFile(t *testing.T) {
|
||||
}},
|
||||
}},
|
||||
EnumType: []*descriptorV1.EnumDescriptorProto{{
|
||||
Name: protoV1.String("E1"),
|
||||
Name: protoV1.String("E1"),
|
||||
Options: &descriptorV1.EnumOptions{Deprecated: protoV1.Bool(true)},
|
||||
Value: []*descriptorV1.EnumValueDescriptorProto{
|
||||
{Name: protoV1.String("FOO"), Number: protoV1.Int32(0)},
|
||||
{
|
||||
Name: protoV1.String("FOO"),
|
||||
Number: protoV1.Int32(0),
|
||||
Options: &descriptorV1.EnumValueOptions{Deprecated: protoV1.Bool(true)},
|
||||
},
|
||||
{Name: protoV1.String("BAR"), Number: protoV1.Int32(1)},
|
||||
},
|
||||
}},
|
||||
@ -338,13 +377,15 @@ func TestFile(t *testing.T) {
|
||||
Extendee: protoV1.String(".test.B"),
|
||||
}},
|
||||
Service: []*descriptorV1.ServiceDescriptorProto{{
|
||||
Name: protoV1.String("S"),
|
||||
Name: protoV1.String("S"),
|
||||
Options: &descriptorV1.ServiceOptions{Deprecated: protoV1.Bool(true)},
|
||||
Method: []*descriptorV1.MethodDescriptorProto{{
|
||||
Name: protoV1.String("M"),
|
||||
InputType: protoV1.String(".test.A"),
|
||||
OutputType: protoV1.String(".test.C.A"),
|
||||
ClientStreaming: protoV1.Bool(true),
|
||||
ServerStreaming: protoV1.Bool(true),
|
||||
Options: &descriptorV1.MethodOptions{Deprecated: protoV1.Bool(true)},
|
||||
}},
|
||||
}},
|
||||
}
|
||||
@ -385,6 +426,7 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
|
||||
"Path": "path/to/file.proto",
|
||||
"Package": pref.FullName("test"),
|
||||
"IsPlaceholder": false,
|
||||
"Options": &descriptorV1.FileOptions{Deprecated: protoV1.Bool(true)},
|
||||
"Messages": M{
|
||||
"Len": 3,
|
||||
"Get:0": M{
|
||||
@ -395,6 +437,10 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
|
||||
"FullName": pref.FullName("test.A"),
|
||||
"IsPlaceholder": false,
|
||||
"IsMapEntry": true,
|
||||
"Options": &descriptorV1.MessageOptions{
|
||||
MapEntry: protoV1.Bool(true),
|
||||
Deprecated: protoV1.Bool(true),
|
||||
},
|
||||
"Fields": M{
|
||||
"Len": 2,
|
||||
"ByNumber:1": M{
|
||||
@ -405,6 +451,7 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
|
||||
"Number": pref.FieldNumber(1),
|
||||
"Cardinality": pref.Optional,
|
||||
"Kind": pref.StringKind,
|
||||
"Options": &descriptorV1.FieldOptions{Deprecated: protoV1.Bool(true)},
|
||||
"JSONName": "key",
|
||||
"IsPacked": false,
|
||||
"IsMap": false,
|
||||
@ -494,6 +541,11 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
|
||||
"ByName:O1": M{
|
||||
"FullName": pref.FullName("test.B.O1"),
|
||||
"Index": 0,
|
||||
"Options": &descriptorV1.OneofOptions{
|
||||
UninterpretedOption: []*descriptorV1.UninterpretedOption{
|
||||
{StringValue: []byte("option")},
|
||||
},
|
||||
},
|
||||
"Fields": M{
|
||||
"Len": 1,
|
||||
"Get:0": M{"FullName": pref.FullName("test.B.field_one")},
|
||||
@ -546,11 +598,15 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
|
||||
"Enums": M{
|
||||
"Len": 1,
|
||||
"Get:0": M{
|
||||
"Name": pref.Name("E1"),
|
||||
"Name": pref.Name("E1"),
|
||||
"Options": &descriptorV1.EnumOptions{Deprecated: protoV1.Bool(true)},
|
||||
"Values": M{
|
||||
"Len": 2,
|
||||
"ByName:Foo": nil,
|
||||
"ByName:FOO": M{"FullName": pref.FullName("test.FOO")},
|
||||
"ByName:FOO": M{
|
||||
"FullName": pref.FullName("test.FOO"),
|
||||
"Options": &descriptorV1.EnumValueOptions{Deprecated: protoV1.Bool(true)},
|
||||
},
|
||||
"ByNumber:2": nil,
|
||||
"ByNumber:1": M{"FullName": pref.FullName("test.BAR")},
|
||||
},
|
||||
@ -566,6 +622,7 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
|
||||
"IsPacked": true,
|
||||
"MessageType": M{"FullName": pref.FullName("test.C"), "IsPlaceholder": false},
|
||||
"ExtendedType": M{"FullName": pref.FullName("test.B"), "IsPlaceholder": false},
|
||||
"Options": &descriptorV1.FieldOptions{Packed: protoV1.Bool(true)},
|
||||
},
|
||||
},
|
||||
"Services": M{
|
||||
@ -575,6 +632,7 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
|
||||
"Parent": M{"FullName": pref.FullName("test")},
|
||||
"Name": pref.Name("S"),
|
||||
"FullName": pref.FullName("test.S"),
|
||||
"Options": &descriptorV1.ServiceOptions{Deprecated: protoV1.Bool(true)},
|
||||
"Methods": M{
|
||||
"Len": 1,
|
||||
"Get:0": M{
|
||||
@ -585,6 +643,7 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
|
||||
"OutputType": M{"FullName": pref.FullName("test.C.A"), "IsPlaceholder": false},
|
||||
"IsStreamingClient": true,
|
||||
"IsStreamingServer": true,
|
||||
"Options": &descriptorV1.MethodOptions{Deprecated: protoV1.Bool(true)},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -659,14 +718,26 @@ func checkAccessors(t *testing.T, p string, rv reflect.Value, want map[string]in
|
||||
// Check that the accessor output matches.
|
||||
if want, ok := v.(map[string]interface{}); ok {
|
||||
checkAccessors(t, p, rets[0], want)
|
||||
} else {
|
||||
got := rets[0].Interface()
|
||||
if pv, ok := got.(pref.Value); ok {
|
||||
got = pv.Interface()
|
||||
}
|
||||
if want := v; !reflect.DeepEqual(got, want) {
|
||||
continue
|
||||
}
|
||||
|
||||
got := rets[0].Interface()
|
||||
if pv, ok := got.(pref.Value); ok {
|
||||
got = pv.Interface()
|
||||
}
|
||||
|
||||
// Compare with proto.Equal if possible.
|
||||
gotMsg, gotMsgOK := got.(protoV1.Message)
|
||||
wantMsg, wantMsgOK := v.(protoV1.Message)
|
||||
if gotMsgOK && wantMsgOK {
|
||||
if !protoV1.Equal(gotMsg, wantMsg) {
|
||||
t.Errorf("%v = %v, want %v", p, got, want)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if want := v; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("%v = %v, want %v", p, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,9 @@ import (
|
||||
// * Placeholder messages and types may only be for weak fields.
|
||||
// * Placeholder full names must be valid.
|
||||
// * The name of each descriptor must be valid.
|
||||
// * Options are consistent with constructor fields:
|
||||
// Message.IsMapEntry and Message.Options.MapEntry
|
||||
// Field.IsPacked and Field.Options.Packed
|
||||
|
||||
func validateFile(t pref.FileDescriptor) error {
|
||||
return nil
|
||||
|
Loading…
x
Reference in New Issue
Block a user