mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2024-12-26 21:24:22 +00:00
80 lines
2.7 KiB
Go
80 lines
2.7 KiB
Go
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
package protogen
|
||
|
|
||
|
import (
|
||
|
"google.golang.org/protobuf/internal/strs"
|
||
|
"google.golang.org/protobuf/reflect/protoreflect"
|
||
|
)
|
||
|
|
||
|
func opaqueNewFieldHook(desc protoreflect.FieldDescriptor, field *Field) {
|
||
|
field.camelCase = strs.GoCamelCase(string(desc.Name()))
|
||
|
}
|
||
|
|
||
|
func opaqueNewOneofHook(desc protoreflect.OneofDescriptor, oneof *Oneof) {
|
||
|
oneof.camelCase = strs.GoCamelCase(string(desc.Name()))
|
||
|
}
|
||
|
|
||
|
func opaqueNewMessageHook(message *Message) {
|
||
|
// New name mangling scheme: Add a '_' between method base
|
||
|
// name (Get, Set, Clear etc) and original field name if
|
||
|
// needed. As a special case, there is one globally reserved
|
||
|
// name, e.g. "Build" thet still results in actual renaming of
|
||
|
// the builder field like in the old scheme. We begin by
|
||
|
// taking care of this special case.
|
||
|
for _, field := range message.Fields {
|
||
|
if field.camelCase == "Build" {
|
||
|
field.camelCase += "_"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Then find all names of the original field names, we do not want the old scheme to affect
|
||
|
// how we name things.
|
||
|
|
||
|
camelCases := map[string]bool{}
|
||
|
for _, field := range message.Fields {
|
||
|
if field.Oneof != nil {
|
||
|
// We add the name of the union here (potentially many times).
|
||
|
camelCases[field.Oneof.camelCase] = true
|
||
|
}
|
||
|
// The member fields of the oneof are considered fields in the struct although
|
||
|
// they are not technically there. This is to allow changing a proto2 optional
|
||
|
// to a oneof with source code compatibility.
|
||
|
camelCases[field.camelCase] = true
|
||
|
|
||
|
}
|
||
|
// For each field, check if any of it's methods would clash with an original field name
|
||
|
for _, field := range message.Fields {
|
||
|
// Every field (except the union fields, that are taken care of separately) has
|
||
|
// a Get and a Set method.
|
||
|
methods := []string{"Set", "Get"}
|
||
|
// For explicit presence fields, we also have Has and Clear.
|
||
|
if field.Desc.HasPresence() {
|
||
|
methods = append(methods, "Has", "Clear")
|
||
|
}
|
||
|
for _, method := range methods {
|
||
|
// If any method name clashes with a field name, all methods get a
|
||
|
// "_" inserted between the operation and the field name.
|
||
|
if camelCases[method+field.camelCase] {
|
||
|
field.hasConflictHybrid = true
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// The union names for oneofs need only have a methods prefix if there is a clash with Has, Clear or Which in
|
||
|
// hybrid and opaque-v0.
|
||
|
for _, field := range message.Fields {
|
||
|
if field.Oneof == nil {
|
||
|
continue
|
||
|
}
|
||
|
for _, method := range []string{"Has", "Clear", "Which"} {
|
||
|
// Same logic as for regular fields - all methods get the "_" if one needs it.
|
||
|
if camelCases[method+field.Oneof.camelCase] {
|
||
|
field.Oneof.hasConflictHybrid = true
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|