.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / honnef.co / go / tools@v0.1.1 / go / types / typeutil / util.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.1.1/go/types/typeutil/util.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.1.1/go/types/typeutil/util.go
new file mode 100644 (file)
index 0000000..b0aca16
--- /dev/null
@@ -0,0 +1,131 @@
+package typeutil
+
+import (
+       "bytes"
+       "go/types"
+       "sync"
+)
+
+var bufferPool = &sync.Pool{
+       New: func() interface{} {
+               buf := bytes.NewBuffer(nil)
+               buf.Grow(64)
+               return buf
+       },
+}
+
+func FuncName(f *types.Func) string {
+       buf := bufferPool.Get().(*bytes.Buffer)
+       buf.Reset()
+       if f.Type() != nil {
+               sig := f.Type().(*types.Signature)
+               if recv := sig.Recv(); recv != nil {
+                       buf.WriteByte('(')
+                       if _, ok := recv.Type().(*types.Interface); ok {
+                               // gcimporter creates abstract methods of
+                               // named interfaces using the interface type
+                               // (not the named type) as the receiver.
+                               // Don't print it in full.
+                               buf.WriteString("interface")
+                       } else {
+                               types.WriteType(buf, recv.Type(), nil)
+                       }
+                       buf.WriteByte(')')
+                       buf.WriteByte('.')
+               } else if f.Pkg() != nil {
+                       writePackage(buf, f.Pkg())
+               }
+       }
+       buf.WriteString(f.Name())
+       s := buf.String()
+       bufferPool.Put(buf)
+       return s
+}
+
+func writePackage(buf *bytes.Buffer, pkg *types.Package) {
+       if pkg == nil {
+               return
+       }
+       s := pkg.Path()
+       if s != "" {
+               buf.WriteString(s)
+               buf.WriteByte('.')
+       }
+}
+
+// Dereference returns a pointer's element type; otherwise it returns
+// T.
+func Dereference(T types.Type) types.Type {
+       if p, ok := T.Underlying().(*types.Pointer); ok {
+               return p.Elem()
+       }
+       return T
+}
+
+// DereferenceR returns a pointer's element type; otherwise it returns
+// T. If the element type is itself a pointer, DereferenceR will be
+// applied recursively.
+func DereferenceR(T types.Type) types.Type {
+       if p, ok := T.Underlying().(*types.Pointer); ok {
+               return DereferenceR(p.Elem())
+       }
+       return T
+}
+
+func IsObject(obj types.Object, name string) bool {
+       var path string
+       if pkg := obj.Pkg(); pkg != nil {
+               path = pkg.Path() + "."
+       }
+       return path+obj.Name() == name
+}
+
+// OPT(dh): IsType is kind of expensive; should we really use it?
+func IsType(T types.Type, name string) bool { return types.TypeString(T, nil) == name }
+
+func IsPointerLike(T types.Type) bool {
+       switch T := T.Underlying().(type) {
+       case *types.Interface, *types.Chan, *types.Map, *types.Signature, *types.Pointer, *types.Slice:
+               return true
+       case *types.Basic:
+               return T.Kind() == types.UnsafePointer
+       }
+       return false
+}
+
+type Field struct {
+       Var  *types.Var
+       Tag  string
+       Path []int
+}
+
+// FlattenFields recursively flattens T and embedded structs,
+// returning a list of fields. If multiple fields with the same name
+// exist, all will be returned.
+func FlattenFields(T *types.Struct) []Field {
+       return flattenFields(T, nil, nil)
+}
+
+func flattenFields(T *types.Struct, path []int, seen map[types.Type]bool) []Field {
+       if seen == nil {
+               seen = map[types.Type]bool{}
+       }
+       if seen[T] {
+               return nil
+       }
+       seen[T] = true
+       var out []Field
+       for i := 0; i < T.NumFields(); i++ {
+               field := T.Field(i)
+               tag := T.Tag(i)
+               np := append(path[:len(path):len(path)], i)
+               if field.Anonymous() {
+                       if s, ok := Dereference(field.Type()).Underlying().(*types.Struct); ok {
+                               out = append(out, flattenFields(s, np, seen)...)
+                       }
+               } else {
+                       out = append(out, Field{field, tag, np})
+               }
+       }
+       return out
+}