diff --git a/cmd/libs/go2idl/deepcopy-gen/generators/deepcopy.go b/cmd/libs/go2idl/deepcopy-gen/generators/deepcopy.go deleted file mode 100644 index 7fa514f863f..00000000000 --- a/cmd/libs/go2idl/deepcopy-gen/generators/deepcopy.go +++ /dev/null @@ -1,624 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package generators - -import ( - "fmt" - "io" - "path/filepath" - "strings" - - "k8s.io/gengo/args" - "k8s.io/gengo/generator" - "k8s.io/gengo/namer" - "k8s.io/gengo/types" - "k8s.io/kubernetes/pkg/util/sets" - - "github.com/golang/glog" -) - -// CustomArgs is used tby the go2idl framework to pass args specific to this -// generator. -type CustomArgs struct { - BoundingDirs []string // Only deal with types rooted under these dirs. -} - -// This is the comment tag that carries parameters for deep-copy generation. -const tagName = "k8s:deepcopy-gen" - -// Known values for the comment tag. -const tagValuePackage = "package" - -// tagValue holds parameters from a tagName tag. -type tagValue struct { - value string - register bool -} - -func extractTag(comments []string) *tagValue { - tagVals := types.ExtractCommentTags("+", comments)[tagName] - if tagVals == nil { - // No match for the tag. - return nil - } - // If there are multiple values, abort. - if len(tagVals) > 1 { - glog.Fatalf("Found %d %s tags: %q", len(tagVals), tagName, tagVals) - } - - // If we got here we are returning something. - tag := &tagValue{} - - // Get the primary value. - parts := strings.Split(tagVals[0], ",") - if len(parts) >= 1 { - tag.value = parts[0] - } - - // Parse extra arguments. - parts = parts[1:] - for i := range parts { - kv := strings.SplitN(parts[i], "=", 2) - k := kv[0] - v := "" - if len(kv) == 2 { - v = kv[1] - } - switch k { - case "register": - if v != "false" { - tag.register = true - } - default: - glog.Fatalf("Unsupported %s param: %q", tagName, parts[i]) - } - } - return tag -} - -// TODO: This is created only to reduce number of changes in a single PR. -// Remove it and use PublicNamer instead. -func deepCopyNamer() *namer.NameStrategy { - return &namer.NameStrategy{ - Join: func(pre string, in []string, post string) string { - return strings.Join(in, "_") - }, - PrependPackageNames: 1, - } -} - -// NameSystems returns the name system used by the generators in this package. -func NameSystems() namer.NameSystems { - return namer.NameSystems{ - "public": deepCopyNamer(), - "raw": namer.NewRawNamer("", nil), - } -} - -// DefaultNameSystem returns the default name system for ordering the types to be -// processed by the generators in this package. -func DefaultNameSystem() string { - return "public" -} - -func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { - boilerplate, err := arguments.LoadGoBoilerplate() - if err != nil { - glog.Fatalf("Failed loading boilerplate: %v", err) - } - - inputs := sets.NewString(context.Inputs...) - packages := generator.Packages{} - header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...) - header = append(header, []byte( - ` -// This file was autogenerated by deepcopy-gen. Do not edit it manually! - -`)...) - - boundingDirs := []string{} - if customArgs, ok := arguments.CustomArgs.(*CustomArgs); ok { - for i := range customArgs.BoundingDirs { - // Strip any trailing slashes - they are not exactly "correct" but - // this is friendlier. - boundingDirs = append(boundingDirs, strings.TrimRight(customArgs.BoundingDirs[i], "/")) - } - } - - for i := range inputs { - glog.V(5).Infof("considering pkg %q", i) - pkg := context.Universe[i] - if pkg == nil { - // If the input had no Go files, for example. - continue - } - - ptag := extractTag(pkg.Comments) - ptagValue := "" - ptagRegister := false - if ptag != nil { - ptagValue = ptag.value - if ptagValue != tagValuePackage { - glog.Fatalf("Package %v: unsupported %s value: %q", i, tagName, ptagValue) - } - ptagRegister = ptag.register - glog.V(5).Infof(" tag.value: %q, tag.register: %t", ptagValue, ptagRegister) - } else { - glog.V(5).Infof(" no tag") - } - - // If the pkg-scoped tag says to generate, we can skip scanning types. - pkgNeedsGeneration := (ptagValue == tagValuePackage) - if !pkgNeedsGeneration { - // If the pkg-scoped tag did not exist, scan all types for one that - // explicitly wants generation. - for _, t := range pkg.Types { - glog.V(5).Infof(" considering type %q", t.Name.String()) - ttag := extractTag(t.CommentLines) - if ttag != nil && ttag.value == "true" { - glog.V(5).Infof(" tag=true") - if !copyableType(t) { - glog.Fatalf("Type %v requests deepcopy generation but is not copyable", t) - } - pkgNeedsGeneration = true - break - } - } - } - - if pkgNeedsGeneration { - packages = append(packages, - &generator.DefaultPackage{ - PackageName: strings.Split(filepath.Base(pkg.Path), ".")[0], - PackagePath: pkg.Path, - HeaderText: header, - GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { - generators = []generator.Generator{} - generators = append( - generators, NewGenDeepCopy(arguments.OutputFileBaseName, pkg.Path, boundingDirs, (ptagValue == tagValuePackage), ptagRegister)) - return generators - }, - FilterFunc: func(c *generator.Context, t *types.Type) bool { - return t.Name.Package == pkg.Path - }, - }) - } - } - return packages -} - -const ( - apiPackagePath = "k8s.io/kubernetes/pkg/api" - conversionPackagePath = "k8s.io/kubernetes/pkg/conversion" - runtimePackagePath = "k8s.io/kubernetes/pkg/runtime" -) - -// genDeepCopy produces a file with autogenerated deep-copy functions. -type genDeepCopy struct { - generator.DefaultGen - targetPackage string - boundingDirs []string - allTypes bool - registerTypes bool - imports namer.ImportTracker - typesForInit []*types.Type -} - -func NewGenDeepCopy(sanitizedName, targetPackage string, boundingDirs []string, allTypes, registerTypes bool) generator.Generator { - return &genDeepCopy{ - DefaultGen: generator.DefaultGen{ - OptionalName: sanitizedName, - }, - targetPackage: targetPackage, - boundingDirs: boundingDirs, - allTypes: allTypes, - registerTypes: registerTypes, - imports: generator.NewImportTracker(), - typesForInit: make([]*types.Type, 0), - } -} - -func (g *genDeepCopy) Namers(c *generator.Context) namer.NameSystems { - // Have the raw namer for this file track what it imports. - return namer.NameSystems{ - "raw": namer.NewRawNamer(g.targetPackage, g.imports), - "dcFnName": &dcFnNamer{ - public: deepCopyNamer(), - tracker: g.imports, - myPackage: g.targetPackage, - }, - } -} - -func (g *genDeepCopy) Filter(c *generator.Context, t *types.Type) bool { - // Filter out types not being processed or not copyable within the package. - enabled := g.allTypes - if !enabled { - ttag := extractTag(t.CommentLines) - if ttag != nil && ttag.value == "true" { - enabled = true - } - } - copyable := enabled && copyableType(t) - if copyable { - g.typesForInit = append(g.typesForInit, t) - } - return copyable -} - -func (g *genDeepCopy) copyableAndInBounds(t *types.Type) bool { - if !copyableType(t) { - return false - } - // Only packages within the restricted range can be processed. - if !isRootedUnder(t.Name.Package, g.boundingDirs) { - return false - } - return true -} - -// hasDeepCopyMethod returns true if an appropriate DeepCopy() method is -// defined for the given type. This allows more efficient deep copy -// implementations to be defined by the type's author. The correct signature -// for a type T is: -// func (t T) DeepCopy() T -// or: -// func (t *T) DeepCopyt() T -func hasDeepCopyMethod(t *types.Type) bool { - for mn, mt := range t.Methods { - if mn != "DeepCopy" { - continue - } - if len(mt.Signature.Parameters) != 0 { - return false - } - if len(mt.Signature.Results) != 1 || mt.Signature.Results[0].Name != t.Name { - return false - } - return true - } - return false -} - -func isRootedUnder(pkg string, roots []string) bool { - // Add trailing / to avoid false matches, e.g. foo/bar vs foo/barn. This - // assumes that bounding dirs do not have trailing slashes. - pkg = pkg + "/" - for _, root := range roots { - if strings.HasPrefix(pkg, root+"/") { - return true - } - } - return false -} - -func copyableType(t *types.Type) bool { - // If the type opts out of copy-generation, stop. - ttag := extractTag(t.CommentLines) - if ttag != nil && ttag.value == "false" { - return false - } - // TODO: Consider generating functions for other kinds too. - if t.Kind != types.Struct { - return false - } - // Also, filter out private types. - if namer.IsPrivateGoName(t.Name.Name) { - return false - } - return true -} - -func (g *genDeepCopy) isOtherPackage(pkg string) bool { - if pkg == g.targetPackage { - return false - } - if strings.HasSuffix(pkg, "\""+g.targetPackage+"\"") { - return false - } - return true -} - -func (g *genDeepCopy) Imports(c *generator.Context) (imports []string) { - importLines := []string{} - for _, singleImport := range g.imports.ImportLines() { - if g.isOtherPackage(singleImport) { - importLines = append(importLines, singleImport) - } - } - return importLines -} - -func argsFromType(t *types.Type) generator.Args { - return generator.Args{ - "type": t, - } -} - -type dcFnNamer struct { - public namer.Namer - tracker namer.ImportTracker - myPackage string -} - -func (n *dcFnNamer) Name(t *types.Type) string { - pubName := n.public.Name(t) - n.tracker.AddType(t) - if t.Name.Package == n.myPackage { - return "DeepCopy_" + pubName - } - return fmt.Sprintf("%s.DeepCopy_%s", n.tracker.LocalNameOf(t.Name.Package), pubName) -} - -func (g *genDeepCopy) Init(c *generator.Context, w io.Writer) error { - cloner := c.Universe.Type(types.Name{Package: conversionPackagePath, Name: "Cloner"}) - g.imports.AddType(cloner) - if !g.registerTypes { - // 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 - } - glog.V(5).Infof("registering types in pkg %q", g.targetPackage) - - sw := generator.NewSnippetWriter(w, c, "$", "$") - sw.Do("func init() {\n", nil) - sw.Do("SchemeBuilder.Register(RegisterDeepCopies)\n", nil) - sw.Do("}\n\n", nil) - - scheme := c.Universe.Type(types.Name{Package: runtimePackagePath, Name: "Scheme"}) - schemePtr := &types.Type{ - Kind: types.Pointer, - Elem: scheme, - } - sw.Do("// RegisterDeepCopies adds deep-copy functions to the given scheme. Public\n", nil) - sw.Do("// to allow building arbitrary schemes.\n", nil) - sw.Do("func RegisterDeepCopies(scheme $.|raw$) error {\n", schemePtr) - sw.Do("return scheme.AddGeneratedDeepCopyFuncs(\n", nil) - for _, t := range g.typesForInit { - args := argsFromType(t). - With("typeof", c.Universe.Package("reflect").Function("TypeOf")) - sw.Do("conversion.GeneratedDeepCopyFunc{Fn: $.type|dcFnName$, InType: $.typeof|raw$(&$.type|raw${})},\n", args) - } - sw.Do(")\n", nil) - sw.Do("}\n\n", nil) - return sw.Error() -} - -func (g *genDeepCopy) needsGeneration(t *types.Type) bool { - tag := extractTag(t.CommentLines) - tv := "" - if tag != nil { - tv = tag.value - if tv != "true" && tv != "false" { - glog.Fatalf("Type %v: unsupported %s value: %q", t, tagName, tag.value) - } - } - if g.allTypes && tv == "false" { - // The whole package is being generated, but this type has opted out. - glog.V(5).Infof("not generating for type %v because type opted out", t) - return false - } - if !g.allTypes && tv != "true" { - // The whole package is NOT being generated, and this type has NOT opted in. - glog.V(5).Infof("not generating for type %v because type did not opt in", t) - return false - } - return true -} - -func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { - if !g.needsGeneration(t) { - return nil - } - glog.V(5).Infof("generating for type %v", t) - - sw := generator.NewSnippetWriter(w, c, "$", "$") - args := argsFromType(t). - With("clonerType", types.Ref(conversionPackagePath, "Cloner")) - sw.Do("func $.type|dcFnName$(in interface{}, out interface{}, c *$.clonerType|raw$) error {{\n", args) - sw.Do("in := in.(*$.type|raw$)\nout := out.(*$.type|raw$)\n", argsFromType(t)) - g.generateFor(t, sw) - sw.Do("return nil\n", nil) - sw.Do("}}\n\n", nil) - return sw.Error() -} - -// we use the system of shadowing 'in' and 'out' so that the same code is valid -// at any nesting level. This makes the autogenerator easy to understand, and -// the compiler shouldn't care. -func (g *genDeepCopy) generateFor(t *types.Type, sw *generator.SnippetWriter) { - var f func(*types.Type, *generator.SnippetWriter) - switch t.Kind { - case types.Builtin: - f = g.doBuiltin - case types.Map: - f = g.doMap - case types.Slice: - f = g.doSlice - case types.Struct: - f = g.doStruct - case types.Interface: - f = g.doInterface - case types.Pointer: - f = g.doPointer - case types.Alias: - f = g.doAlias - default: - f = g.doUnknown - } - f(t, sw) -} - -func (g *genDeepCopy) doBuiltin(t *types.Type, sw *generator.SnippetWriter) { - sw.Do("*out = *in\n", nil) -} - -func (g *genDeepCopy) doMap(t *types.Type, sw *generator.SnippetWriter) { - sw.Do("*out = make($.|raw$)\n", t) - if t.Key.IsAssignable() { - switch { - case hasDeepCopyMethod(t.Elem): - sw.Do("for key, val := range *in {\n", nil) - sw.Do("(*out)[key] = val.DeepCopy()\n", nil) - sw.Do("}\n", nil) - case t.Elem.IsAnonymousStruct(): - sw.Do("for key := range *in {\n", nil) - sw.Do("(*out)[key] = struct{}{}\n", nil) - sw.Do("}\n", nil) - case t.Elem.IsAssignable(): - sw.Do("for key, val := range *in {\n", nil) - sw.Do("(*out)[key] = val\n", nil) - sw.Do("}\n", nil) - default: - sw.Do("for key, val := range *in {\n", nil) - if g.copyableAndInBounds(t.Elem) { - sw.Do("newVal := new($.|raw$)\n", t.Elem) - sw.Do("if err := $.type|dcFnName$(&val, newVal, c); err != nil {\n", argsFromType(t.Elem)) - sw.Do("return err\n", nil) - sw.Do("}\n", nil) - sw.Do("(*out)[key] = *newVal\n", nil) - } else { - sw.Do("if newVal, err := c.DeepCopy(&val); err != nil {\n", nil) - sw.Do("return err\n", nil) - sw.Do("} else {\n", nil) - sw.Do("(*out)[key] = *newVal.(*$.|raw$)\n", t.Elem) - sw.Do("}\n", nil) - } - sw.Do("}\n", nil) - } - } else { - // 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("}\n", nil) - } -} - -func (g *genDeepCopy) doSlice(t *types.Type, sw *generator.SnippetWriter) { - sw.Do("*out = make($.|raw$, len(*in))\n", t) - if t.Elem.Kind == types.Builtin { - sw.Do("copy(*out, *in)\n", nil) - } else { - sw.Do("for i := range *in {\n", nil) - if hasDeepCopyMethod(t.Elem) { - sw.Do("(*out)[i] = (*in)[i].DeepCopy()\n", nil) - } else if t.Elem.IsAssignable() { - sw.Do("(*out)[i] = (*in)[i]\n", nil) - } else if g.copyableAndInBounds(t.Elem) { - sw.Do("if err := $.type|dcFnName$(&(*in)[i], &(*out)[i], c); err != nil {\n", argsFromType(t.Elem)) - sw.Do("return err\n", nil) - sw.Do("}\n", nil) - } else { - sw.Do("if newVal, err := c.DeepCopy(&(*in)[i]); err != nil {\n", nil) - sw.Do("return err\n", nil) - sw.Do("} else {\n", nil) - sw.Do("(*out)[i] = *newVal.(*$.|raw$)\n", t.Elem) - sw.Do("}\n", nil) - } - sw.Do("}\n", nil) - } -} - -func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) { - if len(t.Members) == 0 { - // at least do something with in/out to avoid "declared and not used" errors - sw.Do("_ = in\n_ = out\n", nil) - } - for _, m := range t.Members { - t := m.Type - if t.Kind == types.Alias { - copied := *t.Underlying - copied.Name = t.Name - t = &copied - } - args := generator.Args{ - "type": t, - "name": m.Name, - } - switch t.Kind { - case types.Builtin: - sw.Do("out.$.name$ = in.$.name$\n", args) - case types.Map, types.Slice, types.Pointer: - sw.Do("if in.$.name$ != nil {\n", args) - sw.Do("in, out := &in.$.name$, &out.$.name$\n", args) - g.generateFor(t, sw) - sw.Do("} else {\n", nil) - sw.Do("out.$.name$ = nil\n", args) - sw.Do("}\n", nil) - case types.Struct: - if hasDeepCopyMethod(t) { - sw.Do("out.$.name$ = in.$.name$.DeepCopy()\n", args) - } else if t.IsAssignable() { - sw.Do("out.$.name$ = in.$.name$\n", args) - } else if g.copyableAndInBounds(t) { - sw.Do("if err := $.type|dcFnName$(&in.$.name$, &out.$.name$, c); err != nil {\n", args) - sw.Do("return err\n", nil) - sw.Do("}\n", nil) - } else { - sw.Do("if newVal, err := c.DeepCopy(&in.$.name$); err != nil {\n", args) - sw.Do("return err\n", nil) - sw.Do("} else {\n", nil) - sw.Do("out.$.name$ = *newVal.(*$.type|raw$)\n", args) - sw.Do("}\n", nil) - } - default: - sw.Do("if in.$.name$ == nil {\n", args) - sw.Do("out.$.name$ = nil\n", args) - sw.Do("} else if newVal, err := c.DeepCopy(&in.$.name$); err != nil {\n", args) - sw.Do("return err\n", nil) - sw.Do("} else {\n", nil) - sw.Do("out.$.name$ = *newVal.(*$.type|raw$)\n", args) - sw.Do("}\n", nil) - } - } -} - -func (g *genDeepCopy) doInterface(t *types.Type, sw *generator.SnippetWriter) { - // TODO: Add support for interfaces. - g.doUnknown(t, sw) -} - -func (g *genDeepCopy) doPointer(t *types.Type, sw *generator.SnippetWriter) { - if hasDeepCopyMethod(t.Elem) { - sw.Do("*out = new($.Elem|raw$)\n", t) - sw.Do("**out = (*in).DeepCopy()\n", nil) - } else if t.Elem.IsAssignable() { - sw.Do("*out = new($.Elem|raw$)\n", t) - sw.Do("**out = **in", nil) - } else if g.copyableAndInBounds(t.Elem) { - sw.Do("*out = new($.Elem|raw$)\n", t) - sw.Do("if err := $.type|dcFnName$(*in, *out, c); err != nil {\n", argsFromType(t.Elem)) - sw.Do("return err\n", nil) - sw.Do("}\n", nil) - } else { - sw.Do("if newVal, err := c.DeepCopy(*in); err != nil {\n", nil) - sw.Do("return err\n", nil) - sw.Do("} else {\n", nil) - sw.Do("*out = newVal.(*$.|raw$)\n", t.Elem) - sw.Do("}\n", nil) - } -} - -func (g *genDeepCopy) doAlias(t *types.Type, sw *generator.SnippetWriter) { - // TODO: Add support for aliases. - g.doUnknown(t, sw) -} - -func (g *genDeepCopy) doUnknown(t *types.Type, sw *generator.SnippetWriter) { - sw.Do("// FIXME: Type $.|raw$ is unsupported.\n", t) -} diff --git a/cmd/libs/go2idl/deepcopy-gen/generators/deepcopy_test.go b/cmd/libs/go2idl/deepcopy-gen/generators/deepcopy_test.go deleted file mode 100644 index 434bcaee665..00000000000 --- a/cmd/libs/go2idl/deepcopy-gen/generators/deepcopy_test.go +++ /dev/null @@ -1,344 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package generators - -import ( - "testing" - - "k8s.io/gengo/types" -) - -func Test_isRootedUnder(t *testing.T) { - testCases := []struct { - path string - roots []string - expect bool - }{ - { - path: "/foo/bar", - roots: nil, - expect: false, - }, - { - path: "/foo/bar", - roots: []string{}, - expect: false, - }, - { - path: "/foo/bar", - roots: []string{ - "/bad", - }, - expect: false, - }, - { - path: "/foo/bar", - roots: []string{ - "/foo", - }, - expect: true, - }, - { - path: "/foo/bar", - roots: []string{ - "/bad", - "/foo", - }, - expect: true, - }, - { - path: "/foo/bar/qux/zorb", - roots: []string{ - "/foo/bar/qux", - }, - expect: true, - }, - { - path: "/foo/bar", - roots: []string{ - "/foo/bar", - }, - expect: true, - }, - { - path: "/foo/barn", - roots: []string{ - "/foo/bar", - }, - expect: false, - }, - { - path: "/foo/bar", - roots: []string{ - "/foo/barn", - }, - expect: false, - }, - { - path: "/foo/bar", - roots: []string{ - "", - }, - expect: true, - }, - } - - for i, tc := range testCases { - r := isRootedUnder(tc.path, tc.roots) - if r != tc.expect { - t.Errorf("case[%d]: expected %t, got %t for %q in %q", i, tc.expect, r, tc.path, tc.roots) - } - } -} - -func Test_hasDeepCopyMethod(t *testing.T) { - testCases := []struct { - typ types.Type - expect bool - }{ - { - typ: types.Type{ - Name: types.Name{Package: "pkgname", Name: "typename"}, - Kind: types.Builtin, - // No DeepCopy method. - Methods: map[string]*types.Type{}, - }, - expect: false, - }, - { - typ: types.Type{ - Name: types.Name{Package: "pkgname", Name: "typename"}, - Kind: types.Builtin, - Methods: map[string]*types.Type{ - // No DeepCopy method. - "method": { - Name: types.Name{Package: "pkgname", Name: "func()"}, - Kind: types.Func, - Signature: &types.Signature{ - Parameters: []*types.Type{}, - Results: []*types.Type{}, - }, - }, - }, - }, - expect: false, - }, - { - typ: types.Type{ - Name: types.Name{Package: "pkgname", Name: "typename"}, - Kind: types.Builtin, - Methods: map[string]*types.Type{ - // Wrong signature (no result). - "DeepCopy": { - Name: types.Name{Package: "pkgname", Name: "func()"}, - Kind: types.Func, - Signature: &types.Signature{ - Parameters: []*types.Type{}, - Results: []*types.Type{}, - }, - }, - }, - }, - expect: false, - }, - { - typ: types.Type{ - Name: types.Name{Package: "pkgname", Name: "typename"}, - Kind: types.Builtin, - Methods: map[string]*types.Type{ - // Wrong signature (wrong result). - "DeepCopy": { - Name: types.Name{Package: "pkgname", Name: "func() int"}, - Kind: types.Func, - Signature: &types.Signature{ - Parameters: []*types.Type{}, - Results: []*types.Type{ - { - Name: types.Name{Name: "int"}, - Kind: types.Builtin, - }, - }, - }, - }, - }, - }, - expect: false, - }, - { - typ: types.Type{ - Name: types.Name{Package: "pkgname", Name: "typename"}, - Kind: types.Builtin, - Methods: map[string]*types.Type{ - // Correct signature. - "DeepCopy": { - Name: types.Name{Package: "pkgname", Name: "func() pkgname.typename"}, - Kind: types.Func, - Signature: &types.Signature{ - Parameters: []*types.Type{}, - Results: []*types.Type{ - { - Name: types.Name{Package: "pkgname", Name: "typename"}, - Kind: types.Builtin, - }, - }, - }, - }, - }, - }, - expect: true, - }, - { - typ: types.Type{ - Name: types.Name{Package: "pkgname", Name: "typename"}, - Kind: types.Builtin, - Methods: map[string]*types.Type{ - // Wrong signature (has params). - "DeepCopy": { - Name: types.Name{Package: "pkgname", Name: "func(int) pkgname.typename"}, - Kind: types.Func, - Signature: &types.Signature{ - Parameters: []*types.Type{ - { - Name: types.Name{Name: "int"}, - Kind: types.Builtin, - }, - }, - Results: []*types.Type{ - { - Name: types.Name{Package: "pkgname", Name: "typename"}, - Kind: types.Builtin, - }, - }, - }, - }, - }, - }, - expect: false, - }, - { - typ: types.Type{ - Name: types.Name{Package: "pkgname", Name: "typename"}, - Kind: types.Builtin, - Methods: map[string]*types.Type{ - // Wrong signature (extra results). - "DeepCopy": { - Name: types.Name{Package: "pkgname", Name: "func() (pkgname.typename, int)"}, - Kind: types.Func, - Signature: &types.Signature{ - Parameters: []*types.Type{}, - Results: []*types.Type{ - { - Name: types.Name{Package: "pkgname", Name: "typename"}, - Kind: types.Builtin, - }, - { - Name: types.Name{Name: "int"}, - Kind: types.Builtin, - }, - }, - }, - }, - }, - }, - expect: false, - }, - } - - for i, tc := range testCases { - r := hasDeepCopyMethod(&tc.typ) - if r != tc.expect { - t.Errorf("case[%d]: expected %t, got %t", i, tc.expect, r) - } - } -} - -func Test_extractTagParams(t *testing.T) { - testCases := []struct { - comments []string - expect *tagValue - }{ - { - comments: []string{ - "Human comment", - }, - expect: nil, - }, - { - comments: []string{ - "Human comment", - "+k8s:deepcopy-gen", - }, - expect: &tagValue{ - value: "", - register: false, - }, - }, - { - comments: []string{ - "Human comment", - "+k8s:deepcopy-gen=package", - }, - expect: &tagValue{ - value: "package", - register: false, - }, - }, - { - comments: []string{ - "Human comment", - "+k8s:deepcopy-gen=package,register", - }, - expect: &tagValue{ - value: "package", - register: true, - }, - }, - { - comments: []string{ - "Human comment", - "+k8s:deepcopy-gen=package,register=true", - }, - expect: &tagValue{ - value: "package", - register: true, - }, - }, - { - comments: []string{ - "Human comment", - "+k8s:deepcopy-gen=package,register=false", - }, - expect: &tagValue{ - value: "package", - register: false, - }, - }, - } - - for i, tc := range testCases { - r := extractTag(tc.comments) - if r == nil && tc.expect != nil { - t.Errorf("case[%d]: expected non-nil", i) - } - if r != nil && tc.expect == nil { - t.Errorf("case[%d]: expected nil, got %v", i, *r) - } - if r != nil && *r != *tc.expect { - t.Errorf("case[%d]: expected %v, got %v", i, *tc.expect, *r) - } - } -} diff --git a/cmd/libs/go2idl/deepcopy-gen/main.go b/cmd/libs/go2idl/deepcopy-gen/main.go index c80adf74582..82c4cc354cd 100644 --- a/cmd/libs/go2idl/deepcopy-gen/main.go +++ b/cmd/libs/go2idl/deepcopy-gen/main.go @@ -49,7 +49,7 @@ package main import ( "k8s.io/gengo/args" - "k8s.io/kubernetes/cmd/libs/go2idl/deepcopy-gen/generators" + "k8s.io/gengo/examples/deepcopy-gen/generators" "github.com/golang/glog" "github.com/spf13/pflag" diff --git a/cmd/libs/go2idl/import-boss/generators/import_restrict.go b/cmd/libs/go2idl/import-boss/generators/import_restrict.go deleted file mode 100644 index e806e932964..00000000000 --- a/cmd/libs/go2idl/import-boss/generators/import_restrict.go +++ /dev/null @@ -1,272 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package generators has the generators for the import-boss utility. -package generators - -import ( - "encoding/json" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "regexp" - "sort" - "strings" - - "k8s.io/gengo/args" - "k8s.io/gengo/generator" - "k8s.io/gengo/namer" - "k8s.io/gengo/types" - - "github.com/golang/glog" -) - -const ( - importBossFileType = "import-boss" -) - -// NameSystems returns the name system used by the generators in this package. -func NameSystems() namer.NameSystems { - return namer.NameSystems{ - "raw": namer.NewRawNamer("", nil), - } -} - -// DefaultNameSystem returns the default name system for ordering the types to be -// processed by the generators in this package. -func DefaultNameSystem() string { - return "raw" -} - -// Packages makes the sets package definition. -func Packages(c *generator.Context, arguments *args.GeneratorArgs) generator.Packages { - pkgs := generator.Packages{} - c.FileTypes = map[string]generator.FileType{ - importBossFileType: importRuleFile{}, - } - - for _, p := range c.Universe { - if !arguments.InputIncludes(p) { - // Don't run on e.g. third party dependencies. - continue - } - savedPackage := p - pkgs = append(pkgs, &generator.DefaultPackage{ - PackageName: p.Name, - PackagePath: p.Path, - // GeneratorFunc returns a list of generators. Each generator makes a - // single file. - GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { - return []generator.Generator{&importRules{ - myPackage: savedPackage, - }} - }, - FilterFunc: func(c *generator.Context, t *types.Type) bool { - return false - }, - }) - } - - return pkgs -} - -// A single import restriction rule. -type Rule struct { - // All import paths that match this regexp... - SelectorRegexp string - // ... must have one of these prefixes ... - AllowedPrefixes []string - // ... and must not have one of these prefixes. - ForbiddenPrefixes []string -} - -type fileFormat struct { - CurrentImports []string - - Rules []Rule -} - -func readFile(path string) (*fileFormat, error) { - currentBytes, err := ioutil.ReadFile(path) - if err != nil { - return nil, fmt.Errorf("couldn't read %v: %v", path, err) - } - - var current fileFormat - err = json.Unmarshal(currentBytes, ¤t) - if err != nil { - return nil, fmt.Errorf("couldn't unmarshal %v: %v", path, err) - } - return ¤t, nil -} - -func writeFile(path string, ff *fileFormat) error { - raw, err := json.MarshalIndent(ff, "", "\t") - if err != nil { - return fmt.Errorf("couldn't format data for file %v.\n%#v", path, ff) - } - f, err := os.Create(path) - if err != nil { - return fmt.Errorf("couldn't open %v for writing: %v", path, err) - } - defer f.Close() - _, err = f.Write(raw) - return err -} - -// This does the actual checking, since it knows the literal destination file. -type importRuleFile struct{} - -func (importRuleFile) AssembleFile(f *generator.File, path string) error { - return nil -} - -// TODO: make a flag to enable this, or expose this information in some other way. -func (importRuleFile) listEntireImportTree(f *generator.File, path string) error { - // If the file exists, populate its current imports. This is mostly to help - // humans figure out what they need to fix. - if _, err := os.Stat(path); err != nil { - // Ignore packages which haven't opted in by adding an .import-restrictions file. - return nil - } - - current, err := readFile(path) - if err != nil { - return err - } - - current.CurrentImports = []string{} - for v := range f.Imports { - current.CurrentImports = append(current.CurrentImports, v) - } - sort.Strings(current.CurrentImports) - - return writeFile(path, current) -} - -// removeLastDir removes the last directory, but leaves the file name -// unchanged. It returns the new path and the removed directory. So: -// "a/b/c/file" -> ("a/b/file", "c") -func removeLastDir(path string) (newPath, removedDir string) { - dir, file := filepath.Split(path) - dir = strings.TrimSuffix(dir, string(filepath.Separator)) - return filepath.Join(filepath.Dir(dir), file), filepath.Base(dir) -} - -// Keep going up a directory until we find an .import-restrictions file. -func recursiveRead(path string) (*fileFormat, string, error) { - for { - if _, err := os.Stat(path); err == nil { - ff, err := readFile(path) - return ff, path, err - } - - nextPath, removedDir := removeLastDir(path) - if nextPath == path || removedDir == "src" { - break - } - path = nextPath - } - return nil, "", nil -} - -func (importRuleFile) VerifyFile(f *generator.File, path string) error { - rules, actualPath, err := recursiveRead(path) - if err != nil { - return fmt.Errorf("error finding rules file: %v", err) - } - - if rules == nil { - // No restrictions on this directory. - return nil - } - - for _, r := range rules.Rules { - re, err := regexp.Compile(r.SelectorRegexp) - if err != nil { - return fmt.Errorf("regexp `%s` in file %q doesn't compile: %v", r.SelectorRegexp, actualPath, err) - } - for v := range f.Imports { - glog.V(4).Infof("Checking %v matches %v: %v\n", r.SelectorRegexp, v, re.MatchString(v)) - if !re.MatchString(v) { - continue - } - for _, forbidden := range r.ForbiddenPrefixes { - glog.V(4).Infof("Checking %v against %v\n", v, forbidden) - if strings.HasPrefix(v, forbidden) { - return fmt.Errorf("import %v has forbidden prefix %v", v, forbidden) - } - } - found := false - for _, allowed := range r.AllowedPrefixes { - glog.V(4).Infof("Checking %v against %v\n", v, allowed) - if strings.HasPrefix(v, allowed) { - found = true - break - } - } - if !found { - return fmt.Errorf("import %v did not match any allowed prefix", v) - } - } - } - if len(rules.Rules) > 0 { - glog.V(2).Infof("%v passes rules found in %v\n", path, actualPath) - } - - return nil -} - -// importRules produces a file with a set for a single type. -type importRules struct { - myPackage *types.Package - imports namer.ImportTracker -} - -var ( - _ = generator.Generator(&importRules{}) - _ = generator.FileType(importRuleFile{}) -) - -func (r *importRules) Name() string { return "import rules" } -func (r *importRules) Filter(*generator.Context, *types.Type) bool { return false } -func (r *importRules) Namers(*generator.Context) namer.NameSystems { return nil } -func (r *importRules) PackageVars(*generator.Context) []string { return []string{} } -func (r *importRules) PackageConsts(*generator.Context) []string { return []string{} } -func (r *importRules) GenerateType(*generator.Context, *types.Type, io.Writer) error { return nil } -func (r *importRules) Filename() string { return ".import-restrictions" } -func (r *importRules) FileType() string { return importBossFileType } -func (r *importRules) Init(c *generator.Context, w io.Writer) error { return nil } -func (r *importRules) Finalize(c *generator.Context, w io.Writer) error { return nil } - -func dfsImports(dest *[]string, seen map[string]bool, p *types.Package) { - for _, p2 := range p.Imports { - if seen[p2.Path] { - continue - } - seen[p2.Path] = true - dfsImports(dest, seen, p2) - *dest = append(*dest, p2.Path) - } -} - -func (r *importRules) Imports(*generator.Context) []string { - all := []string{} - dfsImports(&all, map[string]bool{}, r.myPackage) - return all -} diff --git a/cmd/libs/go2idl/import-boss/generators/import_restrict_test.go b/cmd/libs/go2idl/import-boss/generators/import_restrict_test.go deleted file mode 100644 index 0d21024ed58..00000000000 --- a/cmd/libs/go2idl/import-boss/generators/import_restrict_test.go +++ /dev/null @@ -1,36 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package generators - -import ( - "testing" -) - -func TestRemoveLastDir(t *testing.T) { - table := map[string]struct{ newPath, removedDir string }{ - "a/b/c": {"a/c", "b"}, - } - for input, expect := range table { - gotPath, gotRemoved := removeLastDir(input) - if e, a := expect.newPath, gotPath; e != a { - t.Errorf("%v: wanted %v, got %v", input, e, a) - } - if e, a := expect.removedDir, gotRemoved; e != a { - t.Errorf("%v: wanted %v, got %v", input, e, a) - } - } -} diff --git a/cmd/libs/go2idl/import-boss/main.go b/cmd/libs/go2idl/import-boss/main.go index c537ba2c636..22f23d1c2ef 100644 --- a/cmd/libs/go2idl/import-boss/main.go +++ b/cmd/libs/go2idl/import-boss/main.go @@ -33,7 +33,7 @@ limitations under the License. // { // "SelectorRegexp": "k8s[.]io", // "AllowedPrefixes": [ -// "k8s.io/kubernetes/cmd/libs/go2idl", +// "k8s.io/gengo/examples", // "k8s.io/kubernetes/third_party" // ], // "ForbiddenPrefixes": [ @@ -59,7 +59,7 @@ import ( "os" "k8s.io/gengo/args" - "k8s.io/kubernetes/cmd/libs/go2idl/import-boss/generators" + "k8s.io/gengo/examples/import-boss/generators" "github.com/golang/glog" ) diff --git a/cmd/libs/go2idl/set-gen/generators/sets.go b/cmd/libs/go2idl/set-gen/generators/sets.go deleted file mode 100644 index 8b4e72fa409..00000000000 --- a/cmd/libs/go2idl/set-gen/generators/sets.go +++ /dev/null @@ -1,364 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package generators has the generators for the set-gen utility. -package generators - -import ( - "io" - - "k8s.io/gengo/args" - "k8s.io/gengo/generator" - "k8s.io/gengo/namer" - "k8s.io/gengo/types" - - "github.com/golang/glog" -) - -// NameSystems returns the name system used by the generators in this package. -func NameSystems() namer.NameSystems { - return namer.NameSystems{ - "public": namer.NewPublicNamer(0), - "private": namer.NewPrivateNamer(0), - "raw": namer.NewRawNamer("", nil), - } -} - -// DefaultNameSystem returns the default name system for ordering the types to be -// processed by the generators in this package. -func DefaultNameSystem() string { - return "public" -} - -// Packages makes the sets package definition. -func Packages(_ *generator.Context, arguments *args.GeneratorArgs) generator.Packages { - boilerplate, err := arguments.LoadGoBoilerplate() - if err != nil { - glog.Fatalf("Failed loading boilerplate: %v", err) - } - - return generator.Packages{&generator.DefaultPackage{ - PackageName: "sets", - PackagePath: arguments.OutputPackagePath, - HeaderText: append(boilerplate, []byte( - ` -// This file was autogenerated by set-gen. Do not edit it manually! - -`)...), - PackageDocumentation: []byte( - `// Package sets has auto-generated set types. -`), - // GeneratorFunc returns a list of generators. Each generator makes a - // single file. - GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { - generators = []generator.Generator{ - // Always generate a "doc.go" file. - generator.DefaultGen{OptionalName: "doc"}, - // Make a separate file for the Empty type, since it's shared by every type. - generator.DefaultGen{ - OptionalName: "empty", - OptionalBody: []byte(emptyTypeDecl), - }, - } - // Since we want a file per type that we generate a set for, we - // have to provide a function for this. - for _, t := range c.Order { - generators = append(generators, &genSet{ - DefaultGen: generator.DefaultGen{ - // Use the privatized version of the - // type name as the file name. - // - // TODO: make a namer that converts - // camelCase to '-' separation for file - // names? - OptionalName: c.Namers["private"].Name(t), - }, - outputPackage: arguments.OutputPackagePath, - typeToMatch: t, - imports: generator.NewImportTracker(), - }) - } - return generators - }, - FilterFunc: func(c *generator.Context, t *types.Type) bool { - // It would be reasonable to filter by the type's package here. - // It might be necessary if your input directory has a big - // import graph. - switch t.Kind { - case types.Map, types.Slice, types.Pointer: - // These types can't be keys in a map. - return false - case types.Builtin: - return true - case types.Struct: - // Only some structs can be keys in a map. This is triggered by the line - // // +genset - // or - // // +genset=true - return extractBoolTagOrDie("genset", t.CommentLines) == true - } - return false - }, - }} -} - -// genSet produces a file with a set for a single type. -type genSet struct { - generator.DefaultGen - outputPackage string - typeToMatch *types.Type - imports namer.ImportTracker -} - -// Filter ignores all but one type because we're making a single file per type. -func (g *genSet) Filter(c *generator.Context, t *types.Type) bool { return t == g.typeToMatch } - -func (g *genSet) Namers(c *generator.Context) namer.NameSystems { - return namer.NameSystems{ - "raw": namer.NewRawNamer(g.outputPackage, g.imports), - } -} - -func (g *genSet) Imports(c *generator.Context) (imports []string) { - return append(g.imports.ImportLines(), "reflect", "sort") -} - -// args constructs arguments for templates. Usage: -// g.args(t, "key1", value1, "key2", value2, ...) -// -// 't' is loaded with the key 'type'. -// -// We could use t directly as the argument, but doing it this way makes it easy -// to mix in additional parameters. This feature is not used in this set -// generator, but is present as an example. -func (g *genSet) args(t *types.Type, kv ...interface{}) interface{} { - m := map[interface{}]interface{}{"type": t} - for i := 0; i < len(kv)/2; i++ { - m[kv[i*2]] = kv[i*2+1] - } - return m -} - -// GenerateType makes the body of a file implementing a set for type t. -func (g *genSet) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { - sw := generator.NewSnippetWriter(w, c, "$", "$") - sw.Do(setCode, g.args(t)) - sw.Do("func less$.type|public$(lhs, rhs $.type|raw$) bool {\n", g.args(t)) - g.lessBody(sw, t) - sw.Do("}\n", g.args(t)) - return sw.Error() -} - -func (g *genSet) lessBody(sw *generator.SnippetWriter, t *types.Type) { - // TODO: make this recursive, handle pointers and multiple nested structs... - switch t.Kind { - case types.Struct: - for _, m := range types.FlattenMembers(t.Members) { - sw.Do("if lhs.$.Name$ < rhs.$.Name$ { return true }\n", m) - sw.Do("if lhs.$.Name$ > rhs.$.Name$ { return false }\n", m) - } - sw.Do("return false\n", nil) - default: - sw.Do("return lhs < rhs\n", nil) - } -} - -// written to the "empty.go" file. -var emptyTypeDecl = ` -// Empty is public since it is used by some internal API objects for conversions between external -// string arrays and internal sets, and conversion logic requires public types today. -type Empty struct{} -` - -// Written for every type. If you've never used text/template before: -// $.type$ refers to the source type; |public means to -// call the function giving the public name, |raw the raw type name. -var setCode = `// sets.$.type|public$ is a set of $.type|raw$s, implemented via map[$.type|raw$]struct{} for minimal memory consumption. -type $.type|public$ map[$.type|raw$]Empty - -// New creates a $.type|public$ from a list of values. -func New$.type|public$(items ...$.type|raw$) $.type|public$ { - ss := $.type|public${} - ss.Insert(items...) - return ss -} - -// $.type|public$KeySet creates a $.type|public$ from a keys of a map[$.type|raw$](? extends interface{}). -// If the value passed in is not actually a map, this will panic. -func $.type|public$KeySet(theMap interface{}) $.type|public$ { - v := reflect.ValueOf(theMap) - ret := $.type|public${} - - for _, keyValue := range v.MapKeys() { - ret.Insert(keyValue.Interface().($.type|raw$)) - } - return ret -} - -// Insert adds items to the set. -func (s $.type|public$) Insert(items ...$.type|raw$) { - for _, item := range items { - s[item] = Empty{} - } -} - -// Delete removes all items from the set. -func (s $.type|public$) Delete(items ...$.type|raw$) { - for _, item := range items { - delete(s, item) - } -} - -// Has returns true if and only if item is contained in the set. -func (s $.type|public$) Has(item $.type|raw$) bool { - _, contained := s[item] - return contained -} - -// HasAll returns true if and only if all items are contained in the set. -func (s $.type|public$) HasAll(items ...$.type|raw$) bool { - for _, item := range items { - if !s.Has(item) { - return false - } - } - return true -} - -// HasAny returns true if any items are contained in the set. -func (s $.type|public$) HasAny(items ...$.type|raw$) bool { - for _, item := range items { - if s.Has(item) { - return true - } - } - return false -} - -// Difference returns a set of objects that are not in s2 -// For example: -// s1 = {a1, a2, a3} -// s2 = {a1, a2, a4, a5} -// s1.Difference(s2) = {a3} -// s2.Difference(s1) = {a4, a5} -func (s $.type|public$) Difference(s2 $.type|public$) $.type|public$ { - result := New$.type|public$() - for key := range s { - if !s2.Has(key) { - result.Insert(key) - } - } - return result -} - -// Union returns a new set which includes items in either s1 or s2. -// For example: -// s1 = {a1, a2} -// s2 = {a3, a4} -// s1.Union(s2) = {a1, a2, a3, a4} -// s2.Union(s1) = {a1, a2, a3, a4} -func (s1 $.type|public$) Union(s2 $.type|public$) $.type|public$ { - result := New$.type|public$() - for key := range s1 { - result.Insert(key) - } - for key := range s2 { - result.Insert(key) - } - return result -} - -// Intersection returns a new set which includes the item in BOTH s1 and s2 -// For example: -// s1 = {a1, a2} -// s2 = {a2, a3} -// s1.Intersection(s2) = {a2} -func (s1 $.type|public$) Intersection(s2 $.type|public$) $.type|public$ { - var walk, other $.type|public$ - result := New$.type|public$() - if s1.Len() < s2.Len() { - walk = s1 - other = s2 - } else { - walk = s2 - other = s1 - } - for key := range walk { - if other.Has(key) { - result.Insert(key) - } - } - return result -} - -// IsSuperset returns true if and only if s1 is a superset of s2. -func (s1 $.type|public$) IsSuperset(s2 $.type|public$) bool { - for item := range s2 { - if !s1.Has(item) { - return false - } - } - return true -} - -// Equal returns true if and only if s1 is equal (as a set) to s2. -// Two sets are equal if their membership is identical. -// (In practice, this means same elements, order doesn't matter) -func (s1 $.type|public$) Equal(s2 $.type|public$) bool { - return len(s1) == len(s2) && s1.IsSuperset(s2) -} - -type sortableSliceOf$.type|public$ []$.type|raw$ - -func (s sortableSliceOf$.type|public$) Len() int { return len(s) } -func (s sortableSliceOf$.type|public$) Less(i, j int) bool { return less$.type|public$(s[i], s[j]) } -func (s sortableSliceOf$.type|public$) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -// List returns the contents as a sorted $.type|raw$ slice. -func (s $.type|public$) List() []$.type|raw$ { - res := make(sortableSliceOf$.type|public$, 0, len(s)) - for key := range s { - res = append(res, key) - } - sort.Sort(res) - return []$.type|raw$(res) -} - -// UnsortedList returns the slice with contents in random order. -func (s $.type|public$) UnsortedList() []$.type|raw$ { - res :=make([]$.type|raw$, 0, len(s)) - for key := range s { - res = append(res, key) - } - return res -} - -// Returns a single element from the set. -func (s $.type|public$) PopAny() ($.type|raw$, bool) { - for key := range s { - s.Delete(key) - return key, true - } - var zeroValue $.type|raw$ - return zeroValue, false -} - -// Len returns the size of the set. -func (s $.type|public$) Len() int { - return len(s) -} - -` diff --git a/cmd/libs/go2idl/set-gen/generators/tags.go b/cmd/libs/go2idl/set-gen/generators/tags.go deleted file mode 100644 index 34aa77231fa..00000000000 --- a/cmd/libs/go2idl/set-gen/generators/tags.go +++ /dev/null @@ -1,33 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package generators - -import ( - "github.com/golang/glog" - "k8s.io/gengo/types" -) - -// extractBoolTagOrDie gets the comment-tags for the key and asserts that, if -// it exists, the value is boolean. If the tag did not exist, it returns -// false. -func extractBoolTagOrDie(key string, lines []string) bool { - val, err := types.ExtractSingleBoolCommentTag("+", key, false, lines) - if err != nil { - glog.Fatalf(err.Error()) - } - return val -} diff --git a/cmd/libs/go2idl/set-gen/main.go b/cmd/libs/go2idl/set-gen/main.go index b0462d93f8d..431e11db9d7 100644 --- a/cmd/libs/go2idl/set-gen/main.go +++ b/cmd/libs/go2idl/set-gen/main.go @@ -28,7 +28,7 @@ import ( "os" "k8s.io/gengo/args" - "k8s.io/kubernetes/cmd/libs/go2idl/set-gen/generators" + "k8s.io/gengo/examples/set-gen/generators" "github.com/golang/glog" )