mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 03:41:45 +00:00
Generate DeepCopies per directory.
This commit is contained in:
parent
e604efcf0d
commit
74d005f1cf
@ -93,6 +93,9 @@ func (g *GeneratorArgs) LoadGoBoilerplate() ([]byte, error) {
|
|||||||
// directories.
|
// directories.
|
||||||
func (g *GeneratorArgs) NewBuilder() (*parser.Builder, error) {
|
func (g *GeneratorArgs) NewBuilder() (*parser.Builder, error) {
|
||||||
b := parser.New()
|
b := parser.New()
|
||||||
|
// Ignore all auto-generated files.
|
||||||
|
b.AddBuildTags("ignore_autogenerated")
|
||||||
|
|
||||||
for _, d := range g.InputDirs {
|
for _, d := range g.InputDirs {
|
||||||
if g.Recursive {
|
if g.Recursive {
|
||||||
if err := b.AddDirRecursive(d); err != nil {
|
if err := b.AddDirRecursive(d); err != nil {
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
"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/namer"
|
||||||
"k8s.io/kubernetes/cmd/libs/go2idl/types"
|
"k8s.io/kubernetes/cmd/libs/go2idl/types"
|
||||||
|
"k8s.io/kubernetes/pkg/util/sets"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
@ -55,48 +56,52 @@ func DefaultNameSystem() string {
|
|||||||
return "public"
|
return "public"
|
||||||
}
|
}
|
||||||
|
|
||||||
func Packages(_ *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
|
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
|
||||||
boilerplate, err := arguments.LoadGoBoilerplate()
|
boilerplate, err := arguments.LoadGoBoilerplate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Fatalf("Failed loading boilerplate: %v", err)
|
glog.Fatalf("Failed loading boilerplate: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inputs := sets.NewString(arguments.InputDirs...)
|
||||||
packages := generator.Packages{}
|
packages := generator.Packages{}
|
||||||
for _, inputDir := range arguments.InputDirs {
|
header := append([]byte(
|
||||||
packages = append(packages,
|
`
|
||||||
&generator.DefaultPackage{
|
// +build !ignore_autogenerated
|
||||||
PackageName: filepath.Base(inputDir),
|
|
||||||
PackagePath: inputDir,
|
`), boilerplate...)
|
||||||
HeaderText: append(boilerplate, []byte(
|
header = append(header, []byte(
|
||||||
`
|
`
|
||||||
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
|
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
|
||||||
|
|
||||||
`)...),
|
`)...)
|
||||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
for _, p := range context.Universe {
|
||||||
generators = []generator.Generator{}
|
copyableType := false
|
||||||
// TODO: Check whether anything will be generated.
|
for _, t := range p.Types {
|
||||||
generators = append(generators, NewGenDeepCopy("deep_copy_generated", inputDir))
|
if copyableWithinPackage(t) {
|
||||||
return generators
|
copyableType = true
|
||||||
},
|
}
|
||||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
}
|
||||||
switch t.Kind {
|
if copyableType {
|
||||||
case types.Func, types.Chan:
|
path := p.Path
|
||||||
// These types can't be copied.
|
packages = append(packages,
|
||||||
return false
|
&generator.DefaultPackage{
|
||||||
case types.Unknown, types.Unsupported:
|
PackageName: filepath.Base(path),
|
||||||
// These types are explicitly ignored.
|
PackagePath: path,
|
||||||
return false
|
HeaderText: header,
|
||||||
case types.Array:
|
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||||
// We don't support arrays.
|
generators = []generator.Generator{}
|
||||||
return false
|
generators = append(
|
||||||
}
|
generators, NewGenDeepCopy("deep_copy_generated", path, inputs.Has(path)))
|
||||||
// Also, filter out private types.
|
return generators
|
||||||
if namer.IsPrivateGoName(t.Name.Name) {
|
},
|
||||||
return false
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
}
|
if t.Name.Package != path {
|
||||||
return true
|
return false
|
||||||
},
|
}
|
||||||
})
|
return copyableWithinPackage(t)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return packages
|
return packages
|
||||||
}
|
}
|
||||||
@ -109,19 +114,21 @@ const (
|
|||||||
// genDeepCopy produces a file with a set for a single type.
|
// genDeepCopy produces a file with a set for a single type.
|
||||||
type genDeepCopy struct {
|
type genDeepCopy struct {
|
||||||
generator.DefaultGen
|
generator.DefaultGen
|
||||||
targetPackage string
|
targetPackage string
|
||||||
imports namer.ImportTracker
|
imports namer.ImportTracker
|
||||||
typesForInit []*types.Type
|
typesForInit []*types.Type
|
||||||
|
generateInitFunc bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGenDeepCopy(sanitizedName, targetPackage string) generator.Generator {
|
func NewGenDeepCopy(sanitizedName, targetPackage string, generateInitFunc bool) generator.Generator {
|
||||||
return &genDeepCopy{
|
return &genDeepCopy{
|
||||||
DefaultGen: generator.DefaultGen{
|
DefaultGen: generator.DefaultGen{
|
||||||
OptionalName: sanitizedName,
|
OptionalName: sanitizedName,
|
||||||
},
|
},
|
||||||
targetPackage: targetPackage,
|
targetPackage: targetPackage,
|
||||||
imports: generator.NewImportTracker(),
|
imports: generator.NewImportTracker(),
|
||||||
typesForInit: make([]*types.Type, 0),
|
typesForInit: make([]*types.Type, 0),
|
||||||
|
generateInitFunc: generateInitFunc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,21 +140,14 @@ func (g *genDeepCopy) Namers(c *generator.Context) namer.NameSystems {
|
|||||||
// Filter ignores all but one type because we're making a single file per type.
|
// Filter ignores all but one type because we're making a single file per type.
|
||||||
func (g *genDeepCopy) Filter(c *generator.Context, t *types.Type) bool {
|
func (g *genDeepCopy) Filter(c *generator.Context, t *types.Type) bool {
|
||||||
// Filter out all types not copyable within the package.
|
// Filter out all types not copyable within the package.
|
||||||
copyable := g.copyableWithinPackage(t)
|
copyable := copyableWithinPackage(t)
|
||||||
if copyable {
|
if copyable {
|
||||||
g.typesForInit = append(g.typesForInit, t)
|
g.typesForInit = append(g.typesForInit, t)
|
||||||
}
|
}
|
||||||
return copyable
|
return copyable
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *genDeepCopy) copyableWithinPackage(t *types.Type) bool {
|
func copyableWithinPackage(t *types.Type) bool {
|
||||||
// TODO: We should generate public DeepCopy functions per directory, instead
|
|
||||||
// of generating everything everywhere.
|
|
||||||
// This is done that way only to minimize number of changes per PR.
|
|
||||||
// Once this is done, we should replace HasPrefix with:
|
|
||||||
//if t.Name.Package != g.targetPackage {
|
|
||||||
// return false
|
|
||||||
//}
|
|
||||||
if !strings.HasPrefix(t.Name.Package, "k8s.io/kubernetes/") {
|
if !strings.HasPrefix(t.Name.Package, "k8s.io/kubernetes/") {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -158,21 +158,9 @@ func (g *genDeepCopy) copyableWithinPackage(t *types.Type) bool {
|
|||||||
if t.Kind != types.Struct {
|
if t.Kind != types.Struct {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// TODO: This should be removed once we start generating public DeepCopy
|
// Also, filter out private types.
|
||||||
// functions per directory.
|
if namer.IsPrivateGoName(t.Name.Name) {
|
||||||
if t.Name.Package != g.targetPackage {
|
return false
|
||||||
// We won't be able to access private fields.
|
|
||||||
// Thus, this type cannot have private fields.
|
|
||||||
for _, member := range t.Members {
|
|
||||||
if namer.IsPrivateGoName(member.Name) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// TODO: This is a temporary hack, to make avoid generating function
|
|
||||||
// for conversion.Equalities. We should get rid of it.
|
|
||||||
if member.Embedded {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -189,7 +177,7 @@ func (g *genDeepCopy) isOtherPackage(pkg string) bool {
|
|||||||
|
|
||||||
func (g *genDeepCopy) Imports(c *generator.Context) (imports []string) {
|
func (g *genDeepCopy) Imports(c *generator.Context) (imports []string) {
|
||||||
importLines := []string{}
|
importLines := []string{}
|
||||||
if g.isOtherPackage(apiPackagePath) {
|
if g.isOtherPackage(apiPackagePath) && g.generateInitFunc {
|
||||||
importLines = append(importLines, "api \""+apiPackagePath+"\"")
|
importLines = append(importLines, "api \""+apiPackagePath+"\"")
|
||||||
}
|
}
|
||||||
if g.isOtherPackage(conversionPackagePath) {
|
if g.isOtherPackage(conversionPackagePath) {
|
||||||
@ -210,10 +198,21 @@ func argsFromType(t *types.Type) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *genDeepCopy) funcNameTmpl(t *types.Type) string {
|
func (g *genDeepCopy) funcNameTmpl(t *types.Type) string {
|
||||||
return "DeepCopy_$.type|public$"
|
tmpl := "DeepCopy_$.type|public$"
|
||||||
|
g.imports.AddType(t)
|
||||||
|
if t.Name.Package != g.targetPackage {
|
||||||
|
tmpl = g.imports.LocalNameOf(t.Name.Package) + "." + tmpl
|
||||||
|
}
|
||||||
|
return tmpl
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *genDeepCopy) Init(c *generator.Context, w io.Writer) error {
|
func (g *genDeepCopy) Init(c *generator.Context, w io.Writer) error {
|
||||||
|
if !g.generateInitFunc {
|
||||||
|
// TODO: We should come up with a solution to register all generated
|
||||||
|
// deep-copy functions. However, for now, to avoid import cycles
|
||||||
|
// we register only those explicitly requested.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
||||||
sw.Do("func init() {\n", nil)
|
sw.Do("func init() {\n", nil)
|
||||||
if g.targetPackage == apiPackagePath {
|
if g.targetPackage == apiPackagePath {
|
||||||
@ -236,7 +235,11 @@ func (g *genDeepCopy) Init(c *generator.Context, w io.Writer) error {
|
|||||||
func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||||
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
||||||
funcName := g.funcNameTmpl(t)
|
funcName := g.funcNameTmpl(t)
|
||||||
sw.Do(fmt.Sprintf("func %s(in $.type|raw$, out *$.type|raw$, c *conversion.Cloner) error {\n", funcName), argsFromType(t))
|
if g.targetPackage == conversionPackagePath {
|
||||||
|
sw.Do(fmt.Sprintf("func %s(in $.type|raw$, out *$.type|raw$, c *Cloner) error {\n", funcName), argsFromType(t))
|
||||||
|
} else {
|
||||||
|
sw.Do(fmt.Sprintf("func %s(in $.type|raw$, out *$.type|raw$, c *conversion.Cloner) error {\n", funcName), argsFromType(t))
|
||||||
|
}
|
||||||
g.generateFor(t, sw)
|
g.generateFor(t, sw)
|
||||||
sw.Do("return nil\n", nil)
|
sw.Do("return nil\n", nil)
|
||||||
sw.Do("}\n\n", nil)
|
sw.Do("}\n\n", nil)
|
||||||
@ -275,12 +278,12 @@ func (g *genDeepCopy) doBuiltin(t *types.Type, sw *generator.SnippetWriter) {
|
|||||||
|
|
||||||
func (g *genDeepCopy) doMap(t *types.Type, sw *generator.SnippetWriter) {
|
func (g *genDeepCopy) doMap(t *types.Type, sw *generator.SnippetWriter) {
|
||||||
sw.Do("*out = make($.|raw$)\n", t)
|
sw.Do("*out = make($.|raw$)\n", t)
|
||||||
sw.Do("for key, val := range in {\n", nil)
|
|
||||||
if t.Key.IsAssignable() {
|
if t.Key.IsAssignable() {
|
||||||
|
sw.Do("for key, val := range in {\n", nil)
|
||||||
if t.Elem.IsAssignable() {
|
if t.Elem.IsAssignable() {
|
||||||
sw.Do("(*out)[key] = val\n", nil)
|
sw.Do("(*out)[key] = val\n", nil)
|
||||||
} else {
|
} else {
|
||||||
if g.copyableWithinPackage(t.Elem) {
|
if copyableWithinPackage(t.Elem) {
|
||||||
sw.Do("newVal := new($.|raw$)\n", t.Elem)
|
sw.Do("newVal := new($.|raw$)\n", t.Elem)
|
||||||
funcName := g.funcNameTmpl(t.Elem)
|
funcName := g.funcNameTmpl(t.Elem)
|
||||||
sw.Do(fmt.Sprintf("if err := %s(val, newVal, c); err != nil {\n", funcName), argsFromType(t.Elem))
|
sw.Do(fmt.Sprintf("if err := %s(val, newVal, c); err != nil {\n", funcName), argsFromType(t.Elem))
|
||||||
@ -297,6 +300,7 @@ func (g *genDeepCopy) doMap(t *types.Type, sw *generator.SnippetWriter) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO: Implement it when necessary.
|
// TODO: Implement it when necessary.
|
||||||
|
sw.Do("for range in {\n", nil)
|
||||||
sw.Do("// FIXME: Copying unassignable keys unsupported $.|raw$\n", t.Key)
|
sw.Do("// FIXME: Copying unassignable keys unsupported $.|raw$\n", t.Key)
|
||||||
}
|
}
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
@ -310,7 +314,7 @@ func (g *genDeepCopy) doSlice(t *types.Type, sw *generator.SnippetWriter) {
|
|||||||
sw.Do("for i := range in {\n", nil)
|
sw.Do("for i := range in {\n", nil)
|
||||||
if t.Elem.IsAssignable() {
|
if t.Elem.IsAssignable() {
|
||||||
sw.Do("(*out)[i] = in[i]\n", nil)
|
sw.Do("(*out)[i] = in[i]\n", nil)
|
||||||
} else if g.copyableWithinPackage(t.Elem) {
|
} else if copyableWithinPackage(t.Elem) {
|
||||||
funcName := g.funcNameTmpl(t.Elem)
|
funcName := g.funcNameTmpl(t.Elem)
|
||||||
sw.Do(fmt.Sprintf("if err := %s(in[i], &(*out)[i], c); err != nil {\n", funcName), argsFromType(t.Elem))
|
sw.Do(fmt.Sprintf("if err := %s(in[i], &(*out)[i], c); err != nil {\n", funcName), argsFromType(t.Elem))
|
||||||
sw.Do("return err\n", nil)
|
sw.Do("return err\n", nil)
|
||||||
@ -343,7 +347,7 @@ func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) {
|
|||||||
sw.Do("out.$.name$ = nil\n", args)
|
sw.Do("out.$.name$ = nil\n", args)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
case types.Struct:
|
case types.Struct:
|
||||||
if g.copyableWithinPackage(m.Type) {
|
if copyableWithinPackage(m.Type) {
|
||||||
funcName := g.funcNameTmpl(m.Type)
|
funcName := g.funcNameTmpl(m.Type)
|
||||||
sw.Do(fmt.Sprintf("if err := %s(in.$.name$, &out.$.name$, c); err != nil {\n", funcName), args)
|
sw.Do(fmt.Sprintf("if err := %s(in.$.name$, &out.$.name$, c); err != nil {\n", funcName), args)
|
||||||
sw.Do("return err\n", nil)
|
sw.Do("return err\n", nil)
|
||||||
@ -378,7 +382,7 @@ func (g *genDeepCopy) doPointer(t *types.Type, sw *generator.SnippetWriter) {
|
|||||||
sw.Do("*out = new($.Elem|raw$)\n", t)
|
sw.Do("*out = new($.Elem|raw$)\n", t)
|
||||||
if t.Elem.Kind == types.Builtin {
|
if t.Elem.Kind == types.Builtin {
|
||||||
sw.Do("**out = *in", nil)
|
sw.Do("**out = *in", nil)
|
||||||
} else if g.copyableWithinPackage(t.Elem) {
|
} else if copyableWithinPackage(t.Elem) {
|
||||||
funcName := g.funcNameTmpl(t.Elem)
|
funcName := g.funcNameTmpl(t.Elem)
|
||||||
sw.Do(fmt.Sprintf("if err := %s(*in, *out, c); err != nil {\n", funcName), argsFromType(t.Elem))
|
sw.Do(fmt.Sprintf("if err := %s(*in, *out, c); err != nil {\n", funcName), argsFromType(t.Elem))
|
||||||
sw.Do("return err\n", nil)
|
sw.Do("return err\n", nil)
|
||||||
|
Loading…
Reference in New Issue
Block a user