func (g *genFakeForGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") const pkgTestingCore = "k8s.io/kubernetes/pkg/client/testing/core" m := map[string]interface{}{ "group": g.group, "Group": namer.IC(g.group), "Fake": c.Universe.Type(types.Name{Package: pkgTestingCore, Name: "Fake"}), } sw.Do(groupClientTemplate, m) for _, t := range g.types { wrapper := map[string]interface{}{ "type": t, "Group": namer.IC(g.group), "realClientPackage": filepath.Base(g.realClientPath), } namespaced := !(types.ExtractCommentTags("+", t.SecondClosestCommentLines)["nonNamespaced"] == "true") if namespaced { sw.Do(getterImplNamespaced, wrapper) } else { sw.Do(getterImplNonNamespaced, wrapper) } } return sw.Error() }
func (g *genClientset) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { // TODO: We actually don't need any type information to generate the clientset, // perhaps we can adapt the go2ild framework to this kind of usage. sw := generator.NewSnippetWriter(w, c, "$", "$") sw.Do(common, nil) sw.Do(checkImpl, nil) type arg struct { Group string PackageName string } allGroups := []arg{} for _, gv := range g.groupVersions { group := normalization.Group(gv.Group) version := normalization.Version(gv.Version) allGroups = append(allGroups, arg{namer.IC(group), version + group}) } for _, g := range allGroups { sw.Do(clientsetInterfaceImplTemplate, g) } return sw.Error() }
// GenerateType makes the body of a file implementing a set for type t. func (g *genProtoIDL) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") b := bodyGen{ locator: &protobufLocator{ namer: c.Namers["proto"].(ProtobufFromGoNamer), tracker: g.imports, universe: c.Universe, localGoPackage: g.localGoPackage.Package, }, localPackage: g.localPackage, omitGogo: g.omitGogo, omitFieldTypes: g.omitFieldTypes, t: t, } switch t.Kind { case types.Alias: return b.doAlias(sw) case types.Struct: return b.doStruct(sw) default: return b.unknown(sw) } }
func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") const pkgUnversioned = "k8s.io/kubernetes/pkg/client/unversioned" const pkgLatest = "k8s.io/kubernetes/pkg/api/latest" m := map[string]interface{}{ "group": g.group, "Group": namer.IC(g.group), "types": g.types, "Config": c.Universe.Get(types.Name{Package: pkgUnversioned, Name: "Config"}), "DefaultKubernetesUserAgent": c.Universe.Get(types.Name{Package: pkgUnversioned, Name: "DefaultKubernetesUserAgent"}), "RESTClient": c.Universe.Get(types.Name{Package: pkgUnversioned, Name: "RESTClient"}), "RESTClientFor": c.Universe.Get(types.Name{Package: pkgUnversioned, Name: "RESTClientFor"}), "latestGroup": c.Universe.Get(types.Name{Package: pkgLatest, Name: "Group"}), "GroupOrDie": c.Universe.Get(types.Name{Package: pkgLatest, Name: "GroupOrDie"}), } sw.Do(groupInterfaceTemplate, m) sw.Do(groupClientTemplate, m) for _, t := range g.types { wrapper := map[string]interface{}{ "type": t, "Group": namer.IC(g.group), } sw.Do(namespacerImplTemplate, wrapper) } sw.Do(newClientTemplate, m) sw.Do(newClientOrDieTemplate, m) sw.Do(setClientDefaultsTemplate, m) return sw.Error() }
func (g *genExpansion) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") for _, t := range g.types { sw.Do(expansionInterfaceTemplate, t) } return sw.Error() }
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) g.globalVariables = map[string]interface{}{ "Cloner": 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) scheme := c.Universe.Variable(types.Name{Package: apiPackagePath, Name: "Scheme"}) g.imports.AddType(scheme) g.globalVariables["scheme"] = scheme sw := generator.NewSnippetWriter(w, c, "$", "$") sw.Do("func init() {\n", nil) sw.Do("if err := $.scheme|raw$.AddGeneratedDeepCopyFuncs(\n", map[string]interface{}{ "scheme": scheme, }) for _, t := range g.typesForInit { sw.Do(fmt.Sprintf("%s,\n", g.funcNameTmpl(t)), argsFromType(t)) } sw.Do("); err != nil {\n", nil) sw.Do("// if one of the deep copy functions is malformed, detect it immediately.\n", nil) sw.Do("panic(err)\n", nil) sw.Do("}\n", nil) sw.Do("}\n\n", nil) return sw.Error() }
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 *genConversion) Init(c *generator.Context, w io.Writer) error { scheme := c.Universe.Variable(types.Name{Package: apiPackagePath, Name: "Scheme"}) g.imports.AddType(scheme) scope := c.Universe.Type(types.Name{Package: conversionPackagePath, Name: "Scope"}) g.imports.AddType(scope) g.globalVariables = map[string]interface{}{ "scheme": scheme, "Scope": scope, } sw := generator.NewSnippetWriter(w, c, "$", "$") sw.Do("func init() {\n", nil) sw.Do("if err := $.scheme|raw$.AddGeneratedConversionFuncs(\n", map[string]interface{}{ "scheme": scheme, }) for _, conv := range g.typesForInit { funcName := g.funcNameTmpl(conv.inType, conv.outType) sw.Do(fmt.Sprintf("%s,\n", funcName), argsFromType(conv.inType, conv.outType)) } sw.Do("); err != nil {\n", nil) sw.Do("// if one of the conversion functions is malformed, detect it immediately.\n", nil) sw.Do("panic(err)\n", nil) sw.Do("}\n", nil) sw.Do("}\n\n", nil) return sw.Error() }
// GenerateType makes the body of a file implementing a set for type t. func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") pkg := filepath.Base(t.Name.Package) m := map[string]interface{}{ "type": t, "package": pkg, "Package": namer.IC(pkg), "Group": namer.IC(g.group), "watchInterface": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/watch", Name: "Interface"}), "apiDeleteOptions": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "DeleteOptions"}), "apiListOptions": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "ListOptions"}), } sw.Do(namespacerTemplate, m) sw.Do(interfaceTemplate, m) sw.Do(structTemplate, m) sw.Do(newStructTemplate, m) sw.Do(createTemplate, m) sw.Do(updateTemplate, m) sw.Do(deleteTemplate, m) sw.Do(deleteCollectionTemplate, m) sw.Do(getTemplate, m) sw.Do(listTemplate, m) sw.Do(watchTemplate, m) return sw.Error() }
func (g *genClientset) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { // TODO: We actually don't need any type information to generate the clientset, // perhaps we can adapt the go2ild framework to this kind of usage. sw := generator.NewSnippetWriter(w, c, "$", "$") const pkgUnversioned = "k8s.io/kubernetes/pkg/client/unversioned" type arg struct { Group string PackageName string } allGroups := []arg{} for _, gv := range g.groupVersions { group := normalizeGroup(gv.Group) version := normalizeVersion(gv.Version) allGroups = append(allGroups, arg{namer.IC(group), group + "_" + version}) } m := map[string]interface{}{ "allGroups": allGroups, "Config": c.Universe.Type(types.Name{Package: pkgUnversioned, Name: "Config"}), "DefaultKubernetesUserAgent": c.Universe.Function(types.Name{Package: pkgUnversioned, Name: "DefaultKubernetesUserAgent"}), "RESTClient": c.Universe.Type(types.Name{Package: pkgUnversioned, Name: "RESTClient"}), } sw.Do(clientsetInterfaceTemplate, m) sw.Do(clientsetTemplate, m) for _, g := range allGroups { sw.Do(clientsetInterfaceImplTemplate, g) } sw.Do(newClientsetForConfigTemplate, m) sw.Do(newClientsetForConfigOrDieTemplate, m) sw.Do(newClientsetForRESTClientTemplate, m) return sw.Error() }
func (g *genConversion) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { glog.V(5).Infof("generating for type %v", t) sw := generator.NewSnippetWriter(w, c, "$", "$") peerType := getPeerTypeFor(c, t, g.peerPackages) didForward, didBackward := false, false if isDirectlyConvertible(t, peerType, g.manualConversions) { didForward = true g.generateConversion(t, peerType, sw) } if isDirectlyConvertible(peerType, t, g.manualConversions) { didBackward = true g.generateConversion(peerType, t, sw) } if didForward != didBackward { glog.Fatalf("Could only generate one direction of conversion for %v <-> %v", t, peerType) } if !didForward && !didBackward { // TODO: This should be fatal but we have at least 8 types that // currently fail this. The right thing to do is to figure out why they // can't be generated and mark those fields as // +k8s:conversion-gen=false, and ONLY do manual conversions for those // fields, with the manual Convert_...() calling autoConvert_...() // first. glog.Errorf("Warning: could not generate autoConvert functions for %v <-> %v", t, peerType) } return sw.Error() }
// GenerateType makes the body of a file implementing the individual typed client for type t. func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") pkg := filepath.Base(t.Name.Package) namespaced := !(types.ExtractCommentTags("+", t.SecondClosestCommentLines)["nonNamespaced"] == "true") m := map[string]interface{}{ "type": t, "package": pkg, "Package": namer.IC(pkg), "Group": namer.IC(g.group), "watchInterface": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/watch", Name: "Interface"}), "apiDeleteOptions": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "DeleteOptions"}), "apiListOptions": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "ListOptions"}), "apiParameterCodec": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "ParameterCodec"}), "namespaced": namespaced, } sw.Do(getterComment, m) if namespaced { sw.Do(getterNamesapced, m) } else { sw.Do(getterNonNamesapced, m) } noMethods := types.ExtractCommentTags("+", t.SecondClosestCommentLines)["noMethods"] == "true" sw.Do(interfaceTemplate1, m) if !noMethods { sw.Do(interfaceTemplate2, m) // Include the UpdateStatus method if the type has a status if hasStatus(t) { sw.Do(interfaceUpdateStatusTemplate, m) } sw.Do(interfaceTemplate3, m) } sw.Do(interfaceTemplate4, m) if namespaced { sw.Do(structNamespaced, m) sw.Do(newStructNamespaced, m) } else { sw.Do(structNonNamespaced, m) sw.Do(newStructNonNamespaced, m) } if !noMethods { sw.Do(createTemplate, m) sw.Do(updateTemplate, m) // Generate the UpdateStatus method if the type has a status if hasStatus(t) { sw.Do(updateStatusTemplate, m) } sw.Do(deleteTemplate, m) sw.Do(deleteCollectionTemplate, m) sw.Do(getTemplate, m) sw.Do(listTemplate, m) sw.Do(watchTemplate, m) } return sw.Error() }
// GenerateType makes the body of a file implementing a set for type t. func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") sw.Do("func deepCopy_$.|public$(in $.|raw$, out *$.|raw$, c *conversion.Cloner) error {\n", t) g.generateFor(t, sw) sw.Do("return nil\n", nil) sw.Do("}\n\n", nil) return sw.Error() }
// 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 *genExpansion) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") for _, t := range g.types { if _, err := os.Stat(filepath.Join(g.groupPath, strings.ToLower(t.Name.Name+"_expansion.go"))); os.IsNotExist(err) { sw.Do(expansionInterfaceTemplate, t) } } return sw.Error() }
func (g *openAPIGen) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { glog.V(5).Infof("generating for type %v", t) sw := generator.NewSnippetWriter(w, c, "$", "$") err := newOpenAPITypeWriter(sw).generate(t) if err != nil { return err } return sw.Error() }
func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") funcName := g.funcNameTmpl(t) sw.Do(fmt.Sprintf("func %s(in $.type|raw$, out *$.type|raw$, c *$.Cloner|raw$) error {\n", funcName), g.withGlobals(argsFromType(t))) g.generateFor(t, sw) sw.Do("return nil\n", nil) sw.Do("}\n\n", nil) return sw.Error() }
func TestSnippetWriter(t *testing.T) { var structTest = map[string]string{ "base/foo/proto/foo.go": ` package foo // Blah is a test. // A test, I tell you. type Blah struct { // A is the first field. A int64 ` + "`" + `json:"a"` + "`" + ` // B is the second field. // Multiline comments work. B string ` + "`" + `json:"b"` + "`" + ` } `, } c := construct(t, structTest) b := &bytes.Buffer{} err := generator.NewSnippetWriter(b, c, "$", "$"). Do("$.|public$$.|private$", c.Order[0]). Error() if err != nil { t.Errorf("Unexpected error %v", err) } if e, a := "Blahblah", b.String(); e != a { t.Errorf("Expected %q, got %q", e, a) } err = generator.NewSnippetWriter(b, c, "$", "$"). Do("$.|public", c.Order[0]). Error() if err == nil { t.Errorf("expected error on invalid template") } else { // Dear reader, I apologize for making the worst change // detection test in the history of ever. if e, a := "unclosed action", err.Error(); !strings.Contains(a, e) { t.Errorf("Expected %q but didn't find it in %q", e, a) } } }
func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") const pkgUnversioned = "k8s.io/kubernetes/pkg/client/unversioned" const pkgRegistered = "k8s.io/kubernetes/pkg/apimachinery/registered" const pkgAPI = "k8s.io/kubernetes/pkg/api" apiPath := func(group string) string { if group == "legacy" { return `"/api"` } return `"/apis"` } canonize := func(group string) string { if group == "legacy" { return "" } return group } m := map[string]interface{}{ "group": g.group, "Group": namer.IC(g.group), "canonicalGroup": canonize(g.group), "types": g.types, "Config": c.Universe.Type(types.Name{Package: pkgUnversioned, Name: "Config"}), "DefaultKubernetesUserAgent": c.Universe.Function(types.Name{Package: pkgUnversioned, Name: "DefaultKubernetesUserAgent"}), "RESTClient": c.Universe.Type(types.Name{Package: pkgUnversioned, Name: "RESTClient"}), "RESTClientFor": c.Universe.Function(types.Name{Package: pkgUnversioned, Name: "RESTClientFor"}), "latestGroup": c.Universe.Variable(types.Name{Package: pkgRegistered, Name: "Group"}), "GroupOrDie": c.Universe.Variable(types.Name{Package: pkgRegistered, Name: "GroupOrDie"}), "apiPath": apiPath(g.group), "codecs": c.Universe.Variable(types.Name{Package: pkgAPI, Name: "Codecs"}), } sw.Do(groupInterfaceTemplate, m) sw.Do(groupClientTemplate, m) for _, t := range g.types { wrapper := map[string]interface{}{ "type": t, "Group": namer.IC(g.group), } namespaced := !(types.ExtractCommentTags("+", t.SecondClosestCommentLines)["nonNamespaced"] == "true") if namespaced { sw.Do(getterImplNamespaced, wrapper) } else { sw.Do(getterImplNonNamespaced, wrapper) } } sw.Do(newClientForConfigTemplate, m) sw.Do(newClientForConfigOrDieTemplate, m) sw.Do(newClientForRESTClientTemplate, m) sw.Do(setClientDefaultsTemplate, m) return sw.Error() }
func (g *genConversion) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") internalType, _ := getInternalTypeFor(c, t) if isDirectlyConvertible(t, internalType, g.preexisting) { g.generateConversion(t, internalType, sw) } if isDirectlyConvertible(internalType, t, g.preexisting) { g.generateConversion(internalType, t, sw) } return sw.Error() }
func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") funcName := g.funcNameTmpl(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) sw.Do("return nil\n", nil) sw.Do("}\n\n", nil) return sw.Error() }
func (g *genDeepCopy) Init(c *generator.Context, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") sw.Do("func init() {\n", nil) sw.Do("if err := api.Scheme.AddGeneratedDeepCopyFuncs(\n", nil) for _, t := range g.typesForInit { sw.Do("deepCopy_$.|public$,\n", t) } sw.Do("); err != nil {\n", nil) sw.Do("// if one of the deep copy functions is malformed, detect it immediately.\n", nil) sw.Do("panic(err)\n", nil) sw.Do("}\n", nil) sw.Do("}\n\n", nil) return sw.Error() }
// Returns all already existing conversion functions that we are able to find. func existingConversionFunctions(context *generator.Context) conversions { scopeName := types.Name{Package: conversionPackagePath, Name: "Scope"} errorName := types.Name{Package: "", Name: "error"} buffer := &bytes.Buffer{} sw := generator.NewSnippetWriter(buffer, context, "$", "$") preexisting := make(conversions) for _, p := range context.Universe { for _, f := range p.Functions { if f.Underlying == nil || f.Underlying.Kind != types.Func { glog.Errorf("Malformed function: %#v", f) continue } if f.Underlying.Signature == nil { glog.Errorf("Function without signature: %#v", f) continue } signature := f.Underlying.Signature // Check whether the function is conversion function. // Note that all of them have signature: // func Convert_inType_To_outType(inType, outType, conversion.Scope) error if signature.Receiver != nil { continue } if len(signature.Parameters) != 3 || signature.Parameters[2].Name != scopeName { continue } if len(signature.Results) != 1 || signature.Results[0].Name != errorName { continue } inType := signature.Parameters[0] outType := signature.Parameters[1] if inType.Kind != types.Pointer || outType.Kind != types.Pointer { continue } // Now check if the name satisfies the convention. args := argsFromType(inType.Elem, outType.Elem) sw.Do("Convert_$.inType|public$_To_$.outType|public$", args) if f.Name.Name == buffer.String() { key := conversionType{inType.Elem, outType.Elem} if v, ok := preexisting[key]; ok && v != nil { panic(fmt.Sprintf("duplicate static conversion defined: %#v", key)) } preexisting[key] = f } buffer.Reset() } } return preexisting }
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, "$", "$") funcName := g.funcNameTmpl(t) sw.Do(fmt.Sprintf("func %s(in interface{}, out interface{}, c *$.Cloner|raw$) error {{\n", funcName), g.withGlobals(argsFromType(t))) sw.Do("in := in.(*$.type|raw$)\nout := out.(*$.type|raw$)\n", g.withGlobals(argsFromType(t))) g.generateFor(t, sw) sw.Do("return nil\n", nil) sw.Do("}}\n\n", nil) return sw.Error() }
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() }
// Returns all manually-defined conversion functions in the package. func getManualConversionFunctions(context *generator.Context, pkg *types.Package, manualMap conversionFuncMap) { scopeName := types.Ref(conversionPackagePath, "Scope").Name errorName := types.Ref("", "error").Name buffer := &bytes.Buffer{} sw := generator.NewSnippetWriter(buffer, context, "$", "$") for _, f := range pkg.Functions { if f.Underlying == nil || f.Underlying.Kind != types.Func { glog.Errorf("Malformed function: %#v", f) continue } if f.Underlying.Signature == nil { glog.Errorf("Function without signature: %#v", f) continue } signature := f.Underlying.Signature // Check whether the function is conversion function. // Note that all of them have signature: // func Convert_inType_To_outType(inType, outType, conversion.Scope) error if signature.Receiver != nil { continue } if len(signature.Parameters) != 3 || signature.Parameters[2].Name != scopeName { continue } if len(signature.Results) != 1 || signature.Results[0].Name != errorName { continue } inType := signature.Parameters[0] outType := signature.Parameters[1] if inType.Kind != types.Pointer || outType.Kind != types.Pointer { continue } // Now check if the name satisfies the convention. args := argsFromType(inType.Elem, outType.Elem) sw.Do("Convert_$.inType|public$_To_$.outType|public$", args) if f.Name.Name == buffer.String() { key := conversionPair{inType.Elem, outType.Elem} // We might scan the same package twice, and that's OK. if v, ok := manualMap[key]; ok && v != nil && v.Name.Package != pkg.Path { panic(fmt.Sprintf("duplicate static conversion defined: %#v", key)) } manualMap[key] = f } buffer.Reset() } }
func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") const pkgUnversioned = "k8s.io/kubernetes/pkg/client/unversioned" const pkgLatest = "k8s.io/kubernetes/pkg/api/latest" prefix := func(group string) string { if group == "legacy" { return `"/api"` } return `"/apis"` } canonize := func(group string) string { if group == "legacy" { return "" } return group } m := map[string]interface{}{ "group": g.group, "Group": namer.IC(g.group), "canonicalGroup": canonize(g.group), "types": g.types, "Config": c.Universe.Type(types.Name{Package: pkgUnversioned, Name: "Config"}), "DefaultKubernetesUserAgent": c.Universe.Function(types.Name{Package: pkgUnversioned, Name: "DefaultKubernetesUserAgent"}), "RESTClient": c.Universe.Type(types.Name{Package: pkgUnversioned, Name: "RESTClient"}), "RESTClientFor": c.Universe.Function(types.Name{Package: pkgUnversioned, Name: "RESTClientFor"}), "latestGroup": c.Universe.Variable(types.Name{Package: pkgLatest, Name: "Group"}), "GroupOrDie": c.Universe.Variable(types.Name{Package: pkgLatest, Name: "GroupOrDie"}), "prefix": prefix(g.group), } sw.Do(groupInterfaceTemplate, m) sw.Do(groupClientTemplate, m) for _, t := range g.types { wrapper := map[string]interface{}{ "type": t, "Group": namer.IC(g.group), } sw.Do(namespacerImplTemplate, wrapper) } sw.Do(newClientForConfigTemplate, m) sw.Do(newClientForConfigOrDieTemplate, m) sw.Do(newClientForRESTClientTemplate, m) sw.Do(setClientDefaultsTemplate, m) return sw.Error() }
// Returns all already existing defaulting functions that we are able to find. func existingDefaultingFunctions(context *generator.Context) defaulters { buffer := &bytes.Buffer{} sw := generator.NewSnippetWriter(buffer, context, "$", "$") preexisting := make(defaulters) for _, p := range context.Universe { for _, f := range p.Functions { if f.Underlying == nil || f.Underlying.Kind != types.Func { glog.Errorf("Malformed function: %#v", f) continue } if f.Underlying.Signature == nil { glog.Errorf("Function without signature: %#v", f) continue } signature := f.Underlying.Signature // Check whether the function is conversion function. // Note that all of them have signature: // func Convert_inType_To_outType(inType, outType, conversion.Scope) error if signature.Receiver != nil { continue } if len(signature.Parameters) != 1 { continue } if len(signature.Results) != 0 { continue } inType := signature.Parameters[0] if inType.Kind != types.Pointer { continue } // Now check if the name satisfies the convention. args := defaultingArgsFromType(inType.Elem) sw.Do("$.inType|defaultfn$", args) if f.Name.Name == buffer.String() { key := inType.Elem if v, ok := preexisting[key]; ok && v != nil { panic(fmt.Sprintf("duplicate static defaulter defined: %#v", key)) } preexisting[key] = f } buffer.Reset() } } return preexisting }
func (g *genDeepCopy) Init(c *generator.Context, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") sw.Do("func init() {\n", nil) if g.targetPackage == apiPackagePath { sw.Do("if err := Scheme.AddGeneratedDeepCopyFuncs(\n", nil) } else { sw.Do("if err := api.Scheme.AddGeneratedDeepCopyFuncs(\n", nil) } for _, t := range g.typesForInit { sw.Do(fmt.Sprintf("%s,\n", g.funcNameTmpl(t)), argsFromType(t)) } sw.Do("); err != nil {\n", nil) sw.Do("// if one of the deep copy functions is malformed, detect it immediately.\n", nil) sw.Do("panic(err)\n", nil) sw.Do("}\n", nil) sw.Do("}\n\n", nil) return sw.Error() }
func (g *genConversion) Init(c *generator.Context, w io.Writer) error { sw := generator.NewSnippetWriter(w, c, "$", "$") sw.Do("func init() {\n", nil) if g.targetPackage == apiPackagePath { sw.Do("if err := Scheme.AddGeneratedConversionFuncs(\n", nil) } else { sw.Do("if err := api.Scheme.AddGeneratedConversionFuncs(\n", nil) } for _, conv := range g.typesForInit { funcName := g.funcNameTmpl(conv.inType, conv.outType) sw.Do(fmt.Sprintf("%s,\n", funcName), argsFromType(conv.inType, conv.outType)) } sw.Do("); err != nil {\n", nil) sw.Do("// if one of the conversion functions is malformed, detect it immediately.\n", nil) sw.Do("panic(err)\n", nil) sw.Do("}\n", nil) sw.Do("}\n\n", nil) return sw.Error() }