func (t *Type) IsPrimitive() bool {
	if t.Kind == Builtin || (t.Kind == Alias && t.Underlying.Kind == Builtin) {
		return true
	}
	return false
}
IsPrimitive returns whether the type is a built-in type or is an alias to a
built-in type.  For example: strings and aliases of strings are primitives,
structs are not.
package types
import "strings"
func Ref(packageName, typeName string) *Type {
	return &Type{Name: Name{
		Name:    typeName,
		Package: packageName,
	}}
}
type Name struct {
	Package string
	Name string
	Path string
}
func (n Name) String() string {
	if n.Package == "" {
		return n.Name
	}
	return n.Package + "." + n.Name
}
func ParseFullyQualifiedName(fqn string) Name {
	cs := strings.Split(fqn, ".")
	pkg := ""
	if len(cs) > 1 {
		pkg = strings.Join(cs[0:len(cs)-1], ".")
	}
	return Name{
		Name:    cs[len(cs)-1],
		Package: pkg,
	}
}
type Kind string
const (
	Builtin Kind = "Builtin"
	Struct  Kind = "Struct"
	Map     Kind = "Map"
	Slice   Kind = "Slice"
	Pointer Kind = "Pointer"
	Alias Kind = "Alias"
	Interface Kind = "Interface"
	Array Kind = "Array"  
	Chan  Kind = "Chan"
	Func  Kind = "Func"
	DeclarationOf Kind = "DeclarationOf"
	Unknown       Kind = ""
	Unsupported   Kind = "Unsupported"
	Protobuf Kind = "Protobuf"
)
type Package struct {
	Path string
	SourcePath string
	Name string
	DocComments []string
	Comments []string
	Types map[string]*Type
	Functions map[string]*Type
	Variables map[string]*Type
	Imports map[string]*Package
}
func (p *Package) Has(name string) bool {
	_, has := p.Types[name]
	return has
}
func (p *Package) Type(typeName string) *Type {
	if t, ok := p.Types[typeName]; ok {
		return t
	}
	if p.Path == "" {
		if t, ok := builtins.Types[typeName]; ok {
			p.Types[typeName] = t
			return t
		}
	}
	t := &Type{Name: Name{Package: p.Path, Name: typeName}}
	p.Types[typeName] = t
	return t
}
func (p *Package) Function(funcName string) *Type {
	if t, ok := p.Functions[funcName]; ok {
		return t
	}
	t := &Type{Name: Name{Package: p.Path, Name: funcName}}
	t.Kind = DeclarationOf
	p.Functions[funcName] = t
	return t
}
func (p *Package) Variable(varName string) *Type {
	if t, ok := p.Variables[varName]; ok {
		return t
	}
	t := &Type{Name: Name{Package: p.Path, Name: varName}}
	t.Kind = DeclarationOf
	p.Variables[varName] = t
	return t
}
func (p *Package) HasImport(packageName string) bool {
	_, has := p.Imports[packageName]
	return has
}
type Universe map[string]*Package
func (u Universe) Type(n Name) *Type {
	return u.Package(n.Package).Type(n.Name)
}
func (u Universe) Function(n Name) *Type {
	return u.Package(n.Package).Function(n.Name)
}
func (u Universe) Variable(n Name) *Type {
	return u.Package(n.Package).Variable(n.Name)
}
func (u Universe) AddImports(packagePath string, importPaths ...string) {
	p := u.Package(packagePath)
	for _, i := range importPaths {
		p.Imports[i] = u.Package(i)
	}
}
func (u Universe) Package(packagePath string) *Package {
	if p, ok := u[packagePath]; ok {
		return p
	}
	p := &Package{
		Path:      packagePath,
		Types:     map[string]*Type{},
		Functions: map[string]*Type{},
		Variables: map[string]*Type{},
		Imports:   map[string]*Package{},
	}
	u[packagePath] = p
	return p
}
type Type struct {
	Name Name
	Kind Kind
	CommentLines []string
	SecondClosestCommentLines []string
	Members []Member
	Elem *Type
	Key *Type
	Underlying *Type
	Methods map[string]*Type
	Signature *Signature
}
func (t *Type) String() string {
	return t.Name.String()
}