9 var bufferPool = &sync.Pool{
10 New: func() interface{} {
11 buf := bytes.NewBuffer(nil)
17 func FuncName(f *types.Func) string {
18 buf := bufferPool.Get().(*bytes.Buffer)
21 sig := f.Type().(*types.Signature)
22 if recv := sig.Recv(); recv != nil {
24 if _, ok := recv.Type().(*types.Interface); ok {
25 // gcimporter creates abstract methods of
26 // named interfaces using the interface type
27 // (not the named type) as the receiver.
28 // Don't print it in full.
29 buf.WriteString("interface")
31 types.WriteType(buf, recv.Type(), nil)
35 } else if f.Pkg() != nil {
36 writePackage(buf, f.Pkg())
39 buf.WriteString(f.Name())
45 func writePackage(buf *bytes.Buffer, pkg *types.Package) {
56 // Dereference returns a pointer's element type; otherwise it returns
58 func Dereference(T types.Type) types.Type {
59 if p, ok := T.Underlying().(*types.Pointer); ok {
65 // DereferenceR returns a pointer's element type; otherwise it returns
66 // T. If the element type is itself a pointer, DereferenceR will be
67 // applied recursively.
68 func DereferenceR(T types.Type) types.Type {
69 if p, ok := T.Underlying().(*types.Pointer); ok {
70 return DereferenceR(p.Elem())
75 func IsObject(obj types.Object, name string) bool {
77 if pkg := obj.Pkg(); pkg != nil {
78 path = pkg.Path() + "."
80 return path+obj.Name() == name
83 // OPT(dh): IsType is kind of expensive; should we really use it?
84 func IsType(T types.Type, name string) bool { return types.TypeString(T, nil) == name }
86 func IsPointerLike(T types.Type) bool {
87 switch T := T.Underlying().(type) {
88 case *types.Interface, *types.Chan, *types.Map, *types.Signature, *types.Pointer, *types.Slice:
91 return T.Kind() == types.UnsafePointer
102 // FlattenFields recursively flattens T and embedded structs,
103 // returning a list of fields. If multiple fields with the same name
104 // exist, all will be returned.
105 func FlattenFields(T *types.Struct) []Field {
106 return flattenFields(T, nil, nil)
109 func flattenFields(T *types.Struct, path []int, seen map[types.Type]bool) []Field {
111 seen = map[types.Type]bool{}
118 for i := 0; i < T.NumFields(); i++ {
121 np := append(path[:len(path):len(path)], i)
122 if field.Anonymous() {
123 if s, ok := Dereference(field.Type()).Underlying().(*types.Struct); ok {
124 out = append(out, flattenFields(s, np, seen)...)
127 out = append(out, Field{field, tag, np})