Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / k8s.io / gengo / generator / snippet_writer.go
1 /*
2 Copyright 2015 The Kubernetes Authors.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8     http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 package generator
18
19 import (
20         "fmt"
21         "io"
22         "runtime"
23         "text/template"
24 )
25
26 // SnippetWriter is an attempt to make the template library usable.
27 // Methods are chainable, and you don't have to check Error() until you're all
28 // done.
29 type SnippetWriter struct {
30         w       io.Writer
31         context *Context
32         // Left & right delimiters. text/template defaults to "{{" and "}}"
33         // which is totally unusable for go code based templates.
34         left, right string
35         funcMap     template.FuncMap
36         err         error
37 }
38
39 // w is the destination; left and right are the delimiters; @ and $ are both
40 // reasonable choices.
41 //
42 // c is used to make a function for every naming system, to which you can pass
43 // a type and get the corresponding name.
44 func NewSnippetWriter(w io.Writer, c *Context, left, right string) *SnippetWriter {
45         sw := &SnippetWriter{
46                 w:       w,
47                 context: c,
48                 left:    left,
49                 right:   right,
50                 funcMap: template.FuncMap{},
51         }
52         for name, namer := range c.Namers {
53                 sw.funcMap[name] = namer.Name
54         }
55         return sw
56 }
57
58 // Do parses format and runs args through it. You can have arbitrary logic in
59 // the format (see the text/template documentation), but consider running many
60 // short templaces, with ordinary go logic in between--this may be more
61 // readable. Do is chainable. Any error causes every other call to do to be
62 // ignored, and the error will be returned by Error(). So you can check it just
63 // once, at the end of your function.
64 //
65 // 'args' can be quite literally anything; read the text/template documentation
66 // for details. Maps and structs work particularly nicely. Conveniently, the
67 // types package is designed to have structs that are easily referencable from
68 // the template language.
69 //
70 // Example:
71 //
72 // sw := generator.NewSnippetWriter(outBuffer, context, "$", "$")
73 // sw.Do(`The public type name is: $.type|public$`, map[string]interface{}{"type": t})
74 // return sw.Error()
75 //
76 // Where:
77 // * "$" starts a template directive
78 // * "." references the entire thing passed as args
79 // * "type" therefore sees a map and looks up the key "type"
80 // * "|" means "pass the thing on the left to the thing on the right"
81 // * "public" is the name of a naming system, so the SnippetWriter has given
82 //   the template a function called "public" that takes a *types.Type and
83 //   returns the naming system's name. E.g., if the type is "string" this might
84 //   return "String".
85 // * the second "$" ends the template directive.
86 //
87 // The map is actually not necessary. The below does the same thing:
88 //
89 // sw.Do(`The public type name is: $.|public$`, t)
90 //
91 // You may or may not find it more readable to use the map with a descriptive
92 // key, but if you want to pass more than one arg, the map or a custom struct
93 // becomes a requirement. You can do arbitrary logic inside these templates,
94 // but you should consider doing the logic in go and stitching them together
95 // for the sake of your readers.
96 //
97 // TODO: Change Do() to optionally take a list of pairs of parameters (key, value)
98 // and have it construct a combined map with that and args.
99 func (s *SnippetWriter) Do(format string, args interface{}) *SnippetWriter {
100         if s.err != nil {
101                 return s
102         }
103         // Name the template by source file:line so it can be found when
104         // there's an error.
105         _, file, line, _ := runtime.Caller(1)
106         tmpl, err := template.
107                 New(fmt.Sprintf("%s:%d", file, line)).
108                 Delims(s.left, s.right).
109                 Funcs(s.funcMap).
110                 Parse(format)
111         if err != nil {
112                 s.err = err
113                 return s
114         }
115         err = tmpl.Execute(s.w, args)
116         if err != nil {
117                 s.err = err
118         }
119         return s
120 }
121
122 // Args exists to make it convenient to construct arguments for
123 // SnippetWriter.Do.
124 type Args map[interface{}]interface{}
125
126 // With makes a copy of a and adds the given key, value pair.
127 func (a Args) With(key, value interface{}) Args {
128         a2 := Args{key: value}
129         for k, v := range a {
130                 a2[k] = v
131         }
132         return a2
133 }
134
135 // WithArgs makes a copy of a and adds the given arguments.
136 func (a Args) WithArgs(rhs Args) Args {
137         a2 := Args{}
138         for k, v := range rhs {
139                 a2[k] = v
140         }
141         for k, v := range a {
142                 a2[k] = v
143         }
144         return a2
145 }
146
147 func (s *SnippetWriter) Out() io.Writer {
148         return s.w
149 }
150
151 // Error returns any encountered error.
152 func (s *SnippetWriter) Error() error {
153         return s.err
154 }