compiler/protogen: move name mangling logic to protogen
The name mangling logic should be unified in a single place
rather than being split between compiler/protogen and cmd/protoc-gen-go.
Move it over compiler/protogen.
Change-Id: Iea65e0b3fba45e0c95c76e3fc1f061e0fa8f84d7
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/191117
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/compiler/protogen/protogen.go b/compiler/protogen/protogen.go
index 0620d3a..ec03704 100644
--- a/compiler/protogen/protogen.go
+++ b/compiler/protogen/protogen.go
@@ -556,7 +556,7 @@
// A top-level enum value's name is: EnumName_ValueName
// An enum value contained in a message is: MessageName_ValueName
//
- // Enum value names are not camelcased.
+ // For historical reasons, enum value names are not camel-cased.
parentIdent := enum.GoIdent
if message != nil {
parentIdent = message.GoIdent
@@ -661,15 +661,39 @@
usedNames["Get"+name] = hasGetter
return name
}
- seenOneofs := make(map[int]bool)
for _, field := range message.Fields {
field.GoName = makeNameUnique(field.GoName, true)
+ field.GoIdent.GoName = message.GoIdent.GoName + "_" + field.GoName
+ if field.Oneof != nil && field.Oneof.Fields[0] == field {
+ // Make the name for a oneof unique as well. For historical reasons,
+ // this assumes that a getter method is not generated for oneofs.
+ // This is incorrect, but fixing it breaks existing code.
+ field.Oneof.GoName = makeNameUnique(field.Oneof.GoName, false)
+ field.Oneof.GoIdent.GoName = message.GoIdent.GoName + "_" + field.Oneof.GoName
+ }
+ }
+
+ // Oneof field name conflict resolution.
+ //
+ // This conflict resolution is incomplete as it does not consider collisions
+ // with other oneof field types, but fixing it breaks existing code.
+ for _, field := range message.Fields {
if field.Oneof != nil {
- if !seenOneofs[field.Oneof.Desc.Index()] {
- // If this is a field in a oneof that we haven't seen before,
- // make the name for that oneof unique as well.
- field.Oneof.GoName = makeNameUnique(field.Oneof.GoName, false)
- seenOneofs[field.Oneof.Desc.Index()] = true
+ Loop:
+ for {
+ for _, nestedMessage := range message.Messages {
+ if nestedMessage.GoIdent == field.GoIdent {
+ field.GoIdent.GoName += "_"
+ continue Loop
+ }
+ }
+ for _, nestedEnum := range message.Enums {
+ if nestedEnum.GoIdent == field.GoIdent {
+ field.GoIdent.GoName += "_"
+ continue Loop
+ }
+ }
+ break Loop
}
}
}
@@ -703,7 +727,13 @@
// GoName is the base name of this field's Go field and methods.
// For code generated by protoc-gen-go, this means a field named
// '{{GoName}}' and a getter method named 'Get{{GoName}}'.
- GoName string
+ GoName string // e.g., "FieldName"
+
+ // GoIdent is the base name of a top-level declaration for this field.
+ // For code generated by protoc-gen-go, this means a wrapper type named
+ // '{{GoIdent}}' for members fields of a oneof, and a variable named
+ // 'E_{{GoIdent}}' for extension fields.
+ GoIdent GoIdent // e.g., "MessageName_FieldName"
Parent *Message // message in which this field is declared; nil if top-level extension
Oneof *Oneof // containing oneof; nil if not part of a oneof
@@ -726,9 +756,18 @@
default:
loc = message.Location.appendPath(fieldnum.DescriptorProto_Field, int32(desc.Index()))
}
+ camelCased := camelCase(string(desc.Name()))
+ var parentPrefix string
+ if message != nil {
+ parentPrefix = message.GoIdent.GoName + "_"
+ }
field := &Field{
- Desc: desc,
- GoName: camelCase(string(desc.Name())),
+ Desc: desc,
+ GoName: camelCased,
+ GoIdent: GoIdent{
+ GoImportPath: f.GoImportPath,
+ GoName: parentPrefix + camelCased,
+ },
Parent: message,
Location: loc,
Comments: f.comments[newPathKey(loc.Path)],
@@ -769,7 +808,13 @@
type Oneof struct {
Desc protoreflect.OneofDescriptor
- GoName string // Go field name of this oneof
+ // GoName is the base name of this oneof's Go field and methods.
+ // For code generated by protoc-gen-go, this means a field named
+ // '{{GoName}}' and a getter method named 'Get{{GoName}}'.
+ GoName string // e.g., "OneofName"
+
+ // GoIdent is the base name of a top-level declaration for this oneof.
+ GoIdent GoIdent // e.g., "MessageName_OneofName"
Parent *Message // message in which this oneof is declared
@@ -781,10 +826,16 @@
func newOneof(gen *Plugin, f *File, message *Message, desc protoreflect.OneofDescriptor) *Oneof {
loc := message.Location.appendPath(fieldnum.DescriptorProto_OneofDecl, int32(desc.Index()))
+ camelCased := camelCase(string(desc.Name()))
+ parentPrefix := message.GoIdent.GoName + "_"
return &Oneof{
- Desc: desc,
- Parent: message,
- GoName: camelCase(string(desc.Name())),
+ Desc: desc,
+ Parent: message,
+ GoName: camelCased,
+ GoIdent: GoIdent{
+ GoImportPath: f.GoImportPath,
+ GoName: parentPrefix + camelCased,
+ },
Location: loc,
Comments: f.comments[newPathKey(loc.Path)],
}