2 Copyright 2015 The Kubernetes Authors.
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
8 http://www.apache.org/licenses/LICENSE-2.0
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.
21 // Ref makes a reference to the given type. It can only be used for e.g.
23 func Ref(packageName, typeName string) *Type {
24 return &Type{Name: Name{
30 // A type name may have a package qualifier.
32 // Empty if embedded or builtin. This is the package path unless Path is specified.
36 // An optional location of the type definition for languages that can have disjoint
37 // packages and paths.
41 // String returns the name formatted as a string.
42 func (n Name) String() string {
46 return n.Package + "." + n.Name
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, ".")
54 pkg = strings.Join(cs[0:len(cs)-1], ".")
62 // The possible classes of types.
66 // Builtin is a primitive, like bool, string, int.
67 Builtin Kind = "Builtin"
68 Struct Kind = "Struct"
71 Pointer Kind = "Pointer"
73 // Alias is an alias of another type, e.g. in:
76 // Bar is an alias of Foo.
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.
83 // Interface is any type that could have differing types at run time.
84 Interface Kind = "Interface"
86 // The remaining types are included for completeness, but are not well
88 Array Kind = "Array" // Array is just like slice, but has a fixed length.
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"
98 Unsupported Kind = "Unsupported"
100 // Protobuf is protobuf type.
101 Protobuf Kind = "Protobuf"
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.
112 // The location this package was loaded from
115 // Short name of this package; the name that appears in the
119 // The comment right above the package declaration in doc.go, if any.
122 // All comments from doc.go, if any.
123 // TODO: remove Comments and use DocComments everywhere.
126 // Types within this package, indexed by their name (*not* including
128 Types map[string]*Type
130 // Functions within this package, indexed by their name (*not* including
132 Functions map[string]*Type
134 // Global variables within this package, indexed by their name (*not* including
136 Variables map[string]*Type
138 // Packages imported by this package, indexed by (canonicalized)
140 Imports map[string]*Package
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]
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 {
157 // Import the standard builtin types!
158 if t, ok := builtins.Types[typeName]; ok {
159 p.Types[typeName] = t
163 t := &Type{Name: Name{Package: p.Path, Name: typeName}}
164 p.Types[typeName] = t
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 {
176 t := &Type{Name: Name{Package: p.Path, Name: funcName}}
177 t.Kind = DeclarationOf
178 p.Functions[funcName] = t
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 {
190 t := &Type{Name: Name{Package: p.Path, Name: varName}}
191 t.Kind = DeclarationOf
192 p.Variables[varName] = t
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]
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
206 type Universe map[string]*Package
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)
212 func (u Universe) Type(n Name) *Type {
213 return u.Package(n.Package).Type(n.Name)
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)
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)
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)
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 {
251 Types: map[string]*Type{},
252 Functions: map[string]*Type{},
253 Variables: map[string]*Type{},
254 Imports: map[string]*Package{},
260 // Type represents a subset of possible go types.
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
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.
272 // The general kind of this type.
275 // If there are comment lines immediately before the type definition,
276 // they will be recorded here.
277 CommentLines []string
279 // If there are comment lines preceding the `CommentLines`, they will be
280 // recorded here. There are two cases:
282 // SecondClosestCommentLines
290 // SecondClosestCommentLines
294 SecondClosestCommentLines []string
299 // If Kind == Map, Slice, Pointer, or Chan
302 // If Kind == Map, this is the map's key type.
305 // If Kind == Alias, this is the underlying type.
306 // If Kind == DeclarationOf, this is the type of the declaration.
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
314 // If Kind == func, this is the signature of the function.
318 // * channel direction
322 // String returns the name of the type.
323 func (t *Type) String() string {
324 return t.Name.String()
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,
330 func (t *Type) IsPrimitive() bool {
331 if t.Kind == Builtin || (t.Kind == Alias && t.Underlying.Kind == Builtin) {
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
340 func (t *Type) IsAssignable() bool {
344 if t.Kind == Struct {
345 for _, m := range t.Members {
346 if !m.Type.IsAssignable() {
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())
361 // A single struct member
363 // The name of the member.
366 // If the member is embedded (anonymous) this will be true, and the
367 // Name will be the type name.
370 // If there are comment lines immediately before the member in the type
371 // definition, they will be recorded here.
372 CommentLines []string
374 // If there are tags along with this member, they will be saved here.
377 // The type of this member.
381 // String returns the name and type of the member.
382 func (m Member) String() string {
383 return m.Name + " " + m.Type.String()
386 // Signature is a function's signature.
387 type Signature struct {
388 // TODO: store the parameter names, not just types.
390 // If a method of some type, this is the type it's a member of.
395 // True if the last in parameter is of the form ...T.
398 // If there are comment lines immediately before this
399 // signature/method/function declaration, they will be recorded here.
400 CommentLines []string
406 Name: Name{Name: "string"},
410 Name: Name{Name: "int64"},
414 Name: Name{Name: "int32"},
418 Name: Name{Name: "int16"},
422 Name: Name{Name: "int"},
426 Name: Name{Name: "uint64"},
430 Name: Name{Name: "uint32"},
434 Name: Name{Name: "uint16"},
438 Name: Name{Name: "uint"},
442 Name: Name{Name: "uintptr"},
446 Name: Name{Name: "float64"},
450 Name: Name{Name: "float32"},
454 Name: Name{Name: "float"},
458 Name: Name{Name: "bool"},
462 Name: Name{Name: "byte"},
467 Types: map[string]*Type{
486 Imports: map[string]*Package{},
492 func IsInteger(t *Type) bool {
494 case Int, Int64, Int32, Int16, Uint, Uint64, Uint32, Uint16, Byte: