Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / k8s.io / gengo / types / types.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 types
18
19 import "strings"
20
21 // Ref makes a reference to the given type. It can only be used for e.g.
22 // passing to namers.
23 func Ref(packageName, typeName string) *Type {
24         return &Type{Name: Name{
25                 Name:    typeName,
26                 Package: packageName,
27         }}
28 }
29
30 // A type name may have a package qualifier.
31 type Name struct {
32         // Empty if embedded or builtin. This is the package path unless Path is specified.
33         Package string
34         // The type name.
35         Name string
36         // An optional location of the type definition for languages that can have disjoint
37         // packages and paths.
38         Path string
39 }
40
41 // String returns the name formatted as a string.
42 func (n Name) String() string {
43         if n.Package == "" {
44                 return n.Name
45         }
46         return n.Package + "." + n.Name
47 }
48
49 // ParseFullyQualifiedName parses a name like k8s.io/kubernetes/pkg/api.Pod into a Name.
50 func ParseFullyQualifiedName(fqn string) Name {
51         cs := strings.Split(fqn, ".")
52         pkg := ""
53         if len(cs) > 1 {
54                 pkg = strings.Join(cs[0:len(cs)-1], ".")
55         }
56         return Name{
57                 Name:    cs[len(cs)-1],
58                 Package: pkg,
59         }
60 }
61
62 // The possible classes of types.
63 type Kind string
64
65 const (
66         // Builtin is a primitive, like bool, string, int.
67         Builtin Kind = "Builtin"
68         Struct  Kind = "Struct"
69         Map     Kind = "Map"
70         Slice   Kind = "Slice"
71         Pointer Kind = "Pointer"
72
73         // Alias is an alias of another type, e.g. in:
74         //   type Foo string
75         //   type Bar Foo
76         // Bar is an alias of Foo.
77         //
78         // In the real go type system, Foo is a "Named" string; but to simplify
79         // generation, this type system will just say that Foo *is* a builtin.
80         // We then need "Alias" as a way for us to say that Bar *is* a Foo.
81         Alias Kind = "Alias"
82
83         // Interface is any type that could have differing types at run time.
84         Interface Kind = "Interface"
85
86         // The remaining types are included for completeness, but are not well
87         // supported.
88         Array Kind = "Array" // Array is just like slice, but has a fixed length.
89         Chan  Kind = "Chan"
90         Func  Kind = "Func"
91
92         // DeclarationOf is different from other Kinds; it indicates that instead of
93         // representing an actual Type, the type is a declaration of an instance of
94         // a type. E.g., a top-level function, variable, or constant. See the
95         // comment for Type.Name for more detail.
96         DeclarationOf Kind = "DeclarationOf"
97         Unknown       Kind = ""
98         Unsupported   Kind = "Unsupported"
99
100         // Protobuf is protobuf type.
101         Protobuf Kind = "Protobuf"
102 )
103
104 // Package holds package-level information.
105 // Fields are public, as everything in this package, to enable consumption by
106 // templates (for example). But it is strongly encouraged for code to build by
107 // using the provided functions.
108 type Package struct {
109         // Canonical name of this package-- its path.
110         Path string
111
112         // The location this package was loaded from
113         SourcePath string
114
115         // Short name of this package; the name that appears in the
116         // 'package x' line.
117         Name string
118
119         // The comment right above the package declaration in doc.go, if any.
120         DocComments []string
121
122         // All comments from doc.go, if any.
123         // TODO: remove Comments and use DocComments everywhere.
124         Comments []string
125
126         // Types within this package, indexed by their name (*not* including
127         // package name).
128         Types map[string]*Type
129
130         // Functions within this package, indexed by their name (*not* including
131         // package name).
132         Functions map[string]*Type
133
134         // Global variables within this package, indexed by their name (*not* including
135         // package name).
136         Variables map[string]*Type
137
138         // Packages imported by this package, indexed by (canonicalized)
139         // package path.
140         Imports map[string]*Package
141 }
142
143 // Has returns true if the given name references a type known to this package.
144 func (p *Package) Has(name string) bool {
145         _, has := p.Types[name]
146         return has
147 }
148
149 // Type gets the given Type in this Package.  If the Type is not already
150 // defined, this will add it and return the new Type value.  The caller is
151 // expected to finish initialization.
152 func (p *Package) Type(typeName string) *Type {
153         if t, ok := p.Types[typeName]; ok {
154                 return t
155         }
156         if p.Path == "" {
157                 // Import the standard builtin types!
158                 if t, ok := builtins.Types[typeName]; ok {
159                         p.Types[typeName] = t
160                         return t
161                 }
162         }
163         t := &Type{Name: Name{Package: p.Path, Name: typeName}}
164         p.Types[typeName] = t
165         return t
166 }
167
168 // Function gets the given function Type in this Package. If the function is
169 // not already defined, this will add it.  If a function is added, it's the
170 // caller's responsibility to finish construction of the function by setting
171 // Underlying to the correct type.
172 func (p *Package) Function(funcName string) *Type {
173         if t, ok := p.Functions[funcName]; ok {
174                 return t
175         }
176         t := &Type{Name: Name{Package: p.Path, Name: funcName}}
177         t.Kind = DeclarationOf
178         p.Functions[funcName] = t
179         return t
180 }
181
182 // Variable gets the given variable Type in this Package. If the variable is
183 // not already defined, this will add it. If a variable is added, it's the caller's
184 // responsibility to finish construction of the variable by setting Underlying
185 // to the correct type.
186 func (p *Package) Variable(varName string) *Type {
187         if t, ok := p.Variables[varName]; ok {
188                 return t
189         }
190         t := &Type{Name: Name{Package: p.Path, Name: varName}}
191         t.Kind = DeclarationOf
192         p.Variables[varName] = t
193         return t
194 }
195
196 // HasImport returns true if p imports packageName. Package names include the
197 // package directory.
198 func (p *Package) HasImport(packageName string) bool {
199         _, has := p.Imports[packageName]
200         return has
201 }
202
203 // Universe is a map of all packages. The key is the package name, but you
204 // should use Package(), Type(), Function(), or Variable() instead of direct
205 // access.
206 type Universe map[string]*Package
207
208 // Type returns the canonical type for the given fully-qualified name. Builtin
209 // types will always be found, even if they haven't been explicitly added to
210 // the map. If a non-existing type is requested, this will create (a marker for)
211 // it.
212 func (u Universe) Type(n Name) *Type {
213         return u.Package(n.Package).Type(n.Name)
214 }
215
216 // Function returns the canonical function for the given fully-qualified name.
217 // If a non-existing function is requested, this will create (a marker for) it.
218 // If a marker is created, it's the caller's responsibility to finish
219 // construction of the function by setting Underlying to the correct type.
220 func (u Universe) Function(n Name) *Type {
221         return u.Package(n.Package).Function(n.Name)
222 }
223
224 // Variable returns the canonical variable for the given fully-qualified name.
225 // If a non-existing variable is requested, this will create (a marker for) it.
226 // If a marker is created, it's the caller's responsibility to finish
227 // construction of the variable by setting Underlying to the correct type.
228 func (u Universe) Variable(n Name) *Type {
229         return u.Package(n.Package).Variable(n.Name)
230 }
231
232 // AddImports registers import lines for packageName. May be called multiple times.
233 // You are responsible for canonicalizing all package paths.
234 func (u Universe) AddImports(packagePath string, importPaths ...string) {
235         p := u.Package(packagePath)
236         for _, i := range importPaths {
237                 p.Imports[i] = u.Package(i)
238         }
239 }
240
241 // Package returns the Package for the given path.
242 // If a non-existing package is requested, this will create (a marker for) it.
243 // If a marker is created, it's the caller's responsibility to finish
244 // construction of the package.
245 func (u Universe) Package(packagePath string) *Package {
246         if p, ok := u[packagePath]; ok {
247                 return p
248         }
249         p := &Package{
250                 Path:      packagePath,
251                 Types:     map[string]*Type{},
252                 Functions: map[string]*Type{},
253                 Variables: map[string]*Type{},
254                 Imports:   map[string]*Package{},
255         }
256         u[packagePath] = p
257         return p
258 }
259
260 // Type represents a subset of possible go types.
261 type Type struct {
262         // There are two general categories of types, those explicitly named
263         // and those anonymous. Named ones will have a non-empty package in the
264         // name field.
265         //
266         // An exception: If Kind == DeclarationOf, then this name is the name of a
267         // top-level function, variable, or const, and the type can be found in Underlying.
268         // We do this to allow the naming system to work against these objects, even
269         // though they aren't strictly speaking types.
270         Name Name
271
272         // The general kind of this type.
273         Kind Kind
274
275         // If there are comment lines immediately before the type definition,
276         // they will be recorded here.
277         CommentLines []string
278
279         // If there are comment lines preceding the `CommentLines`, they will be
280         // recorded here. There are two cases:
281         // ---
282         // SecondClosestCommentLines
283         // a blank line
284         // CommentLines
285         // type definition
286         // ---
287         //
288         // or
289         // ---
290         // SecondClosestCommentLines
291         // a blank line
292         // type definition
293         // ---
294         SecondClosestCommentLines []string
295
296         // If Kind == Struct
297         Members []Member
298
299         // If Kind == Map, Slice, Pointer, or Chan
300         Elem *Type
301
302         // If Kind == Map, this is the map's key type.
303         Key *Type
304
305         // If Kind == Alias, this is the underlying type.
306         // If Kind == DeclarationOf, this is the type of the declaration.
307         Underlying *Type
308
309         // If Kind == Interface, this is the set of all required functions.
310         // Otherwise, if this is a named type, this is the list of methods that
311         // type has. (All elements will have Kind=="Func")
312         Methods map[string]*Type
313
314         // If Kind == func, this is the signature of the function.
315         Signature *Signature
316
317         // TODO: Add:
318         // * channel direction
319         // * array length
320 }
321
322 // String returns the name of the type.
323 func (t *Type) String() string {
324         return t.Name.String()
325 }
326
327 // IsPrimitive returns whether the type is a built-in type or is an alias to a
328 // built-in type.  For example: strings and aliases of strings are primitives,
329 // structs are not.
330 func (t *Type) IsPrimitive() bool {
331         if t.Kind == Builtin || (t.Kind == Alias && t.Underlying.Kind == Builtin) {
332                 return true
333         }
334         return false
335 }
336
337 // IsAssignable returns whether the type is deep-assignable.  For example,
338 // slices and maps and pointers are shallow copies, but ints and strings are
339 // complete.
340 func (t *Type) IsAssignable() bool {
341         if t.IsPrimitive() {
342                 return true
343         }
344         if t.Kind == Struct {
345                 for _, m := range t.Members {
346                         if !m.Type.IsAssignable() {
347                                 return false
348                         }
349                 }
350                 return true
351         }
352         return false
353 }
354
355 // IsAnonymousStruct returns true if the type is an anonymous struct or an alias
356 // to an anonymous struct.
357 func (t *Type) IsAnonymousStruct() bool {
358         return (t.Kind == Struct && t.Name.Name == "struct{}") || (t.Kind == Alias && t.Underlying.IsAnonymousStruct())
359 }
360
361 // A single struct member
362 type Member struct {
363         // The name of the member.
364         Name string
365
366         // If the member is embedded (anonymous) this will be true, and the
367         // Name will be the type name.
368         Embedded bool
369
370         // If there are comment lines immediately before the member in the type
371         // definition, they will be recorded here.
372         CommentLines []string
373
374         // If there are tags along with this member, they will be saved here.
375         Tags string
376
377         // The type of this member.
378         Type *Type
379 }
380
381 // String returns the name and type of the member.
382 func (m Member) String() string {
383         return m.Name + " " + m.Type.String()
384 }
385
386 // Signature is a function's signature.
387 type Signature struct {
388         // TODO: store the parameter names, not just types.
389
390         // If a method of some type, this is the type it's a member of.
391         Receiver   *Type
392         Parameters []*Type
393         Results    []*Type
394
395         // True if the last in parameter is of the form ...T.
396         Variadic bool
397
398         // If there are comment lines immediately before this
399         // signature/method/function declaration, they will be recorded here.
400         CommentLines []string
401 }
402
403 // Built in types.
404 var (
405         String = &Type{
406                 Name: Name{Name: "string"},
407                 Kind: Builtin,
408         }
409         Int64 = &Type{
410                 Name: Name{Name: "int64"},
411                 Kind: Builtin,
412         }
413         Int32 = &Type{
414                 Name: Name{Name: "int32"},
415                 Kind: Builtin,
416         }
417         Int16 = &Type{
418                 Name: Name{Name: "int16"},
419                 Kind: Builtin,
420         }
421         Int = &Type{
422                 Name: Name{Name: "int"},
423                 Kind: Builtin,
424         }
425         Uint64 = &Type{
426                 Name: Name{Name: "uint64"},
427                 Kind: Builtin,
428         }
429         Uint32 = &Type{
430                 Name: Name{Name: "uint32"},
431                 Kind: Builtin,
432         }
433         Uint16 = &Type{
434                 Name: Name{Name: "uint16"},
435                 Kind: Builtin,
436         }
437         Uint = &Type{
438                 Name: Name{Name: "uint"},
439                 Kind: Builtin,
440         }
441         Uintptr = &Type{
442                 Name: Name{Name: "uintptr"},
443                 Kind: Builtin,
444         }
445         Float64 = &Type{
446                 Name: Name{Name: "float64"},
447                 Kind: Builtin,
448         }
449         Float32 = &Type{
450                 Name: Name{Name: "float32"},
451                 Kind: Builtin,
452         }
453         Float = &Type{
454                 Name: Name{Name: "float"},
455                 Kind: Builtin,
456         }
457         Bool = &Type{
458                 Name: Name{Name: "bool"},
459                 Kind: Builtin,
460         }
461         Byte = &Type{
462                 Name: Name{Name: "byte"},
463                 Kind: Builtin,
464         }
465
466         builtins = &Package{
467                 Types: map[string]*Type{
468                         "bool":    Bool,
469                         "string":  String,
470                         "int":     Int,
471                         "int64":   Int64,
472                         "int32":   Int32,
473                         "int16":   Int16,
474                         "int8":    Byte,
475                         "uint":    Uint,
476                         "uint64":  Uint64,
477                         "uint32":  Uint32,
478                         "uint16":  Uint16,
479                         "uint8":   Byte,
480                         "uintptr": Uintptr,
481                         "byte":    Byte,
482                         "float":   Float,
483                         "float64": Float64,
484                         "float32": Float32,
485                 },
486                 Imports: map[string]*Package{},
487                 Path:    "",
488                 Name:    "",
489         }
490 )
491
492 func IsInteger(t *Type) bool {
493         switch t {
494         case Int, Int64, Int32, Int16, Uint, Uint64, Uint32, Uint16, Byte:
495                 return true
496         default:
497                 return false
498         }
499 }