mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-01-30 12:32:36 +00:00
internal/{fileinit,impl}: minimal weak field support
Weak fields are an obsolete proto1 feature. They have been superseded by extensions. However, some vestigial support for weak fields does remain, mostly as Google-internal patches. (They aren't exciting; extensions really do everything weak fields do in a cleaner and more portable fashion.) At the moment, the only visible impact of marking a field [weak=true] is to exclude it from "internal/fileinit".FileBuilder.DependencyIndexes. We want to preserve that behavior just in case we ever do add full weak field support here. Extend fileinit to look up message descriptors for weak fields in the global registry. If the descriptor cannot be found, use a placeholder instead. Remove special-case handling of weak fields in the impl package. The code generator doesn't do anything special for them, so they can be treated as any other field. Change-Id: Ifa2ee3d30d63680a0eeb59c66ebc9521f38fd660 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/175997 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
This commit is contained in:
parent
bac4cd44d4
commit
82a0306187
@ -16,6 +16,7 @@ import (
|
||||
ptype "github.com/golang/protobuf/v2/internal/prototype"
|
||||
pvalue "github.com/golang/protobuf/v2/internal/value"
|
||||
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
preg "github.com/golang/protobuf/v2/reflect/protoregistry"
|
||||
)
|
||||
|
||||
func (file *fileDesc) lazyInit() *fileLazy {
|
||||
@ -686,7 +687,12 @@ func (fd *fieldDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd p
|
||||
if len(rawTypeName) == 0 || rawTypeName[0] != '.' {
|
||||
panic("weak target name must be fully qualified")
|
||||
}
|
||||
fd.messageType = ptype.PlaceholderMessage(pref.FullName(rawTypeName[1:]))
|
||||
// Consult the global registry for weak messages.
|
||||
name := pref.FullName(rawTypeName[1:])
|
||||
fd.messageType, _ = preg.GlobalFiles.FindMessageByName(name)
|
||||
if fd.messageType == nil {
|
||||
fd.messageType = ptype.PlaceholderMessage(pref.FullName(rawTypeName[1:]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,3 +99,17 @@ func visitFields(m protoreflect.Message, f func(protoreflect.FieldDescriptor)) {
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func TestWeakInit(t *testing.T) {
|
||||
file := testpb.File_test_test_proto
|
||||
fd := file.Messages().ByName("TestWeak").Fields().ByName("weak_message")
|
||||
if want, got := fd.IsWeak(), true; got != want {
|
||||
t.Errorf("field %v: IsWeak() = %v, want %v", fd.FullName(), want, got)
|
||||
}
|
||||
if want, got := fd.Message().IsPlaceholder(), false; got != want {
|
||||
t.Errorf("field %v: Message.IsPlaceholder() = %v, want %v", fd.FullName(), want, got)
|
||||
}
|
||||
if fd.Message().Fields().Len() == 0 {
|
||||
t.Errorf("field %v: Message().Fields().Len() == 0, want >0", fd.FullName())
|
||||
}
|
||||
}
|
||||
|
@ -113,8 +113,6 @@ fieldLoop:
|
||||
fs := fieldsByNumber[fd.Number()]
|
||||
var fi fieldInfo
|
||||
switch {
|
||||
case fd.IsWeak():
|
||||
fi = fieldInfoForWeak(fd, specialByName["XXX_weak"])
|
||||
case fd.Oneof() != nil:
|
||||
fi = fieldInfoForOneof(fd, oneofsByName[fd.Oneof().Name()], oneofWrappersByNumber[fd.Number()])
|
||||
case fd.IsMap():
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/golang/protobuf/v2/internal/flags"
|
||||
pvalue "github.com/golang/protobuf/v2/internal/value"
|
||||
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
)
|
||||
@ -24,14 +23,6 @@ type fieldInfo struct {
|
||||
newMessage func() pref.Message
|
||||
}
|
||||
|
||||
func fieldInfoForWeak(fd pref.FieldDescriptor, fs reflect.StructField) fieldInfo {
|
||||
if !flags.Proto1Legacy {
|
||||
panic("weak fields not supported")
|
||||
}
|
||||
// TODO: support weak fields.
|
||||
panic(fmt.Sprintf("invalid field: %v", fd))
|
||||
}
|
||||
|
||||
func fieldInfoForOneof(fd pref.FieldDescriptor, fs reflect.StructField, ot reflect.Type) fieldInfo {
|
||||
ft := fs.Type
|
||||
if ft.Kind() != reflect.Interface {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,7 @@ package goproto.proto.test;
|
||||
|
||||
import "test/test_import.proto";
|
||||
import public "test/test_public.proto";
|
||||
import weak "test/test_weak.proto";
|
||||
import weak "test/weak/test_weak.proto";
|
||||
|
||||
option go_package = "github.com/golang/protobuf/v2/internal/testprotos/test";
|
||||
|
||||
@ -258,6 +258,10 @@ message TestRequiredGroupFields {
|
||||
}
|
||||
}
|
||||
|
||||
message TestWeak {
|
||||
optional goproto.proto.test.weak.WeakImportMessage weak_message = 1 [weak=true];
|
||||
}
|
||||
|
||||
// Test that RPC services work.
|
||||
message FooRequest {}
|
||||
message FooResponse {}
|
||||
|
@ -1,92 +0,0 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: test/test_weak.proto
|
||||
|
||||
package test
|
||||
|
||||
import (
|
||||
protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
protoregistry "github.com/golang/protobuf/v2/reflect/protoregistry"
|
||||
protoiface "github.com/golang/protobuf/v2/runtime/protoiface"
|
||||
protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
|
||||
|
||||
type WeakImportMessage struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized protoimpl.UnknownFields `json:"-"`
|
||||
XXX_sizecache protoimpl.SizeCache `json:"-"`
|
||||
}
|
||||
|
||||
func (x *WeakImportMessage) Reset() {
|
||||
*x = WeakImportMessage{}
|
||||
}
|
||||
|
||||
func (x *WeakImportMessage) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*WeakImportMessage) ProtoMessage() {}
|
||||
|
||||
func (x *WeakImportMessage) ProtoReflect() protoreflect.Message {
|
||||
return file_test_test_weak_proto_msgTypes[0].MessageOf(x)
|
||||
}
|
||||
|
||||
func (m *WeakImportMessage) XXX_Methods() *protoiface.Methods {
|
||||
return file_test_test_weak_proto_msgTypes[0].Methods()
|
||||
}
|
||||
|
||||
// Deprecated: Use WeakImportMessage.ProtoReflect.Type instead.
|
||||
func (*WeakImportMessage) Descriptor() ([]byte, []int) {
|
||||
return file_test_test_weak_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
var File_test_test_weak_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_test_test_weak_proto_rawDesc = []byte{
|
||||
0x0a, 0x14, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x77, 0x65, 0x61, 0x6b,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x22, 0x13, 0x0a, 0x11, 0x57, 0x65,
|
||||
0x61, 0x6b, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42,
|
||||
0x38, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f,
|
||||
0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x76, 0x32,
|
||||
0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x74, 0x65, 0x73, 0x74,
|
||||
}
|
||||
|
||||
var (
|
||||
file_test_test_weak_proto_rawDescOnce sync.Once
|
||||
file_test_test_weak_proto_rawDescData = file_test_test_weak_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_test_test_weak_proto_rawDescGZIP() []byte {
|
||||
file_test_test_weak_proto_rawDescOnce.Do(func() {
|
||||
file_test_test_weak_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_test_weak_proto_rawDescData)
|
||||
})
|
||||
return file_test_test_weak_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_test_test_weak_proto_msgTypes = make([]protoimpl.MessageType, 1)
|
||||
var file_test_test_weak_proto_goTypes = []interface{}{
|
||||
(*WeakImportMessage)(nil), // 0: goproto.proto.test.WeakImportMessage
|
||||
}
|
||||
var file_test_test_weak_proto_depIdxs = []int32{}
|
||||
|
||||
func init() { file_test_test_weak_proto_init() }
|
||||
func file_test_test_weak_proto_init() {
|
||||
if File_test_test_weak_proto != nil {
|
||||
return
|
||||
}
|
||||
File_test_test_weak_proto = protoimpl.FileBuilder{
|
||||
RawDescriptor: file_test_test_weak_proto_rawDesc,
|
||||
GoTypes: file_test_test_weak_proto_goTypes,
|
||||
DependencyIndexes: file_test_test_weak_proto_depIdxs,
|
||||
MessageOutputTypes: file_test_test_weak_proto_msgTypes,
|
||||
FilesRegistry: protoregistry.GlobalFiles,
|
||||
TypesRegistry: protoregistry.GlobalTypes,
|
||||
}.Init()
|
||||
file_test_test_weak_proto_rawDesc = nil
|
||||
file_test_test_weak_proto_goTypes = nil
|
||||
file_test_test_weak_proto_depIdxs = nil
|
||||
}
|
102
internal/testprotos/test/weak/test_weak.pb.go
Normal file
102
internal/testprotos/test/weak/test_weak.pb.go
Normal file
@ -0,0 +1,102 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: test/weak/test_weak.proto
|
||||
|
||||
package weak
|
||||
|
||||
import (
|
||||
protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
protoregistry "github.com/golang/protobuf/v2/reflect/protoregistry"
|
||||
protoiface "github.com/golang/protobuf/v2/runtime/protoiface"
|
||||
protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
|
||||
|
||||
type WeakImportMessage struct {
|
||||
A *int32 `protobuf:"varint,1,opt,name=a" json:"a,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized protoimpl.UnknownFields `json:"-"`
|
||||
XXX_sizecache protoimpl.SizeCache `json:"-"`
|
||||
}
|
||||
|
||||
func (x *WeakImportMessage) Reset() {
|
||||
*x = WeakImportMessage{}
|
||||
}
|
||||
|
||||
func (x *WeakImportMessage) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*WeakImportMessage) ProtoMessage() {}
|
||||
|
||||
func (x *WeakImportMessage) ProtoReflect() protoreflect.Message {
|
||||
return file_test_weak_test_weak_proto_msgTypes[0].MessageOf(x)
|
||||
}
|
||||
|
||||
func (m *WeakImportMessage) XXX_Methods() *protoiface.Methods {
|
||||
return file_test_weak_test_weak_proto_msgTypes[0].Methods()
|
||||
}
|
||||
|
||||
// Deprecated: Use WeakImportMessage.ProtoReflect.Type instead.
|
||||
func (*WeakImportMessage) Descriptor() ([]byte, []int) {
|
||||
return file_test_weak_test_weak_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *WeakImportMessage) GetA() int32 {
|
||||
if x != nil && x.A != nil {
|
||||
return *x.A
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var File_test_weak_test_weak_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_test_weak_test_weak_proto_rawDesc = []byte{
|
||||
0x0a, 0x19, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x77, 0x65, 0x61, 0x6b, 0x2f, 0x74, 0x65, 0x73, 0x74,
|
||||
0x5f, 0x77, 0x65, 0x61, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x67, 0x6f, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e,
|
||||
0x77, 0x65, 0x61, 0x6b, 0x22, 0x21, 0x0a, 0x11, 0x57, 0x65, 0x61, 0x6b, 0x49, 0x6d, 0x70, 0x6f,
|
||||
0x72, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0c, 0x0a, 0x01, 0x61, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x05, 0x52, 0x01, 0x61, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75,
|
||||
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x76, 0x32, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
|
||||
0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x74, 0x65, 0x73,
|
||||
0x74, 0x2f, 0x77, 0x65, 0x61, 0x6b,
|
||||
}
|
||||
|
||||
var (
|
||||
file_test_weak_test_weak_proto_rawDescOnce sync.Once
|
||||
file_test_weak_test_weak_proto_rawDescData = file_test_weak_test_weak_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_test_weak_test_weak_proto_rawDescGZIP() []byte {
|
||||
file_test_weak_test_weak_proto_rawDescOnce.Do(func() {
|
||||
file_test_weak_test_weak_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_weak_test_weak_proto_rawDescData)
|
||||
})
|
||||
return file_test_weak_test_weak_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_test_weak_test_weak_proto_msgTypes = make([]protoimpl.MessageType, 1)
|
||||
var file_test_weak_test_weak_proto_goTypes = []interface{}{
|
||||
(*WeakImportMessage)(nil), // 0: goproto.proto.test.weak.WeakImportMessage
|
||||
}
|
||||
var file_test_weak_test_weak_proto_depIdxs = []int32{}
|
||||
|
||||
func init() { file_test_weak_test_weak_proto_init() }
|
||||
func file_test_weak_test_weak_proto_init() {
|
||||
if File_test_weak_test_weak_proto != nil {
|
||||
return
|
||||
}
|
||||
File_test_weak_test_weak_proto = protoimpl.FileBuilder{
|
||||
RawDescriptor: file_test_weak_test_weak_proto_rawDesc,
|
||||
GoTypes: file_test_weak_test_weak_proto_goTypes,
|
||||
DependencyIndexes: file_test_weak_test_weak_proto_depIdxs,
|
||||
MessageOutputTypes: file_test_weak_test_weak_proto_msgTypes,
|
||||
FilesRegistry: protoregistry.GlobalFiles,
|
||||
TypesRegistry: protoregistry.GlobalTypes,
|
||||
}.Init()
|
||||
file_test_weak_test_weak_proto_rawDesc = nil
|
||||
file_test_weak_test_weak_proto_goTypes = nil
|
||||
file_test_weak_test_weak_proto_depIdxs = nil
|
||||
}
|
@ -4,9 +4,10 @@
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package goproto.proto.test;
|
||||
package goproto.proto.test.weak;
|
||||
|
||||
option go_package = "github.com/golang/protobuf/v2/internal/testprotos/test";
|
||||
option go_package = "github.com/golang/protobuf/v2/internal/testprotos/test/weak";
|
||||
|
||||
message WeakImportMessage {
|
||||
optional int32 a = 1;
|
||||
}
|
@ -26,9 +26,6 @@ func TestMessage(t testing.TB, message proto.Message) {
|
||||
for i := 0; i < md.Fields().Len(); i++ {
|
||||
fd := md.Fields().Get(i)
|
||||
switch {
|
||||
case fd.IsWeak():
|
||||
// TODO: Weak field support.
|
||||
continue
|
||||
case fd.IsMap():
|
||||
testFieldMap(t, m, fd)
|
||||
case fd.Cardinality() == pref.Repeated:
|
||||
|
@ -19,6 +19,7 @@ func Test(t *testing.T) {
|
||||
(*testpb.TestAllTypes)(nil),
|
||||
(*test3pb.TestAllTypes)(nil),
|
||||
(*testpb.TestRequired)(nil),
|
||||
(*testpb.TestWeak)(nil),
|
||||
} {
|
||||
t.Run(fmt.Sprintf("%T", m), func(t *testing.T) {
|
||||
prototest.TestMessage(t, m)
|
||||
|
Loading…
x
Reference in New Issue
Block a user