Remove BPA from Makefile
[icn.git] / cmd / bpa-operator / vendor / k8s.io / gengo / generator / generator.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         "bytes"
21         "io"
22
23         "k8s.io/gengo/namer"
24         "k8s.io/gengo/parser"
25         "k8s.io/gengo/types"
26 )
27
28 // Package contains the contract for generating a package.
29 type Package interface {
30         // Name returns the package short name.
31         Name() string
32         // Path returns the package import path.
33         Path() string
34
35         // Filter should return true if this package cares about this type.
36         // Otherwise, this type will be omitted from the type ordering for
37         // this package.
38         Filter(*Context, *types.Type) bool
39
40         // Header should return a header for the file, including comment markers.
41         // Useful for copyright notices and doc strings. Include an
42         // autogeneration notice! Do not include the "package x" line.
43         Header(filename string) []byte
44
45         // Generators returns the list of generators for this package. It is
46         // allowed for more than one generator to write to the same file.
47         // A Context is passed in case the list of generators depends on the
48         // input types.
49         Generators(*Context) []Generator
50 }
51
52 type File struct {
53         Name        string
54         FileType    string
55         PackageName string
56         Header      []byte
57         Imports     map[string]struct{}
58         Vars        bytes.Buffer
59         Consts      bytes.Buffer
60         Body        bytes.Buffer
61 }
62
63 type FileType interface {
64         AssembleFile(f *File, path string) error
65         VerifyFile(f *File, path string) error
66 }
67
68 // Packages is a list of packages to generate.
69 type Packages []Package
70
71 // Generator is the contract for anything that wants to do auto-generation.
72 // It's expected that the io.Writers passed to the below functions will be
73 // ErrorTrackers; this allows implementations to not check for io errors,
74 // making more readable code.
75 //
76 // The call order for the functions that take a Context is:
77 // 1. Filter()        // Subsequent calls see only types that pass this.
78 // 2. Namers()        // Subsequent calls see the namers provided by this.
79 // 3. PackageVars()
80 // 4. PackageConsts()
81 // 5. Init()
82 // 6. GenerateType()  // Called N times, once per type in the context's Order.
83 // 7. Imports()
84 //
85 // You may have multiple generators for the same file.
86 type Generator interface {
87         // The name of this generator. Will be included in generated comments.
88         Name() string
89
90         // Filter should return true if this generator cares about this type.
91         // (otherwise, GenerateType will not be called.)
92         //
93         // Filter is called before any of the generator's other functions;
94         // subsequent calls will get a context with only the types that passed
95         // this filter.
96         Filter(*Context, *types.Type) bool
97
98         // If this generator needs special namers, return them here. These will
99         // override the original namers in the context if there is a collision.
100         // You may return nil if you don't need special names. These names will
101         // be available in the context passed to the rest of the generator's
102         // functions.
103         //
104         // A use case for this is to return a namer that tracks imports.
105         Namers(*Context) namer.NameSystems
106
107         // Init should write an init function, and any other content that's not
108         // generated per-type. (It's not intended for generator specific
109         // initialization! Do that when your Package constructs the
110         // Generators.)
111         Init(*Context, io.Writer) error
112
113         // Finalize should write finish up functions, and any other content that's not
114         // generated per-type.
115         Finalize(*Context, io.Writer) error
116
117         // PackageVars should emit an array of variable lines. They will be
118         // placed in a var ( ... ) block. There's no need to include a leading
119         // \t or trailing \n.
120         PackageVars(*Context) []string
121
122         // PackageConsts should emit an array of constant lines. They will be
123         // placed in a const ( ... ) block. There's no need to include a leading
124         // \t or trailing \n.
125         PackageConsts(*Context) []string
126
127         // GenerateType should emit the code for a particular type.
128         GenerateType(*Context, *types.Type, io.Writer) error
129
130         // Imports should return a list of necessary imports. They will be
131         // formatted correctly. You do not need to include quotation marks,
132         // return only the package name; alternatively, you can also return
133         // imports in the format `name "path/to/pkg"`. Imports will be called
134         // after Init, PackageVars, PackageConsts, and GenerateType, to allow
135         // you to keep track of what imports you actually need.
136         Imports(*Context) []string
137
138         // Preferred file name of this generator, not including a path. It is
139         // allowed for multiple generators to use the same filename, but it's
140         // up to you to make sure they don't have colliding import names.
141         // TODO: provide per-file import tracking, removing the requirement
142         // that generators coordinate..
143         Filename() string
144
145         // A registered file type in the context to generate this file with. If
146         // the FileType is not found in the context, execution will stop.
147         FileType() string
148 }
149
150 // Context is global context for individual generators to consume.
151 type Context struct {
152         // A map from the naming system to the names for that system. E.g., you
153         // might have public names and several private naming systems.
154         Namers namer.NameSystems
155
156         // All the types, in case you want to look up something.
157         Universe types.Universe
158
159         // All the user-specified packages.  This is after recursive expansion.
160         Inputs []string
161
162         // The canonical ordering of the types (will be filtered by both the
163         // Package's and Generator's Filter methods).
164         Order []*types.Type
165
166         // A set of types this context can process. If this is empty or nil,
167         // the default "golang" filetype will be provided.
168         FileTypes map[string]FileType
169
170         // If true, Execute* calls will just verify that the existing output is
171         // correct. (You may set this after calling NewContext.)
172         Verify bool
173
174         // Allows generators to add packages at runtime.
175         builder *parser.Builder
176 }
177
178 // NewContext generates a context from the given builder, naming systems, and
179 // the naming system you wish to construct the canonical ordering from.
180 func NewContext(b *parser.Builder, nameSystems namer.NameSystems, canonicalOrderName string) (*Context, error) {
181         universe, err := b.FindTypes()
182         if err != nil {
183                 return nil, err
184         }
185
186         c := &Context{
187                 Namers:   namer.NameSystems{},
188                 Universe: universe,
189                 Inputs:   b.FindPackages(),
190                 FileTypes: map[string]FileType{
191                         GolangFileType: NewGolangFile(),
192                 },
193                 builder: b,
194         }
195
196         for name, systemNamer := range nameSystems {
197                 c.Namers[name] = systemNamer
198                 if name == canonicalOrderName {
199                         orderer := namer.Orderer{Namer: systemNamer}
200                         c.Order = orderer.OrderUniverse(universe)
201                 }
202         }
203         return c, nil
204 }
205
206 // AddDir adds a Go package to the context. The specified path must be a single
207 // go package import path.  GOPATH, GOROOT, and the location of your go binary
208 // (`which go`) will all be searched, in the normal Go fashion.
209 // Deprecated. Please use AddDirectory.
210 func (ctxt *Context) AddDir(path string) error {
211         return ctxt.builder.AddDirTo(path, &ctxt.Universe)
212 }
213
214 // AddDirectory adds a Go package to the context. The specified path must be a
215 // single go package import path.  GOPATH, GOROOT, and the location of your go
216 // binary (`which go`) will all be searched, in the normal Go fashion.
217 func (ctxt *Context) AddDirectory(path string) (*types.Package, error) {
218         return ctxt.builder.AddDirectoryTo(path, &ctxt.Universe)
219 }