cmd/protoc-gen-go: factor out oneof field naming

A oneof is represented by a single struct field of interface type.
Pull out the decision of what to name that field into a separate
function.

The function is trivial (return oneof.GoName), but factoring out the
field name like this makes it a bit easier to experiment with changes to
the oneof implementation in the future.

Change-Id: I1114b68c85cb6608852fa1c6bf4103ff58fd5de6
Reviewed-on: https://go-review.googlesource.com/c/146397
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/cmd/protoc-gen-go/internal_gengo/oneof.go b/cmd/protoc-gen-go/internal_gengo/oneof.go
index 26ad1c5..eb22a2f 100644
--- a/cmd/protoc-gen-go/internal_gengo/oneof.go
+++ b/cmd/protoc-gen-go/internal_gengo/oneof.go
@@ -18,13 +18,13 @@
 	if g.PrintLeadingComments(oneof.Location) {
 		g.P("//")
 	}
-	g.P("// Types that are valid to be assigned to ", oneof.GoName, ":")
+	g.P("// Types that are valid to be assigned to ", oneofFieldName(oneof), ":")
 	for _, field := range oneof.Fields {
 		g.PrintLeadingComments(field.Location)
 		g.P("//\t*", fieldOneofType(field))
 	}
-	g.Annotate(message.GoIdent.GoName+"."+oneof.GoName, oneof.Location)
-	g.P(oneof.GoName, " ", oneofInterfaceName(message, oneof), " `protobuf_oneof:\"", oneof.Desc.Name(), "\"`")
+	g.Annotate(message.GoIdent.GoName+"."+oneofFieldName(oneof), oneof.Location)
+	g.P(oneofFieldName(oneof), " ", oneofInterfaceName(oneof), " `protobuf_oneof:\"", oneof.Desc.Name(), "\"`")
 }
 
 // genOneofTypes generates the interface type used for a oneof field,
@@ -33,7 +33,7 @@
 // It also generates the getter method for the parent oneof field
 // (but not the member fields).
 func genOneofTypes(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message, oneof *protogen.Oneof) {
-	ifName := oneofInterfaceName(message, oneof)
+	ifName := oneofInterfaceName(oneof)
 	g.P("type ", ifName, " interface {")
 	g.P(ifName, "()")
 	g.P("}")
@@ -58,15 +58,25 @@
 	g.Annotate(message.GoIdent.GoName+".Get"+oneof.GoName, oneof.Location)
 	g.P("func (m *", message.GoIdent.GoName, ") Get", oneof.GoName, "() ", ifName, " {")
 	g.P("if m != nil {")
-	g.P("return m.", oneof.GoName)
+	g.P("return m.", oneofFieldName(oneof))
 	g.P("}")
 	g.P("return nil")
 	g.P("}")
 	g.P()
 }
 
-func oneofInterfaceName(message *protogen.Message, oneof *protogen.Oneof) string {
-	return fmt.Sprintf("is%s_%s", message.GoIdent.GoName, oneof.GoName)
+// oneofFieldName returns the name of the struct field holding the oneof value.
+//
+// This function is trivial, but pulling out the name like this makes it easier
+// to experiment with alternative oneof implementations.
+func oneofFieldName(oneof *protogen.Oneof) string {
+	return oneof.GoName
+}
+
+// oneofInterfaceName returns the name of the interface type implemented by
+// the oneof field value types.
+func oneofInterfaceName(oneof *protogen.Oneof) string {
+	return fmt.Sprintf("is%s_%s", oneof.ParentMessage.GoIdent.GoName, oneof.GoName)
 }
 
 // genOneofFuncs generates the XXX_OneofFuncs method for a message.
@@ -104,7 +114,7 @@
 	g.P("m := msg.(*", message.GoIdent, ")")
 	for _, oneof := range message.Oneofs {
 		g.P("// ", oneof.Desc.Name())
-		g.P("switch x := m.", oneof.GoName, ".(type) {")
+		g.P("switch x := m.", oneofFieldName(oneof), ".(type) {")
 		for _, field := range oneof.Fields {
 			genOneofFieldMarshal(g, field)
 		}
@@ -113,7 +123,7 @@
 		g.P("return ", protogen.GoIdent{
 			GoImportPath: "fmt",
 			GoName:       "Errorf",
-		}, `("`, message.GoIdent.GoName, ".", oneof.GoName, ` has unexpected type %T", x)`)
+		}, `("`, message.GoIdent.GoName, ".", oneofFieldName(oneof), ` has unexpected type %T", x)`)
 		g.P("}")
 	}
 	g.P("return nil")
@@ -140,7 +150,7 @@
 	g.P("m := msg.(*", message.GoIdent, ")")
 	for _, oneof := range message.Oneofs {
 		g.P("// ", oneof.Desc.Name())
-		g.P("switch x := m.", oneof.GoName, ".(type) {")
+		g.P("switch x := m.", oneofFieldName(oneof), ".(type) {")
 		for _, field := range oneof.Fields {
 			genOneofFieldSizer(g, field)
 		}
@@ -238,11 +248,11 @@
 	case protoreflect.BoolKind:
 		checkTag("WireVarint")
 		g.P("x, err := b.DecodeVarint()")
-		g.P("m.", oneof.GoName, " = &", fieldOneofType(field), "{x != 0}")
+		g.P("m.", oneofFieldName(oneof), " = &", fieldOneofType(field), "{x != 0}")
 	case protoreflect.EnumKind:
 		checkTag("WireVarint")
 		g.P("x, err := b.DecodeVarint()")
-		g.P("m.", oneof.GoName, " = &", fieldOneofType(field), "{", field.EnumType.GoIdent, "(x)}")
+		g.P("m.", oneofFieldName(oneof), " = &", fieldOneofType(field), "{", field.EnumType.GoIdent, "(x)}")
 	case protoreflect.Int32Kind, protoreflect.Uint32Kind, protoreflect.Int64Kind, protoreflect.Uint64Kind:
 		checkTag("WireVarint")
 		g.P("x, err := b.DecodeVarint()")
@@ -250,63 +260,63 @@
 		if goType, _ := fieldGoType(g, field); goType != "uint64" {
 			x = goType + "(x)"
 		}
-		g.P("m.", oneof.GoName, " = &", fieldOneofType(field), "{", x, "}")
+		g.P("m.", oneofFieldName(oneof), " = &", fieldOneofType(field), "{", x, "}")
 	case protoreflect.Sint32Kind:
 		checkTag("WireVarint")
 		g.P("x, err := b.DecodeZigzag32()")
-		g.P("m.", oneof.GoName, " = &", fieldOneofType(field), "{int32(x)}")
+		g.P("m.", oneofFieldName(oneof), " = &", fieldOneofType(field), "{int32(x)}")
 	case protoreflect.Sint64Kind:
 		checkTag("WireVarint")
 		g.P("x, err := b.DecodeZigzag64()")
-		g.P("m.", oneof.GoName, " = &", fieldOneofType(field), "{int64(x)}")
+		g.P("m.", oneofFieldName(oneof), " = &", fieldOneofType(field), "{int64(x)}")
 	case protoreflect.Sfixed32Kind:
 		checkTag("WireFixed32")
 		g.P("x, err := b.DecodeFixed32()")
-		g.P("m.", oneof.GoName, " = &", fieldOneofType(field), "{int32(x)}")
+		g.P("m.", oneofFieldName(oneof), " = &", fieldOneofType(field), "{int32(x)}")
 	case protoreflect.Fixed32Kind:
 		checkTag("WireFixed32")
 		g.P("x, err := b.DecodeFixed32()")
-		g.P("m.", oneof.GoName, " = &", fieldOneofType(field), "{uint32(x)}")
+		g.P("m.", oneofFieldName(oneof), " = &", fieldOneofType(field), "{uint32(x)}")
 	case protoreflect.FloatKind:
 		checkTag("WireFixed32")
 		g.P("x, err := b.DecodeFixed32()")
-		g.P("m.", oneof.GoName, " = &", fieldOneofType(field), "{", protogen.GoIdent{
+		g.P("m.", oneofFieldName(oneof), " = &", fieldOneofType(field), "{", protogen.GoIdent{
 			GoImportPath: "math",
 			GoName:       "Float32frombits",
 		}, "(uint32(x))}")
 	case protoreflect.Sfixed64Kind:
 		checkTag("WireFixed64")
 		g.P("x, err := b.DecodeFixed64()")
-		g.P("m.", oneof.GoName, " = &", fieldOneofType(field), "{int64(x)}")
+		g.P("m.", oneofFieldName(oneof), " = &", fieldOneofType(field), "{int64(x)}")
 	case protoreflect.Fixed64Kind:
 		checkTag("WireFixed64")
 		g.P("x, err := b.DecodeFixed64()")
-		g.P("m.", oneof.GoName, " = &", fieldOneofType(field), "{x}")
+		g.P("m.", oneofFieldName(oneof), " = &", fieldOneofType(field), "{x}")
 	case protoreflect.DoubleKind:
 		checkTag("WireFixed64")
 		g.P("x, err := b.DecodeFixed64()")
-		g.P("m.", oneof.GoName, " = &", fieldOneofType(field), "{", protogen.GoIdent{
+		g.P("m.", oneofFieldName(oneof), " = &", fieldOneofType(field), "{", protogen.GoIdent{
 			GoImportPath: "math",
 			GoName:       "Float64frombits",
 		}, "(x)}")
 	case protoreflect.StringKind:
 		checkTag("WireBytes")
 		g.P("x, err := b.DecodeStringBytes()")
-		g.P("m.", oneof.GoName, " = &", fieldOneofType(field), "{x}")
+		g.P("m.", oneofFieldName(oneof), " = &", fieldOneofType(field), "{x}")
 	case protoreflect.BytesKind:
 		checkTag("WireBytes")
 		g.P("x, err := b.DecodeRawBytes(true)")
-		g.P("m.", oneof.GoName, " = &", fieldOneofType(field), "{x}")
+		g.P("m.", oneofFieldName(oneof), " = &", fieldOneofType(field), "{x}")
 	case protoreflect.MessageKind:
 		checkTag("WireBytes")
 		g.P("msg := new(", field.MessageType.GoIdent, ")")
 		g.P("err := b.DecodeMessage(msg)")
-		g.P("m.", oneof.GoName, " = &", fieldOneofType(field), "{msg}")
+		g.P("m.", oneofFieldName(oneof), " = &", fieldOneofType(field), "{msg}")
 	case protoreflect.GroupKind:
 		checkTag("WireStartGroup")
 		g.P("msg := new(", field.MessageType.GoIdent, ")")
 		g.P("err := b.DecodeGroup(msg)")
-		g.P("m.", oneof.GoName, " = &", fieldOneofType(field), "{msg}")
+		g.P("m.", oneofFieldName(oneof), " = &", fieldOneofType(field), "{msg}")
 	}
 	g.P("return true, err")
 }