// 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 } } } }