No public description
PiperOrigin-RevId: 799008780
Change-Id: I275c7c9605c0b42d586a4f2a8516849a536ea90a
diff --git a/internal/fix/build.go b/internal/fix/build.go
index 0363547..338b8bf 100644
--- a/internal/fix/build.go
+++ b/internal/fix/build.go
@@ -197,29 +197,8 @@
continue
}
- // Don't rewrite the oneof in
- //
- // &pb.M2{OneofField: &pb.M2_MsgOneof{}}
- // &pb.M2{OneofField: &pb.M2_EnumOneof{}}
- //
- // It's a tricky case and should be very rare because "oneof
- // with a type but without a value" is not a valid protocol buffers
- // concept.
- //
- // It happens due to a mismatch between what's allowed in protocol buffers
- // and the Go structs representing protocol buffers in the open API.
- // This information will not be marshalled to the wire and the field
- // is effectively discarded during marshalling when it does not have
- // a value.
- //
- // The opaque API does not allow this. While the struct can technically
- // represent this, you cannot use the API to bring the struct into
- // this state.
- //
- // For enums: this should be rare and we don't want to guess the default
- // value.
- if fieldValue == nil && !isBasic(fieldType) {
- c.Logf("returning: RHS is nil of Type %T (looking for types.Basic)", fieldType)
+ if fieldValue == nil && !isBasic(fieldType) && !isPtr(fieldType) && !isEnum(fieldType) {
+ c.Logf("returning: RHS is nil of Type %T (looking for types.Basic or types.Pointer)", fieldType)
return false
}
@@ -235,11 +214,27 @@
unsafeRewrite = true
}
- // Handle `M{Oneof: OneofBasicField{}}`
+ // Handle `M{Oneof: OneofBasicField{}}`, `M{Oneof: OneofMsgField{}}` or
+ // `M{Oneof: OneofEnumField{}}`
if fieldValue == nil {
updates = append(updates, func() {
kv.Key.(*dst.Ident).Name = fieldName // Rename the key to field name from the oneof wrapper.
- kv.Value = c.newProtoHelperCall(nil, types.Unalias(fieldType).(*types.Basic))
+ if isBasic(fieldType) {
+ kv.Value = c.newProtoHelperCall(nil, types.Unalias(fieldType).(*types.Basic))
+ } else if isPtr(fieldType) {
+ lit := &dst.CompositeLit{
+ Type: c.selectorForProtoMessageType(fieldType),
+ }
+ c.setType(lit, fieldType)
+ kv.Value = &dst.UnaryExpr{
+ Op: token.AND,
+ X: lit,
+ }
+ c.setType(kv.Value, fieldType)
+ } else { /* must be isEnum(fieldType) */
+ kv.Value = &dst.Ident{Name: "0"}
+ c.setType(kv.Value, types.Typ[types.Invalid])
+ }
})
c.Logf("generated RHS for field %v", fieldName)
continue
diff --git a/internal/fix/build_test.go b/internal/fix/build_test.go
index 6844641..47dd165 100644
--- a/internal/fix/build_test.go
+++ b/internal/fix/build_test.go
@@ -451,6 +451,7 @@
_ = pb2.M2_builder{
// comment before
BytesOneof:/*comment1*/ m2.GetBytesOneof(), // eol comment
+ EmptyOneof: m2.GetEmptyOneof(),
EnumOneof: proto.ValueOrNil(m2.HasEnumOneof(), m2.GetEnumOneof),
IntOneof: proto.ValueOrNil(m2.HasIntOneof(), m2.GetIntOneof),
MsgOneof: m2.GetMsgOneof(),
@@ -461,6 +462,7 @@
_ = pb2.M2_builder{
// comment before
BytesOneof:/*comment1*/ m2.GetBytesOneof(), // eol comment
+ EmptyOneof: m2.GetEmptyOneof(),
EnumOneof: proto.ValueOrNil(m2.HasEnumOneof(), m2.GetEnumOneof),
IntOneof: proto.ValueOrNil(m2.HasIntOneof(), m2.GetIntOneof),
MsgOneof: m2.GetMsgOneof(),
@@ -522,6 +524,7 @@
_ = pb2.M2_builder{
S: proto.String("42"),
BytesOneof: m2.GetBytesOneof(),
+ EmptyOneof: m2.GetEmptyOneof(),
EnumOneof: proto.ValueOrNil(m2.HasEnumOneof(), m2.GetEnumOneof),
IntOneof: proto.ValueOrNil(m2.HasIntOneof(), m2.GetIntOneof),
MsgOneof: m2.GetMsgOneof(),
@@ -543,6 +546,7 @@
_ = pb2.M2_builder{
S: proto.String("42"),
BytesOneof: m2.GetBytesOneof(),
+ EmptyOneof: m2.GetEmptyOneof(),
EnumOneof: proto.ValueOrNil(m2.HasEnumOneof(), m2.GetEnumOneof),
IntOneof: proto.ValueOrNil(m2.HasIntOneof(), m2.GetIntOneof),
MsgOneof: m2.GetMsgOneof(),
@@ -570,26 +574,29 @@
desc: "oneofs: msg zero value",
in: `
_ = &pb2.M2{OneofField: &pb2.M2_MsgOneof{}}
+_ = &pb2.M2{OneofField: &pb2.M2_EmptyOneof{}}
`,
want: map[Level]string{
Green: `
_ = &pb2.M2{OneofField: &pb2.M2_MsgOneof{}}
+_ = &pb2.M2{OneofField: &pb2.M2_EmptyOneof{}}
`,
Red: `
-_ = pb2.M2_builder{OneofField: &pb2.M2_MsgOneof{}}.Build()
+_ = pb2.M2_builder{MsgOneof: &pb2.M2{}}.Build()
+_ = pb2.M2_builder{EmptyOneof: &xpb.Empty{}}.Build()
`,
},
}, {
- desc: "oneofs: enum zero value", // no rewrite (see comments in rules.go)
+ desc: "oneofs: enum zero value",
in: `
_ = &pb2.M2{OneofField: &pb2.M2_EnumOneof{}}
`,
want: map[Level]string{
Green: `
-_ = &pb2.M2{OneofField: &pb2.M2_EnumOneof{}}
+_ = pb2.M2_builder{EnumOneof: 0}.Build()
`,
Red: `
-_ = pb2.M2_builder{OneofField: &pb2.M2_EnumOneof{}}.Build()
+_ = pb2.M2_builder{EnumOneof: 0}.Build()
`,
},
}, {
@@ -617,10 +624,10 @@
want: map[Level]string{
Green: `
msg := &pb2.M2{}
-_ = &pb2.M2{
- OneofField: &pb2.M2_StringOneof{"hello"},
- OneofField2: &pb2.M2_EnumOneof2{},
-}
+_ = pb2.M2_builder{
+ StringOneof: proto.String("hello"),
+ EnumOneof2: 0,
+}.Build()
_ = &pb2.M2{
OneofField: &pb2.M2_StringOneof{"hello"},
OneofField2: &pb2.M2_MsgOneof2{msg},
@@ -636,18 +643,18 @@
`,
Yellow: `
msg := &pb2.M2{}
-_ = &pb2.M2{
- OneofField: &pb2.M2_StringOneof{"hello"},
- OneofField2: &pb2.M2_EnumOneof2{},
-}
+_ = pb2.M2_builder{
+ StringOneof: proto.String("hello"),
+ EnumOneof2: 0,
+}.Build()
_ = pb2.M2_builder{
StringOneof: proto.String("hello"),
MsgOneof2: proto.ValueOrDefault(msg),
}.Build()
-_ = &pb2.M2{
- OneofField: &pb2.M2_StringOneof{"hello"},
- OneofField2: &pb2.M2_MsgOneof2{},
-}
+_ = pb2.M2_builder{
+ StringOneof: proto.String("hello"),
+ MsgOneof2: &pb2.M2{},
+}.Build()
_ = &pb2.M2{
OneofField: &pb2.M2_StringOneof{"hello"},
OneofField2: F(),
diff --git a/internal/fix/fix.go b/internal/fix/fix.go
index 17256b5..1855a89 100644
--- a/internal/fix/fix.go
+++ b/internal/fix/fix.go
@@ -411,6 +411,9 @@
for _, imp := range c.imports.importsToAdd {
cur.InsertAfter(imp)
c.setType(imp.Path, types.Typ[types.Invalid])
+ if imp.Name != nil {
+ c.setType(imp.Name, types.Typ[types.Invalid])
+ }
}
return false // import added, abort traversal
})
diff --git a/internal/fix/testdata/proto2test_go_proto/proto2test.proto b/internal/fix/testdata/proto2test_go_proto/proto2test.proto
index e4c93d3..08a280d 100644
--- a/internal/fix/testdata/proto2test_go_proto/proto2test.proto
+++ b/internal/fix/testdata/proto2test_go_proto/proto2test.proto
@@ -7,6 +7,7 @@
package net.proto2.go.open2opaque.o2o.test;
import "google/protobuf/go_features.proto";
+import "google/protobuf/empty.proto";
message DoNotMigrateMe {
option features.(pb.go).api_level = API_OPEN;
@@ -40,6 +41,7 @@
M2 msg_oneof = 16;
Enum enum_oneof = 17;
bytes bytes_oneof = 18;
+ google.protobuf.Empty empty_oneof = 99;
}
oneof oneof_field2 {
string string_oneof2 = 19;