Isolate generated ProtoMessage() methods in build-tagged files

This commit is contained in:
Jordan Liggitt
2025-10-01 13:56:47 -04:00
parent 5fb0e16be6
commit 6d8adfe402
5 changed files with 58 additions and 11 deletions

View File

@@ -145,6 +145,7 @@ function codegen::protobuf() {
git_find -z \
':(glob)**/generated.proto' \
':(glob)**/generated.pb.go' \
':(glob)**/generated.protomessage.pb.go' \
| xargs -0 rm -f
if kube::protoc::check_protoc >/dev/null; then

View File

@@ -320,8 +320,6 @@ type unbufferedMarshaller interface {
// unmarshaler is the subset of gogo Message and Unmarshaler used by unmarshal
type unmarshaler interface {
// Marker method, currently defined on all protoc-generated messages
ProtoMessage()
// Reset() is called on the top-level message before unmarshaling,
// and clears all existing data from the message instance.
Reset()

View File

@@ -279,6 +279,7 @@ func Run(g *Generator) {
path := filepath.Join(g.OutputDir, p.ImportPath())
outputPath := filepath.Join(g.OutputDir, p.OutputPath())
protomessageOutputPath := filepath.Join(g.OutputDir, p.ProtomessageOutputPath())
// generate the gogoprotobuf protoc
cmd := exec.Command("protoc", append(args, path)...)
@@ -295,12 +296,17 @@ func Run(g *Generator) {
// alter the generated protobuf file to remove the generated types (but leave the serializers) and rewrite the
// package statement to match the desired package name
if err := RewriteGeneratedGogoProtobufFile(outputPath, p.ExtractGeneratedType, p.OptionalTypeName, buf.Bytes(), g.DropGogoGo); err != nil {
if err := RewriteGeneratedGogoProtobufFile(outputPath, protomessageOutputPath, p.ExtractGeneratedType, p.OptionalTypeName, buf.Bytes(), g.DropGogoGo); err != nil {
log.Fatalf("Unable to rewrite generated %s: %v", outputPath, err)
}
outputPaths := []string{outputPath}
if g.DropGogoGo {
outputPaths = append(outputPaths, protomessageOutputPath)
}
// sort imports
cmd = exec.Command("goimports", "-w", outputPath)
cmd = exec.Command("goimports", append([]string{"-w"}, outputPaths...)...)
out, err = cmd.CombinedOutput()
if len(out) > 0 {
log.Print(string(out))
@@ -311,7 +317,7 @@ func Run(g *Generator) {
}
// format and simplify the generated file
cmd = exec.Command("gofmt", "-s", "-w", outputPath)
cmd = exec.Command("gofmt", append([]string{"-s", "-w"}, outputPaths...)...)
out, err = cmd.CombinedOutput()
if len(out) > 0 {
log.Print(string(out))

View File

@@ -80,7 +80,7 @@ type protobufPackage struct {
}
func (p *protobufPackage) Clean() error {
for _, s := range []string{p.ImportPath(), p.OutputPath()} {
for _, s := range []string{p.ImportPath(), p.OutputPath(), p.ProtomessageOutputPath()} {
if err := os.Remove(filepath.Join(p.Dir(), filepath.Base(s))); err != nil && !os.IsNotExist(err) {
return err
}
@@ -200,6 +200,10 @@ func (p *protobufPackage) OutputPath() string {
return filepath.Join(p.Path(), "generated.pb.go")
}
func (p *protobufPackage) ProtomessageOutputPath() string {
return filepath.Join(p.Path(), "generated.protomessage.pb.go")
}
var (
_ = generator.Target(&protobufPackage{})
)

View File

@@ -27,6 +27,7 @@ import (
"go/token"
"os"
"reflect"
"regexp"
"strings"
customreflect "k8s.io/code-generator/third_party/forked/golang/reflect"
@@ -77,8 +78,46 @@ type ExtractFunc func(*ast.TypeSpec) bool
// and should have its marshal functions adjusted to remove the 'Items' accessor.
type OptionalFunc func(name string) bool
func RewriteGeneratedGogoProtobufFile(name string, extractFn ExtractFunc, optionalFn OptionalFunc, header []byte, dropGogo bool) error {
return rewriteFile(name, header, func(fset *token.FileSet, file *ast.File) error {
func RewriteGeneratedGogoProtobufFile(file, protomessageFile string, extractFn ExtractFunc, optionalFn OptionalFunc, header []byte, dropGogo bool) error {
// Optionally extract ProtoMessage() marker methods to a separate build-tagged file
if dropGogo {
data, err := os.ReadFile(file)
if err != nil {
return err
}
packageRE := regexp.MustCompile(`^package .*`)
wrotePackage := false
protomessageFuncRE := regexp.MustCompile(`^func \(.*\) ProtoMessage\(\) \{\}$`)
b := bytes.NewBuffer(nil)
// add build tag
b.WriteString("//go:build kubernetes_protomessage_one_more_release\n")
b.WriteString("// +build kubernetes_protomessage_one_more_release\n\n")
// add boilerplate
b.Write(header)
b.WriteString("\n// Code generated by go-to-protobuf. DO NOT EDIT.\n\n")
for _, line := range bytes.Split(data, []byte("\n")) {
// copy package
if packageRE.Match(line) && !wrotePackage {
b.Write(line)
b.WriteString("\n\n")
wrotePackage = true
}
// copy empty ProtoMessage impls
if protomessageFuncRE.Match(line) {
b.Write(line)
b.WriteString("\n\n")
}
}
if err := os.WriteFile(protomessageFile, b.Bytes(), os.FileMode(0644)); err != nil {
return err
}
}
return rewriteFile(file, header, func(fset *token.FileSet, file *ast.File) error {
cmap := ast.NewCommentMap(fset, file, file.Comments)
// transform methods that point to optional maps or slices
@@ -172,9 +211,8 @@ var keepFuncs = map[string]bool{
"valueToStringGenerated": true,
// unmarshal
"Reset": true,
"ProtoMessage": true,
"Unmarshal": true,
"Reset": true,
"Unmarshal": true,
// marshal
"Size": true,