| // 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 ( |
| "fmt" |
| |
| "google.golang.org/protobuf/internal/filedesc" |
| "google.golang.org/protobuf/internal/genid" |
| "google.golang.org/protobuf/reflect/protoreflect" |
| "google.golang.org/protobuf/types/gofeaturespb" |
| ) |
| |
| func fileAPILevel(fd protoreflect.FileDescriptor, def gofeaturespb.GoFeatures_APILevel) gofeaturespb.GoFeatures_APILevel { |
| level := gofeaturespb.GoFeatures_API_OPEN |
| level = def |
| if fd, ok := fd.(*filedesc.File); ok { |
| al := fd.L1.EditionFeatures.APILevel |
| if al != genid.GoFeatures_API_LEVEL_UNSPECIFIED_enum_value { |
| level = gofeaturespb.GoFeatures_APILevel(al) |
| } |
| } |
| |
| return level |
| } |
| |
| func messageAPILevel(md protoreflect.MessageDescriptor, def gofeaturespb.GoFeatures_APILevel) gofeaturespb.GoFeatures_APILevel { |
| level := def |
| if md, ok := md.(*filedesc.Message); ok { |
| al := md.L1.EditionFeatures.APILevel |
| if al != genid.GoFeatures_API_LEVEL_UNSPECIFIED_enum_value { |
| level = gofeaturespb.GoFeatures_APILevel(al) |
| } |
| } |
| |
| return level |
| } |
| |
| func (p *Plugin) defaultAPILevel() gofeaturespb.GoFeatures_APILevel { |
| if p.opts.DefaultAPILevel != gofeaturespb.GoFeatures_API_LEVEL_UNSPECIFIED { |
| return p.opts.DefaultAPILevel |
| } |
| |
| return gofeaturespb.GoFeatures_API_OPEN |
| } |
| |
| // MethodName returns the (possibly mangled) name of the generated accessor |
| // method, along with the backwards-compatible name (if needed). |
| // |
| // method must be one of Get, Set, Has, Clear. MethodName panics otherwise. |
| func (field *Field) MethodName(method string) (name, compat string) { |
| switch method { |
| case "Get": |
| return field.getterName() |
| |
| case "Set": |
| return field.setterName() |
| |
| case "Has", "Clear": |
| return field.methodName(method), "" |
| |
| default: |
| panic(fmt.Sprintf("Field.MethodName called for unknown method %q", method)) |
| } |
| } |
| |
| // methodName returns the (possibly mangled) name of the generated method with |
| // the given prefix. |
| // |
| // For the Open API, the return value is "". |
| func (field *Field) methodName(prefix string) string { |
| switch field.Parent.APILevel { |
| case gofeaturespb.GoFeatures_API_OPEN: |
| // In the Open API, only generate getters (no Has or Clear methods). |
| return "" |
| |
| case gofeaturespb.GoFeatures_API_HYBRID: |
| var infix string |
| if field.hasConflictHybrid { |
| infix = "_" |
| } |
| return prefix + infix + field.camelCase |
| |
| case gofeaturespb.GoFeatures_API_OPAQUE: |
| return prefix + field.camelCase |
| |
| default: |
| panic("BUG: message is neither open, nor hybrid, nor opaque?!") |
| } |
| } |
| |
| // getterName returns the (possibly mangled) name of the generated Get method, |
| // along with the backwards-compatible name (if needed). |
| func (field *Field) getterName() (getter, compat string) { |
| switch field.Parent.APILevel { |
| case gofeaturespb.GoFeatures_API_OPEN: |
| // In the Open API, only generate a getter with the old style mangled name. |
| return "Get" + field.GoName, "" |
| |
| case gofeaturespb.GoFeatures_API_HYBRID: |
| // In the Hybrid API, return the mangled getter name and the old style |
| // name if needed, for backwards compatibility with the Open API. |
| var infix string |
| if field.hasConflictHybrid { |
| infix = "_" |
| } |
| orig := "Get" + infix + field.camelCase |
| mangled := "Get" + field.GoName |
| if mangled == orig { |
| mangled = "" |
| } |
| return orig, mangled |
| |
| case gofeaturespb.GoFeatures_API_OPAQUE: |
| return field.methodName("Get"), "" |
| |
| default: |
| panic("BUG: message is neither open, nor hybrid, nor opaque?!") |
| } |
| } |
| |
| // setterName returns the (possibly mangled) name of the generated Set method, |
| // along with the backwards-compatible name (if needed). |
| func (field *Field) setterName() (setter, compat string) { |
| return field.methodName("Set"), "" |
| } |
| |
| // BuilderFieldName returns the name of this field in the corresponding _builder |
| // struct. |
| func (field *Field) BuilderFieldName() string { |
| return field.camelCase |
| } |
| |
| // MethodName returns the (possibly mangled) name of the generated accessor |
| // method. |
| // |
| // method must be one of Has, Clear, Which. MethodName panics otherwise. |
| func (oneof *Oneof) MethodName(method string) string { |
| switch method { |
| case "Has", "Clear", "Which": |
| return oneof.methodName(method) |
| |
| default: |
| panic(fmt.Sprintf("Oneof.MethodName called for unknown method %q", method)) |
| } |
| } |
| |
| // methodName returns the (possibly mangled) name of the generated method with |
| // the given prefix. |
| // |
| // For the Open API, the return value is "". |
| func (oneof *Oneof) methodName(prefix string) string { |
| switch oneof.Parent.APILevel { |
| case gofeaturespb.GoFeatures_API_OPEN: |
| // In the Open API, only generate getters. |
| return "" |
| |
| case gofeaturespb.GoFeatures_API_HYBRID: |
| var infix string |
| if oneof.hasConflictHybrid { |
| infix = "_" |
| } |
| return prefix + infix + oneof.camelCase |
| |
| case gofeaturespb.GoFeatures_API_OPAQUE: |
| return prefix + oneof.camelCase |
| |
| default: |
| panic("BUG: message is neither open, nor hybrid, nor opaque?!") |
| } |
| } |