.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.1-0.20210319172145-bda8f5cee399 / internal / lsp / source / completion / util.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.1-0.20210319172145-bda8f5cee399/internal/lsp/source/completion/util.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.1-0.20210319172145-bda8f5cee399/internal/lsp/source/completion/util.go
new file mode 100644 (file)
index 0000000..6733906
--- /dev/null
@@ -0,0 +1,312 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package completion
+
+import (
+       "go/ast"
+       "go/token"
+       "go/types"
+
+       "golang.org/x/tools/internal/lsp/source"
+)
+
+// exprAtPos returns the index of the expression containing pos.
+func exprAtPos(pos token.Pos, args []ast.Expr) int {
+       for i, expr := range args {
+               if expr.Pos() <= pos && pos <= expr.End() {
+                       return i
+               }
+       }
+       return len(args)
+}
+
+// eachField invokes fn for each field that can be selected from a
+// value of type T.
+func eachField(T types.Type, fn func(*types.Var)) {
+       // TODO(adonovan): this algorithm doesn't exclude ambiguous
+       // selections that match more than one field/method.
+       // types.NewSelectionSet should do that for us.
+
+       // for termination on recursive types
+       var seen map[*types.Struct]bool
+
+       var visit func(T types.Type)
+       visit = func(T types.Type) {
+               if T, ok := source.Deref(T).Underlying().(*types.Struct); ok {
+                       if seen[T] {
+                               return
+                       }
+
+                       for i := 0; i < T.NumFields(); i++ {
+                               f := T.Field(i)
+                               fn(f)
+                               if f.Anonymous() {
+                                       if seen == nil {
+                                               // Lazily create "seen" since it is only needed for
+                                               // embedded structs.
+                                               seen = make(map[*types.Struct]bool)
+                                       }
+                                       seen[T] = true
+                                       visit(f.Type())
+                               }
+                       }
+               }
+       }
+       visit(T)
+}
+
+// typeIsValid reports whether typ doesn't contain any Invalid types.
+func typeIsValid(typ types.Type) bool {
+       // Check named types separately, because we don't want
+       // to call Underlying() on them to avoid problems with recursive types.
+       if _, ok := typ.(*types.Named); ok {
+               return true
+       }
+
+       switch typ := typ.Underlying().(type) {
+       case *types.Basic:
+               return typ.Kind() != types.Invalid
+       case *types.Array:
+               return typeIsValid(typ.Elem())
+       case *types.Slice:
+               return typeIsValid(typ.Elem())
+       case *types.Pointer:
+               return typeIsValid(typ.Elem())
+       case *types.Map:
+               return typeIsValid(typ.Key()) && typeIsValid(typ.Elem())
+       case *types.Chan:
+               return typeIsValid(typ.Elem())
+       case *types.Signature:
+               return typeIsValid(typ.Params()) && typeIsValid(typ.Results())
+       case *types.Tuple:
+               for i := 0; i < typ.Len(); i++ {
+                       if !typeIsValid(typ.At(i).Type()) {
+                               return false
+                       }
+               }
+               return true
+       case *types.Struct, *types.Interface:
+               // Don't bother checking structs, interfaces for validity.
+               return true
+       default:
+               return false
+       }
+}
+
+// resolveInvalid traverses the node of the AST that defines the scope
+// containing the declaration of obj, and attempts to find a user-friendly
+// name for its invalid type. The resulting Object and its Type are fake.
+func resolveInvalid(fset *token.FileSet, obj types.Object, node ast.Node, info *types.Info) types.Object {
+       var resultExpr ast.Expr
+       ast.Inspect(node, func(node ast.Node) bool {
+               switch n := node.(type) {
+               case *ast.ValueSpec:
+                       for _, name := range n.Names {
+                               if info.Defs[name] == obj {
+                                       resultExpr = n.Type
+                               }
+                       }
+                       return false
+               case *ast.Field: // This case handles parameters and results of a FuncDecl or FuncLit.
+                       for _, name := range n.Names {
+                               if info.Defs[name] == obj {
+                                       resultExpr = n.Type
+                               }
+                       }
+                       return false
+               default:
+                       return true
+               }
+       })
+       // Construct a fake type for the object and return a fake object with this type.
+       typename := source.FormatNode(fset, resultExpr)
+       typ := types.NewNamed(types.NewTypeName(token.NoPos, obj.Pkg(), typename, nil), types.Typ[types.Invalid], nil)
+       return types.NewVar(obj.Pos(), obj.Pkg(), obj.Name(), typ)
+}
+
+func isPointer(T types.Type) bool {
+       _, ok := T.(*types.Pointer)
+       return ok
+}
+
+func isVar(obj types.Object) bool {
+       _, ok := obj.(*types.Var)
+       return ok
+}
+
+func isTypeName(obj types.Object) bool {
+       _, ok := obj.(*types.TypeName)
+       return ok
+}
+
+func isFunc(obj types.Object) bool {
+       _, ok := obj.(*types.Func)
+       return ok
+}
+
+func isEmptyInterface(T types.Type) bool {
+       intf, _ := T.(*types.Interface)
+       return intf != nil && intf.NumMethods() == 0
+}
+
+func isUntyped(T types.Type) bool {
+       if basic, ok := T.(*types.Basic); ok {
+               return basic.Info()&types.IsUntyped > 0
+       }
+       return false
+}
+
+func isPkgName(obj types.Object) bool {
+       _, ok := obj.(*types.PkgName)
+       return ok
+}
+
+func isASTFile(n ast.Node) bool {
+       _, ok := n.(*ast.File)
+       return ok
+}
+
+func deslice(T types.Type) types.Type {
+       if slice, ok := T.Underlying().(*types.Slice); ok {
+               return slice.Elem()
+       }
+       return nil
+}
+
+// isSelector returns the enclosing *ast.SelectorExpr when pos is in the
+// selector.
+func enclosingSelector(path []ast.Node, pos token.Pos) *ast.SelectorExpr {
+       if len(path) == 0 {
+               return nil
+       }
+
+       if sel, ok := path[0].(*ast.SelectorExpr); ok {
+               return sel
+       }
+
+       if _, ok := path[0].(*ast.Ident); ok && len(path) > 1 {
+               if sel, ok := path[1].(*ast.SelectorExpr); ok && pos >= sel.Sel.Pos() {
+                       return sel
+               }
+       }
+
+       return nil
+}
+
+// enclosingDeclLHS returns LHS idents from containing value spec or
+// assign statement.
+func enclosingDeclLHS(path []ast.Node) []*ast.Ident {
+       for _, n := range path {
+               switch n := n.(type) {
+               case *ast.ValueSpec:
+                       return n.Names
+               case *ast.AssignStmt:
+                       ids := make([]*ast.Ident, 0, len(n.Lhs))
+                       for _, e := range n.Lhs {
+                               if id, ok := e.(*ast.Ident); ok {
+                                       ids = append(ids, id)
+                               }
+                       }
+                       return ids
+               }
+       }
+
+       return nil
+}
+
+// exprObj returns the types.Object associated with the *ast.Ident or
+// *ast.SelectorExpr e.
+func exprObj(info *types.Info, e ast.Expr) types.Object {
+       var ident *ast.Ident
+       switch expr := e.(type) {
+       case *ast.Ident:
+               ident = expr
+       case *ast.SelectorExpr:
+               ident = expr.Sel
+       default:
+               return nil
+       }
+
+       return info.ObjectOf(ident)
+}
+
+// typeConversion returns the type being converted to if call is a type
+// conversion expression.
+func typeConversion(call *ast.CallExpr, info *types.Info) types.Type {
+       // Type conversion (e.g. "float64(foo)").
+       if fun, _ := exprObj(info, call.Fun).(*types.TypeName); fun != nil {
+               return fun.Type()
+       }
+
+       return nil
+}
+
+// fieldsAccessible returns whether s has at least one field accessible by p.
+func fieldsAccessible(s *types.Struct, p *types.Package) bool {
+       for i := 0; i < s.NumFields(); i++ {
+               f := s.Field(i)
+               if f.Exported() || f.Pkg() == p {
+                       return true
+               }
+       }
+       return false
+}
+
+// prevStmt returns the statement that precedes the statement containing pos.
+// For example:
+//
+//     foo := 1
+//     bar(1 + 2<>)
+//
+// If "<>" is pos, prevStmt returns "foo := 1"
+func prevStmt(pos token.Pos, path []ast.Node) ast.Stmt {
+       var blockLines []ast.Stmt
+       for i := 0; i < len(path) && blockLines == nil; i++ {
+               switch n := path[i].(type) {
+               case *ast.BlockStmt:
+                       blockLines = n.List
+               case *ast.CommClause:
+                       blockLines = n.Body
+               case *ast.CaseClause:
+                       blockLines = n.Body
+               }
+       }
+
+       for i := len(blockLines) - 1; i >= 0; i-- {
+               if blockLines[i].End() < pos {
+                       return blockLines[i]
+               }
+       }
+
+       return nil
+}
+
+// formatZeroValue produces Go code representing the zero value of T. It
+// returns the empty string if T is invalid.
+func formatZeroValue(T types.Type, qf types.Qualifier) string {
+       switch u := T.Underlying().(type) {
+       case *types.Basic:
+               switch {
+               case u.Info()&types.IsNumeric > 0:
+                       return "0"
+               case u.Info()&types.IsString > 0:
+                       return `""`
+               case u.Info()&types.IsBoolean > 0:
+                       return "false"
+               default:
+                       return ""
+               }
+       case *types.Pointer, *types.Interface, *types.Chan, *types.Map, *types.Slice, *types.Signature:
+               return "nil"
+       default:
+               return types.TypeString(T, qf) + "{}"
+       }
+}
+
+// isBasicKind returns whether t is a basic type of kind k.
+func isBasicKind(t types.Type, k types.BasicInfo) bool {
+       b, _ := t.Underlying().(*types.Basic)
+       return b != nil && b.Info()&k > 0
+}