Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / honnef.co / go / tools@v0.0.1-2020.1.5 / code / code.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.0.1-2020.1.5/code/code.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.0.1-2020.1.5/code/code.go
new file mode 100644 (file)
index 0000000..6f4df8b
--- /dev/null
@@ -0,0 +1,481 @@
+// Package code answers structural and type questions about Go code.
+package code
+
+import (
+       "flag"
+       "fmt"
+       "go/ast"
+       "go/constant"
+       "go/token"
+       "go/types"
+       "strings"
+
+       "golang.org/x/tools/go/analysis"
+       "golang.org/x/tools/go/analysis/passes/inspect"
+       "golang.org/x/tools/go/ast/astutil"
+       "golang.org/x/tools/go/ast/inspector"
+       "honnef.co/go/tools/facts"
+       "honnef.co/go/tools/go/types/typeutil"
+       "honnef.co/go/tools/ir"
+       "honnef.co/go/tools/lint"
+)
+
+type Positioner interface {
+       Pos() token.Pos
+}
+
+func CallName(call *ir.CallCommon) string {
+       if call.IsInvoke() {
+               return ""
+       }
+       switch v := call.Value.(type) {
+       case *ir.Function:
+               fn, ok := v.Object().(*types.Func)
+               if !ok {
+                       return ""
+               }
+               return lint.FuncName(fn)
+       case *ir.Builtin:
+               return v.Name()
+       }
+       return ""
+}
+
+func IsCallTo(call *ir.CallCommon, name string) bool { return CallName(call) == name }
+
+func IsCallToAny(call *ir.CallCommon, names ...string) bool {
+       q := CallName(call)
+       for _, name := range names {
+               if q == name {
+                       return true
+               }
+       }
+       return false
+}
+
+func IsType(T types.Type, name string) bool { return types.TypeString(T, nil) == name }
+
+func FilterDebug(instr []ir.Instruction) []ir.Instruction {
+       var out []ir.Instruction
+       for _, ins := range instr {
+               if _, ok := ins.(*ir.DebugRef); !ok {
+                       out = append(out, ins)
+               }
+       }
+       return out
+}
+
+func IsExample(fn *ir.Function) bool {
+       if !strings.HasPrefix(fn.Name(), "Example") {
+               return false
+       }
+       f := fn.Prog.Fset.File(fn.Pos())
+       if f == nil {
+               return false
+       }
+       return strings.HasSuffix(f.Name(), "_test.go")
+}
+
+func IsPointerLike(T types.Type) bool {
+       switch T := T.Underlying().(type) {
+       case *types.Interface, *types.Chan, *types.Map, *types.Signature, *types.Pointer:
+               return true
+       case *types.Basic:
+               return T.Kind() == types.UnsafePointer
+       }
+       return false
+}
+
+func IsIdent(expr ast.Expr, ident string) bool {
+       id, ok := expr.(*ast.Ident)
+       return ok && id.Name == ident
+}
+
+// isBlank returns whether id is the blank identifier "_".
+// If id == nil, the answer is false.
+func IsBlank(id ast.Expr) bool {
+       ident, _ := id.(*ast.Ident)
+       return ident != nil && ident.Name == "_"
+}
+
+func IsIntLiteral(expr ast.Expr, literal string) bool {
+       lit, ok := expr.(*ast.BasicLit)
+       return ok && lit.Kind == token.INT && lit.Value == literal
+}
+
+// Deprecated: use IsIntLiteral instead
+func IsZero(expr ast.Expr) bool {
+       return IsIntLiteral(expr, "0")
+}
+
+func IsOfType(pass *analysis.Pass, expr ast.Expr, name string) bool {
+       return IsType(pass.TypesInfo.TypeOf(expr), name)
+}
+
+func IsInTest(pass *analysis.Pass, node Positioner) bool {
+       // FIXME(dh): this doesn't work for global variables with
+       // initializers
+       f := pass.Fset.File(node.Pos())
+       return f != nil && strings.HasSuffix(f.Name(), "_test.go")
+}
+
+// IsMain reports whether the package being processed is a package
+// main.
+func IsMain(pass *analysis.Pass) bool {
+       return pass.Pkg.Name() == "main"
+}
+
+// IsMainLike reports whether the package being processed is a
+// main-like package. A main-like package is a package that is
+// package main, or that is intended to be used by a tool framework
+// such as cobra to implement a command.
+//
+// Note that this function errs on the side of false positives; it may
+// return true for packages that aren't main-like. IsMainLike is
+// intended for analyses that wish to suppress diagnostics for
+// main-like packages to avoid false positives.
+func IsMainLike(pass *analysis.Pass) bool {
+       if pass.Pkg.Name() == "main" {
+               return true
+       }
+       for _, imp := range pass.Pkg.Imports() {
+               if imp.Path() == "github.com/spf13/cobra" {
+                       return true
+               }
+       }
+       return false
+}
+
+func SelectorName(pass *analysis.Pass, expr *ast.SelectorExpr) string {
+       info := pass.TypesInfo
+       sel := info.Selections[expr]
+       if sel == nil {
+               if x, ok := expr.X.(*ast.Ident); ok {
+                       pkg, ok := info.ObjectOf(x).(*types.PkgName)
+                       if !ok {
+                               // This shouldn't happen
+                               return fmt.Sprintf("%s.%s", x.Name, expr.Sel.Name)
+                       }
+                       return fmt.Sprintf("%s.%s", pkg.Imported().Path(), expr.Sel.Name)
+               }
+               panic(fmt.Sprintf("unsupported selector: %v", expr))
+       }
+       return fmt.Sprintf("(%s).%s", sel.Recv(), sel.Obj().Name())
+}
+
+func IsNil(pass *analysis.Pass, expr ast.Expr) bool {
+       return pass.TypesInfo.Types[expr].IsNil()
+}
+
+func BoolConst(pass *analysis.Pass, expr ast.Expr) bool {
+       val := pass.TypesInfo.ObjectOf(expr.(*ast.Ident)).(*types.Const).Val()
+       return constant.BoolVal(val)
+}
+
+func IsBoolConst(pass *analysis.Pass, expr ast.Expr) bool {
+       // We explicitly don't support typed bools because more often than
+       // not, custom bool types are used as binary enums and the
+       // explicit comparison is desired.
+
+       ident, ok := expr.(*ast.Ident)
+       if !ok {
+               return false
+       }
+       obj := pass.TypesInfo.ObjectOf(ident)
+       c, ok := obj.(*types.Const)
+       if !ok {
+               return false
+       }
+       basic, ok := c.Type().(*types.Basic)
+       if !ok {
+               return false
+       }
+       if basic.Kind() != types.UntypedBool && basic.Kind() != types.Bool {
+               return false
+       }
+       return true
+}
+
+func ExprToInt(pass *analysis.Pass, expr ast.Expr) (int64, bool) {
+       tv := pass.TypesInfo.Types[expr]
+       if tv.Value == nil {
+               return 0, false
+       }
+       if tv.Value.Kind() != constant.Int {
+               return 0, false
+       }
+       return constant.Int64Val(tv.Value)
+}
+
+func ExprToString(pass *analysis.Pass, expr ast.Expr) (string, bool) {
+       val := pass.TypesInfo.Types[expr].Value
+       if val == nil {
+               return "", false
+       }
+       if val.Kind() != constant.String {
+               return "", false
+       }
+       return constant.StringVal(val), true
+}
+
+// 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 CallNameAST(pass *analysis.Pass, call *ast.CallExpr) string {
+       switch fun := astutil.Unparen(call.Fun).(type) {
+       case *ast.SelectorExpr:
+               fn, ok := pass.TypesInfo.ObjectOf(fun.Sel).(*types.Func)
+               if !ok {
+                       return ""
+               }
+               return lint.FuncName(fn)
+       case *ast.Ident:
+               obj := pass.TypesInfo.ObjectOf(fun)
+               switch obj := obj.(type) {
+               case *types.Func:
+                       return lint.FuncName(obj)
+               case *types.Builtin:
+                       return obj.Name()
+               default:
+                       return ""
+               }
+       default:
+               return ""
+       }
+}
+
+func IsCallToAST(pass *analysis.Pass, node ast.Node, name string) bool {
+       call, ok := node.(*ast.CallExpr)
+       if !ok {
+               return false
+       }
+       return CallNameAST(pass, call) == name
+}
+
+func IsCallToAnyAST(pass *analysis.Pass, node ast.Node, names ...string) bool {
+       call, ok := node.(*ast.CallExpr)
+       if !ok {
+               return false
+       }
+       q := CallNameAST(pass, call)
+       for _, name := range names {
+               if q == name {
+                       return true
+               }
+       }
+       return false
+}
+
+func Preamble(f *ast.File) string {
+       cutoff := f.Package
+       if f.Doc != nil {
+               cutoff = f.Doc.Pos()
+       }
+       var out []string
+       for _, cmt := range f.Comments {
+               if cmt.Pos() >= cutoff {
+                       break
+               }
+               out = append(out, cmt.Text())
+       }
+       return strings.Join(out, "\n")
+}
+
+func GroupSpecs(fset *token.FileSet, specs []ast.Spec) [][]ast.Spec {
+       if len(specs) == 0 {
+               return nil
+       }
+       groups := make([][]ast.Spec, 1)
+       groups[0] = append(groups[0], specs[0])
+
+       for _, spec := range specs[1:] {
+               g := groups[len(groups)-1]
+               if fset.PositionFor(spec.Pos(), false).Line-1 !=
+                       fset.PositionFor(g[len(g)-1].End(), false).Line {
+
+                       groups = append(groups, nil)
+               }
+
+               groups[len(groups)-1] = append(groups[len(groups)-1], spec)
+       }
+
+       return groups
+}
+
+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
+}
+
+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
+}
+
+func File(pass *analysis.Pass, node Positioner) *ast.File {
+       m := pass.ResultOf[facts.TokenFile].(map[*token.File]*ast.File)
+       return m[pass.Fset.File(node.Pos())]
+}
+
+// IsGenerated reports whether pos is in a generated file, It ignores
+// //line directives.
+func IsGenerated(pass *analysis.Pass, pos token.Pos) bool {
+       _, ok := Generator(pass, pos)
+       return ok
+}
+
+// Generator returns the generator that generated the file containing
+// pos. It ignores //line directives.
+func Generator(pass *analysis.Pass, pos token.Pos) (facts.Generator, bool) {
+       file := pass.Fset.PositionFor(pos, false).Filename
+       m := pass.ResultOf[facts.Generated].(map[string]facts.Generator)
+       g, ok := m[file]
+       return g, ok
+}
+
+// MayHaveSideEffects reports whether expr may have side effects. If
+// the purity argument is nil, this function implements a purely
+// syntactic check, meaning that any function call may have side
+// effects, regardless of the called function's body. Otherwise,
+// purity will be consulted to determine the purity of function calls.
+func MayHaveSideEffects(pass *analysis.Pass, expr ast.Expr, purity facts.PurityResult) bool {
+       switch expr := expr.(type) {
+       case *ast.BadExpr:
+               return true
+       case *ast.Ellipsis:
+               return MayHaveSideEffects(pass, expr.Elt, purity)
+       case *ast.FuncLit:
+               // the literal itself cannot have side ffects, only calling it
+               // might, which is handled by CallExpr.
+               return false
+       case *ast.ArrayType, *ast.StructType, *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType:
+               // types cannot have side effects
+               return false
+       case *ast.BasicLit:
+               return false
+       case *ast.BinaryExpr:
+               return MayHaveSideEffects(pass, expr.X, purity) || MayHaveSideEffects(pass, expr.Y, purity)
+       case *ast.CallExpr:
+               if purity == nil {
+                       return true
+               }
+               switch obj := typeutil.Callee(pass.TypesInfo, expr).(type) {
+               case *types.Func:
+                       if _, ok := purity[obj]; !ok {
+                               return true
+                       }
+               case *types.Builtin:
+                       switch obj.Name() {
+                       case "len", "cap":
+                       default:
+                               return true
+                       }
+               default:
+                       return true
+               }
+               for _, arg := range expr.Args {
+                       if MayHaveSideEffects(pass, arg, purity) {
+                               return true
+                       }
+               }
+               return false
+       case *ast.CompositeLit:
+               if MayHaveSideEffects(pass, expr.Type, purity) {
+                       return true
+               }
+               for _, elt := range expr.Elts {
+                       if MayHaveSideEffects(pass, elt, purity) {
+                               return true
+                       }
+               }
+               return false
+       case *ast.Ident:
+               return false
+       case *ast.IndexExpr:
+               return MayHaveSideEffects(pass, expr.X, purity) || MayHaveSideEffects(pass, expr.Index, purity)
+       case *ast.KeyValueExpr:
+               return MayHaveSideEffects(pass, expr.Key, purity) || MayHaveSideEffects(pass, expr.Value, purity)
+       case *ast.SelectorExpr:
+               return MayHaveSideEffects(pass, expr.X, purity)
+       case *ast.SliceExpr:
+               return MayHaveSideEffects(pass, expr.X, purity) ||
+                       MayHaveSideEffects(pass, expr.Low, purity) ||
+                       MayHaveSideEffects(pass, expr.High, purity) ||
+                       MayHaveSideEffects(pass, expr.Max, purity)
+       case *ast.StarExpr:
+               return MayHaveSideEffects(pass, expr.X, purity)
+       case *ast.TypeAssertExpr:
+               return MayHaveSideEffects(pass, expr.X, purity)
+       case *ast.UnaryExpr:
+               if MayHaveSideEffects(pass, expr.X, purity) {
+                       return true
+               }
+               return expr.Op == token.ARROW
+       case *ast.ParenExpr:
+               return MayHaveSideEffects(pass, expr.X, purity)
+       case nil:
+               return false
+       default:
+               panic(fmt.Sprintf("internal error: unhandled type %T", expr))
+       }
+}
+
+func IsGoVersion(pass *analysis.Pass, minor int) bool {
+       version := pass.Analyzer.Flags.Lookup("go").Value.(flag.Getter).Get().(int)
+       return version >= minor
+}
+
+func Preorder(pass *analysis.Pass, fn func(ast.Node), types ...ast.Node) {
+       pass.ResultOf[inspect.Analyzer].(*inspector.Inspector).Preorder(types, fn)
+}