mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
Merge pull request #30387 from lavalamp/refactor-generators
Automatic merge from submit-queue Refactor generators Extracting pure refactoring out of #25526 so I don't have to do it for a 4th time. This makes no changes to the output of the generators. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.kubernetes.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.kubernetes.io/reviews/kubernetes/kubernetes/30387) <!-- Reviewable:end -->
This commit is contained in:
commit
475f6c5ef6
@ -104,8 +104,8 @@ type conversionFuncMap map[conversionPair]*types.Type
|
||||
|
||||
// Returns all manually-defined conversion functions in the package.
|
||||
func getManualConversionFunctions(context *generator.Context, pkg *types.Package, manualMap conversionFuncMap) {
|
||||
scopeName := types.Name{Package: conversionPackagePath, Name: "Scope"}
|
||||
errorName := types.Name{Package: "", Name: "error"}
|
||||
scopeName := types.Ref(conversionPackagePath, "Scope").Name
|
||||
errorName := types.Ref("", "error").Name
|
||||
buffer := &bytes.Buffer{}
|
||||
sw := generator.NewSnippetWriter(buffer, context, "$", "$")
|
||||
|
||||
@ -409,8 +409,6 @@ type genConversion struct {
|
||||
manualDefaulters defaulterFuncMap
|
||||
imports namer.ImportTracker
|
||||
typesForInit []conversionPair
|
||||
|
||||
globalVariables map[string]interface{}
|
||||
}
|
||||
|
||||
func NewGenConversion(sanitizedName, targetPackage string, manualConversions conversionFuncMap, manualDefaulters defaulterFuncMap, peerPkgs []string) generator.Generator {
|
||||
@ -429,7 +427,23 @@ func NewGenConversion(sanitizedName, targetPackage string, manualConversions con
|
||||
|
||||
func (g *genConversion) 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)}
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.targetPackage, g.imports),
|
||||
"publicIT": &namerPlusImportTracking{
|
||||
delegate: conversionNamer(),
|
||||
tracker: g.imports,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type namerPlusImportTracking struct {
|
||||
delegate namer.Namer
|
||||
tracker namer.ImportTracker
|
||||
}
|
||||
|
||||
func (n *namerPlusImportTracking) Name(t *types.Type) string {
|
||||
n.tracker.AddType(t)
|
||||
return n.delegate.Name(t)
|
||||
}
|
||||
|
||||
func (g *genConversion) convertibleOnlyWithinPackage(inType, outType *types.Type) bool {
|
||||
@ -506,33 +520,20 @@ func (g *genConversion) Imports(c *generator.Context) (imports []string) {
|
||||
return importLines
|
||||
}
|
||||
|
||||
func (g *genConversion) withGlobals(args map[string]interface{}) map[string]interface{} {
|
||||
for k, v := range g.globalVariables {
|
||||
if _, ok := args[k]; !ok {
|
||||
args[k] = v
|
||||
}
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func argsFromType(inType, outType *types.Type) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
func argsFromType(inType, outType *types.Type) generator.Args {
|
||||
return generator.Args{
|
||||
"inType": inType,
|
||||
"outType": outType,
|
||||
}
|
||||
}
|
||||
|
||||
func defaultingArgsFromType(inType *types.Type) interface{} {
|
||||
return map[string]interface{}{
|
||||
func defaultingArgsFromType(inType *types.Type) generator.Args {
|
||||
return generator.Args{
|
||||
"inType": inType,
|
||||
}
|
||||
}
|
||||
func (g *genConversion) funcNameTmpl(inType, outType *types.Type) string {
|
||||
tmpl := "Convert_$.inType|public$_To_$.outType|public$"
|
||||
g.imports.AddType(inType)
|
||||
g.imports.AddType(outType)
|
||||
return tmpl
|
||||
}
|
||||
|
||||
const nameTmpl = "Convert_$.inType|publicIT$_To_$.outType|publicIT$"
|
||||
|
||||
func (g *genConversion) preexists(inType, outType *types.Type) (*types.Type, bool) {
|
||||
function, ok := g.manualConversions[conversionPair{inType, outType}]
|
||||
@ -540,23 +541,15 @@ func (g *genConversion) preexists(inType, outType *types.Type) (*types.Type, boo
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
scheme := c.Universe.Package(apiPackagePath).Variable("Scheme")
|
||||
|
||||
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
||||
sw.Do("func init() {\n", nil)
|
||||
sw.Do("if err := $.scheme|raw$.AddGeneratedConversionFuncs(\n", map[string]interface{}{
|
||||
sw.Do("if err := $.scheme|raw$.AddGeneratedConversionFuncs(\n", generator.Args{
|
||||
"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(nameTmpl+",\n", 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)
|
||||
@ -595,9 +588,10 @@ func (g *genConversion) GenerateType(c *generator.Context, t *types.Type, w io.W
|
||||
}
|
||||
|
||||
func (g *genConversion) generateConversion(inType, outType *types.Type, sw *generator.SnippetWriter) {
|
||||
funcName := g.funcNameTmpl(inType, outType)
|
||||
args := argsFromType(inType, outType).
|
||||
With("Scope", types.Ref(conversionPackagePath, "Scope"))
|
||||
|
||||
sw.Do(fmt.Sprintf("func auto%s(in *$.inType|raw$, out *$.outType|raw$, s $.Scope|raw$) error {\n", funcName), g.withGlobals(argsFromType(inType, outType)))
|
||||
sw.Do("func auto"+nameTmpl+"(in *$.inType|raw$, out *$.outType|raw$, s $.Scope|raw$) error {\n", args)
|
||||
// if no defaulter of form SetDefaults_XXX is defined, do not inline a check for defaulting.
|
||||
if function, ok := g.manualDefaulters[inType]; ok {
|
||||
sw.Do("$.|raw$(in)\n", function)
|
||||
@ -608,8 +602,8 @@ func (g *genConversion) generateConversion(inType, outType *types.Type, sw *gene
|
||||
|
||||
// If there is no public manual Conversion method, generate it.
|
||||
if _, ok := g.preexists(inType, outType); !ok {
|
||||
sw.Do(fmt.Sprintf("func %s(in *$.inType|raw$, out *$.outType|raw$, s $.Scope|raw$) error {\n", funcName), g.withGlobals(argsFromType(inType, outType)))
|
||||
sw.Do(fmt.Sprintf("return auto%s(in, out, s)\n", funcName), argsFromType(inType, outType))
|
||||
sw.Do("func "+nameTmpl+"(in *$.inType|raw$, out *$.outType|raw$, s $.Scope|raw$) error {\n", args)
|
||||
sw.Do("return auto"+nameTmpl+"(in, out, s)\n", args)
|
||||
sw.Do("}\n\n", nil)
|
||||
}
|
||||
}
|
||||
@ -666,8 +660,7 @@ func (g *genConversion) doMap(inType, outType *types.Type, sw *generator.Snippet
|
||||
if function, ok := g.preexists(inType.Elem, outType.Elem); ok {
|
||||
sw.Do("if err := $.|raw$(&val, newVal, s); err != nil {\n", function)
|
||||
} else if g.convertibleOnlyWithinPackage(inType.Elem, outType.Elem) {
|
||||
funcName := g.funcNameTmpl(inType.Elem, outType.Elem)
|
||||
sw.Do(fmt.Sprintf("if err := %s(&val, newVal, s); err != nil {\n", funcName), argsFromType(inType.Elem, outType.Elem))
|
||||
sw.Do("if err := "+nameTmpl+"(&val, newVal, s); err != nil {\n", argsFromType(inType.Elem, outType.Elem))
|
||||
} else {
|
||||
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
||||
sw.Do("if err := s.Convert(&val, newVal, 0); err != nil {\n", nil)
|
||||
@ -704,8 +697,7 @@ func (g *genConversion) doSlice(inType, outType *types.Type, sw *generator.Snipp
|
||||
if function, ok := g.preexists(inType.Elem, outType.Elem); ok {
|
||||
sw.Do("if err := $.|raw$(&(*in)[i], &(*out)[i], s); err != nil {\n", function)
|
||||
} else if g.convertibleOnlyWithinPackage(inType.Elem, outType.Elem) {
|
||||
funcName := g.funcNameTmpl(inType.Elem, outType.Elem)
|
||||
sw.Do(fmt.Sprintf("if err := %s(&(*in)[i], &(*out)[i], s); err != nil {\n", funcName), argsFromType(inType.Elem, outType.Elem))
|
||||
sw.Do("if err := "+nameTmpl+"(&(*in)[i], &(*out)[i], s); err != nil {\n", argsFromType(inType.Elem, outType.Elem))
|
||||
} else {
|
||||
// TODO: This triggers on v1.ObjectMeta <-> api.ObjectMeta and
|
||||
// similar because neither package is the target package, and
|
||||
@ -785,8 +777,7 @@ func (g *genConversion) doStruct(inType, outType *types.Type, sw *generator.Snip
|
||||
continue
|
||||
}
|
||||
if g.convertibleOnlyWithinPackage(t, outT) {
|
||||
funcName := g.funcNameTmpl(t, outT)
|
||||
sw.Do(fmt.Sprintf("if err := %s(&in.$.name$, &out.$.name$, s); err != nil {\n", funcName), args)
|
||||
sw.Do("if err := "+nameTmpl+"(&in.$.name$, &out.$.name$, s); err != nil {\n", args)
|
||||
} else {
|
||||
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
||||
sw.Do("if err := s.Convert(&in.$.name$, &out.$.name$, 0); err != nil {\n", args)
|
||||
@ -802,8 +793,7 @@ func (g *genConversion) doStruct(inType, outType *types.Type, sw *generator.Snip
|
||||
}
|
||||
} else {
|
||||
if g.convertibleOnlyWithinPackage(t, outT) {
|
||||
funcName := g.funcNameTmpl(t, outT)
|
||||
sw.Do(fmt.Sprintf("if err := %s(&in.$.name$, &out.$.name$, s); err != nil {\n", funcName), args)
|
||||
sw.Do("if err := "+nameTmpl+"(&in.$.name$, &out.$.name$, s); err != nil {\n", args)
|
||||
} else {
|
||||
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
||||
sw.Do("if err := s.Convert(&in.$.name$, &out.$.name$, 0); err != nil {\n", args)
|
||||
@ -813,8 +803,7 @@ func (g *genConversion) doStruct(inType, outType *types.Type, sw *generator.Snip
|
||||
}
|
||||
default:
|
||||
if g.convertibleOnlyWithinPackage(t, outT) {
|
||||
funcName := g.funcNameTmpl(t, outT)
|
||||
sw.Do(fmt.Sprintf("if err := %s(&in.$.name$, &out.$.name$, s); err != nil {\n", funcName), args)
|
||||
sw.Do("if err := "+nameTmpl+"(&in.$.name$, &out.$.name$, s); err != nil {\n", args)
|
||||
} else {
|
||||
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
||||
sw.Do("if err := s.Convert(&in.$.name$, &out.$.name$, 0); err != nil {\n", args)
|
||||
@ -841,8 +830,7 @@ func (g *genConversion) doPointer(inType, outType *types.Type, sw *generator.Sni
|
||||
if function, ok := g.preexists(inType.Elem, outType.Elem); ok {
|
||||
sw.Do("if err := $.|raw$(*in, *out, s); err != nil {\n", function)
|
||||
} else if g.convertibleOnlyWithinPackage(inType.Elem, outType.Elem) {
|
||||
funcName := g.funcNameTmpl(inType.Elem, outType.Elem)
|
||||
sw.Do(fmt.Sprintf("if err := %s(*in, *out, s); err != nil {\n", funcName), argsFromType(inType.Elem, outType.Elem))
|
||||
sw.Do("if err := "+nameTmpl+"(*in, *out, s); err != nil {\n", argsFromType(inType.Elem, outType.Elem))
|
||||
} else {
|
||||
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
||||
sw.Do("if err := s.Convert(*in, *out, 0); err != nil {\n", nil)
|
||||
|
@ -216,8 +216,6 @@ type genDeepCopy struct {
|
||||
registerTypes bool
|
||||
imports namer.ImportTracker
|
||||
typesForInit []*types.Type
|
||||
|
||||
globalVariables map[string]interface{}
|
||||
}
|
||||
|
||||
func NewGenDeepCopy(sanitizedName, targetPackage string, boundingDirs []string, allTypes, registerTypes bool) generator.Generator {
|
||||
@ -236,7 +234,14 @@ func NewGenDeepCopy(sanitizedName, targetPackage string, boundingDirs []string,
|
||||
|
||||
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)}
|
||||
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 {
|
||||
@ -338,36 +343,30 @@ func (g *genDeepCopy) Imports(c *generator.Context) (imports []string) {
|
||||
return importLines
|
||||
}
|
||||
|
||||
func (g *genDeepCopy) withGlobals(args map[string]interface{}) map[string]interface{} {
|
||||
for k, v := range g.globalVariables {
|
||||
if _, ok := args[k]; !ok {
|
||||
args[k] = v
|
||||
}
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func argsFromType(t *types.Type) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
func argsFromType(t *types.Type) generator.Args {
|
||||
return generator.Args{
|
||||
"type": t,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *genDeepCopy) funcNameTmpl(t *types.Type) string {
|
||||
tmpl := "DeepCopy_$.type|public$"
|
||||
g.imports.AddType(t)
|
||||
if t.Name.Package != g.targetPackage {
|
||||
tmpl = g.imports.LocalNameOf(t.Name.Package) + "." + tmpl
|
||||
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 tmpl
|
||||
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)
|
||||
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
|
||||
@ -377,18 +376,15 @@ func (g *genDeepCopy) Init(c *generator.Context, w io.Writer) error {
|
||||
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{}{
|
||||
sw.Do("if err := $.scheme|raw$.AddGeneratedDeepCopyFuncs(\n", generator.Args{
|
||||
"scheme": scheme,
|
||||
})
|
||||
reflect := c.Universe.Type(types.Name{Package: "reflect", Name: "TypeOf"})
|
||||
for _, t := range g.typesForInit {
|
||||
g.imports.AddType(reflect)
|
||||
sw.Do(fmt.Sprintf("conversion.GeneratedDeepCopyFunc{Fn: %s, InType: reflect.TypeOf(&$.type|raw${})},\n", g.funcNameTmpl(t)), argsFromType(t))
|
||||
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("); err != nil {\n", nil)
|
||||
sw.Do("// if one of the deep copy functions is malformed, detect it immediately.\n", nil)
|
||||
@ -427,9 +423,10 @@ func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Wri
|
||||
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)))
|
||||
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)
|
||||
@ -486,8 +483,7 @@ func (g *genDeepCopy) doMap(t *types.Type, sw *generator.SnippetWriter) {
|
||||
sw.Do("for key, val := range *in {\n", nil)
|
||||
if g.copyableAndInBounds(t.Elem) {
|
||||
sw.Do("newVal := new($.|raw$)\n", 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("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)
|
||||
@ -519,8 +515,7 @@ func (g *genDeepCopy) doSlice(t *types.Type, sw *generator.SnippetWriter) {
|
||||
} else if t.Elem.IsAssignable() {
|
||||
sw.Do("(*out)[i] = (*in)[i]\n", nil)
|
||||
} else if g.copyableAndInBounds(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("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 {
|
||||
@ -546,7 +541,7 @@ func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) {
|
||||
copied.Name = t.Name
|
||||
t = &copied
|
||||
}
|
||||
args := map[string]interface{}{
|
||||
args := generator.Args{
|
||||
"type": t,
|
||||
"name": m.Name,
|
||||
}
|
||||
@ -566,8 +561,7 @@ func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) {
|
||||
} else if t.IsAssignable() {
|
||||
sw.Do("out.$.name$ = in.$.name$\n", args)
|
||||
} else if g.copyableAndInBounds(t) {
|
||||
funcName := g.funcNameTmpl(t)
|
||||
sw.Do(fmt.Sprintf("if err := %s(&in.$.name$, &out.$.name$, c); err != nil {\n", funcName), args)
|
||||
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 {
|
||||
@ -602,9 +596,8 @@ func (g *genDeepCopy) doPointer(t *types.Type, sw *generator.SnippetWriter) {
|
||||
sw.Do("*out = new($.Elem|raw$)\n", t)
|
||||
sw.Do("**out = **in", nil)
|
||||
} else if g.copyableAndInBounds(t.Elem) {
|
||||
funcName := g.funcNameTmpl(t.Elem)
|
||||
sw.Do("*out = new($.Elem|raw$)\n", t)
|
||||
sw.Do(fmt.Sprintf("if err := %s(*in, *out, c); err != nil {\n", funcName), argsFromType(t.Elem))
|
||||
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 {
|
||||
|
@ -94,7 +94,7 @@ func NewSnippetWriter(w io.Writer, c *Context, left, right string) *SnippetWrite
|
||||
// but you should consider doing the logic in go and stitching them together
|
||||
// for the sake of your readers.
|
||||
//
|
||||
// TODO: Change Do() to optionally take a list of pairt of parameters (key, value)
|
||||
// TODO: Change Do() to optionally take a list of pairs of parameters (key, value)
|
||||
// and have it construct a combined map with that and args.
|
||||
func (s *SnippetWriter) Do(format string, args interface{}) *SnippetWriter {
|
||||
if s.err != nil {
|
||||
@ -119,6 +119,31 @@ func (s *SnippetWriter) Do(format string, args interface{}) *SnippetWriter {
|
||||
return s
|
||||
}
|
||||
|
||||
// Args exists to make it convenient to construct arguments for
|
||||
// SnippetWriter.Do.
|
||||
type Args map[interface{}]interface{}
|
||||
|
||||
// With makes a copy of a and adds the given key, value pair.
|
||||
func (a Args) With(key, value interface{}) Args {
|
||||
a2 := Args{key: value}
|
||||
for k, v := range a {
|
||||
a2[k] = v
|
||||
}
|
||||
return a2
|
||||
}
|
||||
|
||||
// WithArgs makes a copy of a and adds the given arguments.
|
||||
func (a Args) WithArgs(rhs Args) Args {
|
||||
a2 := Args{}
|
||||
for k, v := range rhs {
|
||||
a2[k] = v
|
||||
}
|
||||
for k, v := range a {
|
||||
a2[k] = v
|
||||
}
|
||||
return a2
|
||||
}
|
||||
|
||||
func (s *SnippetWriter) Out() io.Writer {
|
||||
return s.w
|
||||
}
|
||||
|
@ -16,6 +16,15 @@ limitations under the License.
|
||||
|
||||
package types
|
||||
|
||||
// Ref makes a reference to the given type. It can only be used for e.g.
|
||||
// passing to namers.
|
||||
func Ref(packageName, typeName string) *Type {
|
||||
return &Type{Name: Name{
|
||||
Name: typeName,
|
||||
Package: packageName,
|
||||
}}
|
||||
}
|
||||
|
||||
// A type name may have a package qualifier.
|
||||
type Name struct {
|
||||
// Empty if embedded or builtin. This is the package path unless Path is specified.
|
||||
|
Loading…
Reference in New Issue
Block a user