Skip to content

Commit 8081512

Browse files
Andrew Braunsteindsymonds
authored andcommitted
Ensure all field and method names are unique.
This change forces the compiler to pick unique names when generating getters. If a name collision is found when generating a getter, it follows the same convention as fields do and appends an "_" to the end of the method name. Signed-off-by: David Symonds <[email protected]>
1 parent 0c959e8 commit 8081512

File tree

4 files changed

+54
-16
lines changed

4 files changed

+54
-16
lines changed

protoc-gen-go/generator/generator.go

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,18 +1607,36 @@ func (g *Generator) generateMessage(message *Descriptor) {
16071607
g.P("type ", ccTypeName, " struct {")
16081608
g.In()
16091609

1610-
allocName := func(basis string) string {
1611-
n := CamelCase(basis)
1612-
for usedNames[n] {
1613-
n += "_"
1610+
// allocNames finds a conflict-free variation of the given strings,
1611+
// consistently mutating their suffixes.
1612+
// It returns the same number of strings.
1613+
allocNames := func(ns ...string) []string {
1614+
Loop:
1615+
for {
1616+
for _, n := range ns {
1617+
if usedNames[n] {
1618+
for i := range ns {
1619+
ns[i] += "_"
1620+
}
1621+
continue Loop
1622+
}
1623+
}
1624+
for _, n := range ns {
1625+
usedNames[n] = true
1626+
}
1627+
return ns
16141628
}
1615-
usedNames[n] = true
1616-
return n
16171629
}
16181630

16191631
for i, field := range message.Field {
1620-
fieldName := allocName(*field.Name)
1621-
fieldGetterName := fieldName
1632+
// Allocate the getter and the field at the same time so name
1633+
// collisions create field/method consistent names.
1634+
// TODO: This allocation occurs based on the order of the fields
1635+
// in the proto file, meaning that a change in the field
1636+
// ordering can change generated Method/Field names.
1637+
base := CamelCase(*field.Name)
1638+
ns := allocNames(base, "Get"+base)
1639+
fieldName, fieldGetterName := ns[0], ns[1]
16221640
typename, wiretype := g.GoType(message, field)
16231641
jsonName := *field.Name
16241642
tag := fmt.Sprintf("protobuf:%s json:%q", g.goTag(message, field, wiretype), jsonName+",omitempty")
@@ -1629,7 +1647,7 @@ func (g *Generator) generateMessage(message *Descriptor) {
16291647
oneof := field.OneofIndex != nil
16301648
if oneof && oneofFieldName[*field.OneofIndex] == "" {
16311649
odp := message.OneofDecl[int(*field.OneofIndex)]
1632-
fname := allocName(odp.GetName())
1650+
fname := allocNames(CamelCase(odp.GetName()))[0]
16331651

16341652
// This is the first field of a oneof we haven't seen before.
16351653
// Generate the union field.
@@ -1907,7 +1925,7 @@ func (g *Generator) generateMessage(message *Descriptor) {
19071925
if t, ok := mapFieldTypes[field]; ok {
19081926
typename = t
19091927
}
1910-
mname := "Get" + fieldGetterNames[field]
1928+
mname := fieldGetterNames[field]
19111929
star := ""
19121930
if needsStar(*field.Type) && typename[0] == '*' {
19131931
typename = typename[1:]

protoc-gen-go/testdata/my_test/test.pb.go

Lines changed: 12 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

protoc-gen-go/testdata/my_test/test.pb.go.golden

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,11 @@ type Request struct {
184184
// This is a map field. It will generate map[int32]string.
185185
NameMapping map[int32]string `protobuf:"bytes,14,rep,name=name_mapping" json:"name_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
186186
// This is a map field whose value type is a message.
187-
MsgMapping map[int64]*Reply `protobuf:"bytes,15,rep,name=msg_mapping" json:"msg_mapping,omitempty" protobuf_key:"zigzag64,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
188-
Reset_ *int32 `protobuf:"varint,12,opt,name=reset" json:"reset,omitempty"`
189-
XXX_unrecognized []byte `json:"-"`
187+
MsgMapping map[int64]*Reply `protobuf:"bytes,15,rep,name=msg_mapping" json:"msg_mapping,omitempty" protobuf_key:"zigzag64,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
188+
Reset_ *int32 `protobuf:"varint,12,opt,name=reset" json:"reset,omitempty"`
189+
// This field should not conflict with any getters.
190+
GetKey_ *string `protobuf:"bytes,16,opt,name=get_key" json:"get_key,omitempty"`
191+
XXX_unrecognized []byte `json:"-"`
190192
}
191193

192194
func (m *Request) Reset() { *m = Request{} }
@@ -253,6 +255,13 @@ func (m *Request) GetReset_() int32 {
253255
return 0
254256
}
255257

258+
func (m *Request) GetGetKey_() string {
259+
if m != nil && m.GetKey_ != nil {
260+
return *m.GetKey_
261+
}
262+
return ""
263+
}
264+
256265
type Request_SomeGroup struct {
257266
GroupField *int32 `protobuf:"varint,9,opt,name=group_field" json:"group_field,omitempty"`
258267
XXX_unrecognized []byte `json:"-"`

protoc-gen-go/testdata/my_test/test.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ message Request {
8181
map<sint64, Reply> msg_mapping = 15;
8282

8383
optional int32 reset = 12;
84+
// This field should not conflict with any getters.
85+
optional string get_key = 16;
8486
}
8587

8688
message Reply {

0 commit comments

Comments
 (0)