protobuf-go/compiler/protogen/protogen_apilevel.go
Michael Stapelberg eb7b468655 all: Release the Opaque API
For golang/protobuf#1657

Change-Id: I7b2b0c30506706015ce278e6054439c9ad9ef727
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/634815
TryBot-Bypass: Michael Stapelberg <stapelberg@google.com>
Reviewed-by: Joseph Tsai <joetsai@digital-static.net>
Reviewed-by: Damien Neil <dneil@google.com>
2024-12-11 03:16:51 -08:00

193 lines
5.3 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 (
"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) {
// TODO(b/359846588): remove weak field support?
if field.Desc.IsWeak() && field.Parent.APILevel != gofeaturespb.GoFeatures_API_OPAQUE {
switch field.Parent.APILevel {
case gofeaturespb.GoFeatures_API_OPEN:
return "Set" + field.GoName, ""
default:
var infix string
if field.hasConflictHybrid {
infix = "_"
}
orig := "Set" + infix + field.camelCase
mangled := "Set" + field.GoName
if mangled == orig {
mangled = ""
}
return orig, mangled
}
}
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?!")
}
}