mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 09:22:44 +00:00
Refactor assmebling proto files to avoid code duplication
This commit is contained in:
parent
e5748a44d6
commit
0db2012039
@ -91,7 +91,7 @@ func Packages(_ *generator.Context, arguments *args.GeneratorArgs) generator.Pac
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// Also, filter out private types.
|
// Also, filter out private types.
|
||||||
if strings.ToLower(t.Name.Name[:1]) == t.Name.Name[:1] {
|
if namer.IsPrivateGoName(t.Name.Name) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -164,7 +164,7 @@ func (g *genDeepCopy) copyableWithinPackage(t *types.Type) bool {
|
|||||||
// We won't be able to access private fields.
|
// We won't be able to access private fields.
|
||||||
// Thus, this type cannot have private fields.
|
// Thus, this type cannot have private fields.
|
||||||
for _, member := range t.Members {
|
for _, member := range t.Members {
|
||||||
if strings.ToLower(member.Name[:1]) == member.Name[:1] {
|
if namer.IsPrivateGoName(member.Name) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// TODO: This is a temporary hack, to make avoid generating function
|
// TODO: This is a temporary hack, to make avoid generating function
|
||||||
|
@ -57,9 +57,12 @@ func (c *Context) ExecutePackages(outDir string, packages Packages) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type golangFileType struct{}
|
type DefaultFileType struct {
|
||||||
|
Format func([]byte) ([]byte, error)
|
||||||
|
Assemble func(io.Writer, *File)
|
||||||
|
}
|
||||||
|
|
||||||
func (ft golangFileType) AssembleFile(f *File, pathname string) error {
|
func (ft DefaultFileType) AssembleFile(f *File, pathname string) error {
|
||||||
log.Printf("Assembling file %q", pathname)
|
log.Printf("Assembling file %q", pathname)
|
||||||
destFile, err := os.Create(pathname)
|
destFile, err := os.Create(pathname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -69,12 +72,12 @@ func (ft golangFileType) AssembleFile(f *File, pathname string) error {
|
|||||||
|
|
||||||
b := &bytes.Buffer{}
|
b := &bytes.Buffer{}
|
||||||
et := NewErrorTracker(b)
|
et := NewErrorTracker(b)
|
||||||
ft.assemble(et, f)
|
ft.Assemble(et, f)
|
||||||
if et.Error() != nil {
|
if et.Error() != nil {
|
||||||
return et.Error()
|
return et.Error()
|
||||||
}
|
}
|
||||||
if formatted, err := format.Source(b.Bytes()); err != nil {
|
if formatted, err := ft.Format(b.Bytes()); err != nil {
|
||||||
err = fmt.Errorf("unable to run gofmt on %q (%v).", pathname, err)
|
err = fmt.Errorf("unable to format file %q (%v).", pathname, err)
|
||||||
// Write the file anyway, so they can see what's going wrong and fix the generator.
|
// Write the file anyway, so they can see what's going wrong and fix the generator.
|
||||||
if _, err2 := destFile.Write(b.Bytes()); err2 != nil {
|
if _, err2 := destFile.Write(b.Bytes()); err2 != nil {
|
||||||
return err2
|
return err2
|
||||||
@ -86,18 +89,18 @@ func (ft golangFileType) AssembleFile(f *File, pathname string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ft golangFileType) VerifyFile(f *File, pathname string) error {
|
func (ft DefaultFileType) VerifyFile(f *File, pathname string) error {
|
||||||
log.Printf("Verifying file %q", pathname)
|
log.Printf("Verifying file %q", pathname)
|
||||||
friendlyName := filepath.Join(f.PackageName, f.Name)
|
friendlyName := filepath.Join(f.PackageName, f.Name)
|
||||||
b := &bytes.Buffer{}
|
b := &bytes.Buffer{}
|
||||||
et := NewErrorTracker(b)
|
et := NewErrorTracker(b)
|
||||||
ft.assemble(et, f)
|
ft.Assemble(et, f)
|
||||||
if et.Error() != nil {
|
if et.Error() != nil {
|
||||||
return et.Error()
|
return et.Error()
|
||||||
}
|
}
|
||||||
formatted, err := format.Source(b.Bytes())
|
formatted, err := ft.Format(b.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to gofmt the output for %q: %v", friendlyName, err)
|
return fmt.Errorf("unable to format the output for %q: %v", friendlyName, err)
|
||||||
}
|
}
|
||||||
existing, err := ioutil.ReadFile(pathname)
|
existing, err := ioutil.ReadFile(pathname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -121,7 +124,7 @@ func (ft golangFileType) VerifyFile(f *File, pathname string) error {
|
|||||||
return fmt.Errorf("output for %q differs; first existing/expected diff: \n %q\n %q", friendlyName, string(eDiff), string(fDiff))
|
return fmt.Errorf("output for %q differs; first existing/expected diff: \n %q\n %q", friendlyName, string(eDiff), string(fDiff))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ft golangFileType) assemble(w io.Writer, f *File) {
|
func assembleGolangFile(w io.Writer, f *File) {
|
||||||
w.Write(f.Header)
|
w.Write(f.Header)
|
||||||
fmt.Fprintf(w, "package %v\n\n", f.PackageName)
|
fmt.Fprintf(w, "package %v\n\n", f.PackageName)
|
||||||
|
|
||||||
@ -155,6 +158,13 @@ func (ft golangFileType) assemble(w io.Writer, f *File) {
|
|||||||
w.Write(f.Body.Bytes())
|
w.Write(f.Body.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewGolangFile() *DefaultFileType {
|
||||||
|
return &DefaultFileType{
|
||||||
|
Format: format.Source,
|
||||||
|
Assemble: assembleGolangFile,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// format should be one line only, and not end with \n.
|
// format should be one line only, and not end with \n.
|
||||||
func addIndentHeaderComment(b *bytes.Buffer, format string, args ...interface{}) {
|
func addIndentHeaderComment(b *bytes.Buffer, format string, args ...interface{}) {
|
||||||
if b.Len() > 0 {
|
if b.Len() > 0 {
|
||||||
|
@ -177,7 +177,7 @@ func NewContext(b *parser.Builder, nameSystems namer.NameSystems, canonicalOrder
|
|||||||
Namers: namer.NameSystems{},
|
Namers: namer.NameSystems{},
|
||||||
Universe: u,
|
Universe: u,
|
||||||
FileTypes: map[string]FileType{
|
FileTypes: map[string]FileType{
|
||||||
GolangFileType: golangFileType{},
|
GolangFileType: NewGolangFile(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ func Run(g *Generator) {
|
|||||||
"public",
|
"public",
|
||||||
)
|
)
|
||||||
c.Verify = g.Common.VerifyOnly
|
c.Verify = g.Common.VerifyOnly
|
||||||
c.FileTypes["protoidl"] = protoIDLFileType{}
|
c.FileTypes["protoidl"] = NewProtoFile()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed making a context: %v", err)
|
log.Fatalf("Failed making a context: %v", err)
|
||||||
|
@ -17,13 +17,9 @@ limitations under the License.
|
|||||||
package protobuf
|
package protobuf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -231,7 +227,7 @@ func (b bodyGen) doStruct(sw *generator.SnippetWriter) error {
|
|||||||
if len(b.t.Name.Name) == 0 {
|
if len(b.t.Name.Name) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if isPrivateGoName(b.t.Name.Name) {
|
if namer.IsPrivateGoName(b.t.Name.Name) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,7 +521,7 @@ func membersToFields(locator ProtobufLocator, t *types.Type, localPackage types.
|
|||||||
fields := []protoField{}
|
fields := []protoField{}
|
||||||
|
|
||||||
for _, m := range t.Members {
|
for _, m := range t.Members {
|
||||||
if isPrivateGoName(m.Name) {
|
if namer.IsPrivateGoName(m.Name) {
|
||||||
// skip private fields
|
// skip private fields
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -561,7 +557,7 @@ func membersToFields(locator ProtobufLocator, t *types.Type, localPackage types.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(field.Name) == 0 {
|
if len(field.Name) == 0 {
|
||||||
field.Name = strings.ToLower(m.Name[:1]) + m.Name[1:]
|
field.Name = namer.IL(m.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if field.Map && field.Repeated {
|
if field.Map && field.Repeated {
|
||||||
@ -573,7 +569,7 @@ func membersToFields(locator ProtobufLocator, t *types.Type, localPackage types.
|
|||||||
if !field.Nullable {
|
if !field.Nullable {
|
||||||
field.Extras["(gogoproto.nullable)"] = "false"
|
field.Extras["(gogoproto.nullable)"] = "false"
|
||||||
}
|
}
|
||||||
if (field.Type.Name.Name == "bytes" && field.Type.Name.Package == "") || (field.Repeated && field.Type.Name.Package == "" && isPrivateGoName(field.Type.Name.Name)) {
|
if (field.Type.Name.Name == "bytes" && field.Type.Name.Package == "") || (field.Repeated && field.Type.Name.Package == "" && namer.IsPrivateGoName(field.Type.Name.Name)) {
|
||||||
delete(field.Extras, "(gogoproto.nullable)")
|
delete(field.Extras, "(gogoproto.nullable)")
|
||||||
}
|
}
|
||||||
if field.Name != m.Name {
|
if field.Name != m.Name {
|
||||||
@ -627,61 +623,12 @@ func genComment(out io.Writer, comment, indent string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type protoIDLFileType struct{}
|
func formatProtoFile(source []byte) ([]byte, error) {
|
||||||
|
// TODO; Is there any protobuf formatter?
|
||||||
func (ft protoIDLFileType) AssembleFile(f *generator.File, pathname string) error {
|
return source, nil
|
||||||
log.Printf("Assembling IDL file %q", pathname)
|
|
||||||
destFile, err := os.Create(pathname)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer destFile.Close()
|
|
||||||
|
|
||||||
b := &bytes.Buffer{}
|
|
||||||
et := generator.NewErrorTracker(b)
|
|
||||||
ft.assemble(et, f)
|
|
||||||
if et.Error() != nil {
|
|
||||||
return et.Error()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: is there an IDL formatter?
|
func assembleProtoFile(w io.Writer, f *generator.File) {
|
||||||
_, err = destFile.Write(b.Bytes())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ft protoIDLFileType) VerifyFile(f *generator.File, pathname string) error {
|
|
||||||
log.Printf("Verifying IDL file %q", pathname)
|
|
||||||
friendlyName := filepath.Join(f.PackageName, f.Name)
|
|
||||||
b := &bytes.Buffer{}
|
|
||||||
et := generator.NewErrorTracker(b)
|
|
||||||
ft.assemble(et, f)
|
|
||||||
if et.Error() != nil {
|
|
||||||
return et.Error()
|
|
||||||
}
|
|
||||||
formatted := b.Bytes()
|
|
||||||
existing, err := ioutil.ReadFile(pathname)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to read file %q for comparison: %v", friendlyName, err)
|
|
||||||
}
|
|
||||||
if bytes.Compare(formatted, existing) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Be nice and find the first place where they differ
|
|
||||||
i := 0
|
|
||||||
for i < len(formatted) && i < len(existing) && formatted[i] == existing[i] {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
eDiff, fDiff := existing[i:], formatted[i:]
|
|
||||||
if len(eDiff) > 100 {
|
|
||||||
eDiff = eDiff[:100]
|
|
||||||
}
|
|
||||||
if len(fDiff) > 100 {
|
|
||||||
fDiff = fDiff[:100]
|
|
||||||
}
|
|
||||||
return fmt.Errorf("output for %q differs; first existing/expected diff: \n %q\n %q", friendlyName, string(eDiff), string(fDiff))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ft protoIDLFileType) assemble(w io.Writer, f *generator.File) {
|
|
||||||
w.Write(f.Header)
|
w.Write(f.Header)
|
||||||
|
|
||||||
fmt.Fprint(w, "syntax = 'proto2';\n\n")
|
fmt.Fprint(w, "syntax = 'proto2';\n\n")
|
||||||
@ -709,9 +656,9 @@ func (ft protoIDLFileType) assemble(w io.Writer, f *generator.File) {
|
|||||||
w.Write(f.Body.Bytes())
|
w.Write(f.Body.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
func isPrivateGoName(name string) bool {
|
func NewProtoFile() *generator.DefaultFileType {
|
||||||
if len(name) == 0 {
|
return &generator.DefaultFileType{
|
||||||
return true
|
Format: formatProtoFile,
|
||||||
|
Assemble: assembleProtoFile,
|
||||||
}
|
}
|
||||||
return strings.ToLower(name[:1]) == name[:1]
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/kubernetes/cmd/libs/go2idl/generator"
|
"k8s.io/kubernetes/cmd/libs/go2idl/generator"
|
||||||
|
"k8s.io/kubernetes/cmd/libs/go2idl/namer"
|
||||||
"k8s.io/kubernetes/cmd/libs/go2idl/types"
|
"k8s.io/kubernetes/cmd/libs/go2idl/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -124,7 +125,7 @@ func assignGoTypeToProtoPackage(p *protobufPackage, t *types.Type, local, global
|
|||||||
|
|
||||||
local[t.Name] = p
|
local[t.Name] = p
|
||||||
for _, m := range t.Members {
|
for _, m := range t.Members {
|
||||||
if isPrivateGoName(m.Name) {
|
if namer.IsPrivateGoName(m.Name) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
field := &protoField{}
|
field := &protoField{}
|
||||||
|
@ -23,6 +23,11 @@ import (
|
|||||||
"k8s.io/kubernetes/cmd/libs/go2idl/types"
|
"k8s.io/kubernetes/cmd/libs/go2idl/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Returns whether a name is a private Go name.
|
||||||
|
func IsPrivateGoName(name string) bool {
|
||||||
|
return len(name) == 0 || strings.ToLower(name[:1]) == name[:1]
|
||||||
|
}
|
||||||
|
|
||||||
// NewPublicNamer is a helper function that returns a namer that makes
|
// NewPublicNamer is a helper function that returns a namer that makes
|
||||||
// CamelCase names. See the NameStrategy struct for an explanation of the
|
// CamelCase names. See the NameStrategy struct for an explanation of the
|
||||||
// arguments to this constructor.
|
// arguments to this constructor.
|
||||||
|
Loading…
Reference in New Issue
Block a user