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 / lint / lintutil / util.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.0.1-2020.1.5/lint/lintutil/util.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.0.1-2020.1.5/lint/lintutil/util.go
new file mode 100644 (file)
index 0000000..7c3dbde
--- /dev/null
@@ -0,0 +1,444 @@
+// Copyright (c) 2013 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 or at
+// https://developers.google.com/open-source/licenses/bsd.
+
+// Package lintutil provides helpers for writing linter command lines.
+package lintutil // import "honnef.co/go/tools/lint/lintutil"
+
+import (
+       "crypto/sha256"
+       "errors"
+       "flag"
+       "fmt"
+       "go/build"
+       "go/token"
+       "io"
+       "log"
+       "os"
+       "os/signal"
+       "regexp"
+       "runtime"
+       "runtime/pprof"
+       "strconv"
+       "strings"
+       "sync"
+       "sync/atomic"
+       "time"
+
+       "honnef.co/go/tools/config"
+       "honnef.co/go/tools/internal/cache"
+       "honnef.co/go/tools/lint"
+       "honnef.co/go/tools/lint/lintutil/format"
+       "honnef.co/go/tools/version"
+
+       "golang.org/x/tools/go/analysis"
+       "golang.org/x/tools/go/buildutil"
+       "golang.org/x/tools/go/packages"
+)
+
+func NewVersionFlag() flag.Getter {
+       tags := build.Default.ReleaseTags
+       v := tags[len(tags)-1][2:]
+       version := new(VersionFlag)
+       if err := version.Set(v); err != nil {
+               panic(fmt.Sprintf("internal error: %s", err))
+       }
+       return version
+}
+
+type VersionFlag int
+
+func (v *VersionFlag) String() string {
+       return fmt.Sprintf("1.%d", *v)
+
+}
+
+func (v *VersionFlag) Set(s string) error {
+       if len(s) < 3 {
+               return errors.New("invalid Go version")
+       }
+       if s[0] != '1' {
+               return errors.New("invalid Go version")
+       }
+       if s[1] != '.' {
+               return errors.New("invalid Go version")
+       }
+       i, err := strconv.Atoi(s[2:])
+       *v = VersionFlag(i)
+       return err
+}
+
+func (v *VersionFlag) Get() interface{} {
+       return int(*v)
+}
+
+func usage(name string, flags *flag.FlagSet) func() {
+       return func() {
+               fmt.Fprintf(os.Stderr, "Usage of %s:\n", name)
+               fmt.Fprintf(os.Stderr, "\t%s [flags] # runs on package in current directory\n", name)
+               fmt.Fprintf(os.Stderr, "\t%s [flags] packages\n", name)
+               fmt.Fprintf(os.Stderr, "\t%s [flags] directory\n", name)
+               fmt.Fprintf(os.Stderr, "\t%s [flags] files... # must be a single package\n", name)
+               fmt.Fprintf(os.Stderr, "Flags:\n")
+               flags.PrintDefaults()
+       }
+}
+
+type list []string
+
+func (list *list) String() string {
+       return `"` + strings.Join(*list, ",") + `"`
+}
+
+func (list *list) Set(s string) error {
+       if s == "" {
+               *list = nil
+               return nil
+       }
+
+       *list = strings.Split(s, ",")
+       return nil
+}
+
+func FlagSet(name string) *flag.FlagSet {
+       flags := flag.NewFlagSet("", flag.ExitOnError)
+       flags.Usage = usage(name, flags)
+       flags.String("tags", "", "List of `build tags`")
+       flags.Bool("tests", true, "Include tests")
+       flags.Bool("version", false, "Print version and exit")
+       flags.Bool("show-ignored", false, "Don't filter ignored problems")
+       flags.String("f", "text", "Output `format` (valid choices are 'stylish', 'text' and 'json')")
+       flags.String("explain", "", "Print description of `check`")
+
+       flags.String("debug.cpuprofile", "", "Write CPU profile to `file`")
+       flags.String("debug.memprofile", "", "Write memory profile to `file`")
+       flags.Bool("debug.version", false, "Print detailed version information about this program")
+       flags.Bool("debug.no-compile-errors", false, "Don't print compile errors")
+       flags.String("debug.measure-analyzers", "", "Write analysis measurements to `file`. `file` will be opened for appending if it already exists.")
+       flags.Uint("debug.repeat-analyzers", 0, "Run analyzers `num` times")
+
+       checks := list{"inherit"}
+       fail := list{"all"}
+       flags.Var(&checks, "checks", "Comma-separated list of `checks` to enable.")
+       flags.Var(&fail, "fail", "Comma-separated list of `checks` that can cause a non-zero exit status.")
+
+       tags := build.Default.ReleaseTags
+       v := tags[len(tags)-1][2:]
+       version := new(VersionFlag)
+       if err := version.Set(v); err != nil {
+               panic(fmt.Sprintf("internal error: %s", err))
+       }
+
+       flags.Var(version, "go", "Target Go `version` in the format '1.x'")
+       return flags
+}
+
+func findCheck(cs []*analysis.Analyzer, check string) (*analysis.Analyzer, bool) {
+       for _, c := range cs {
+               if c.Name == check {
+                       return c, true
+               }
+       }
+       return nil, false
+}
+
+func ProcessFlagSet(cs []*analysis.Analyzer, cums []lint.CumulativeChecker, fs *flag.FlagSet) {
+       tags := fs.Lookup("tags").Value.(flag.Getter).Get().(string)
+       tests := fs.Lookup("tests").Value.(flag.Getter).Get().(bool)
+       goVersion := fs.Lookup("go").Value.(flag.Getter).Get().(int)
+       formatter := fs.Lookup("f").Value.(flag.Getter).Get().(string)
+       printVersion := fs.Lookup("version").Value.(flag.Getter).Get().(bool)
+       showIgnored := fs.Lookup("show-ignored").Value.(flag.Getter).Get().(bool)
+       explain := fs.Lookup("explain").Value.(flag.Getter).Get().(string)
+
+       cpuProfile := fs.Lookup("debug.cpuprofile").Value.(flag.Getter).Get().(string)
+       memProfile := fs.Lookup("debug.memprofile").Value.(flag.Getter).Get().(string)
+       debugVersion := fs.Lookup("debug.version").Value.(flag.Getter).Get().(bool)
+       debugNoCompile := fs.Lookup("debug.no-compile-errors").Value.(flag.Getter).Get().(bool)
+       debugRepeat := fs.Lookup("debug.repeat-analyzers").Value.(flag.Getter).Get().(uint)
+
+       var measureAnalyzers func(analysis *analysis.Analyzer, pkg *lint.Package, d time.Duration)
+       if path := fs.Lookup("debug.measure-analyzers").Value.(flag.Getter).Get().(string); path != "" {
+               f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
+               if err != nil {
+                       log.Fatal(err)
+               }
+
+               mu := &sync.Mutex{}
+               measureAnalyzers = func(analysis *analysis.Analyzer, pkg *lint.Package, d time.Duration) {
+                       mu.Lock()
+                       defer mu.Unlock()
+                       if _, err := fmt.Fprintf(f, "%s\t%s\t%d\n", analysis.Name, pkg.ID, d.Nanoseconds()); err != nil {
+                               log.Println("error writing analysis measurements:", err)
+                       }
+               }
+       }
+
+       cfg := config.Config{}
+       cfg.Checks = *fs.Lookup("checks").Value.(*list)
+
+       exit := func(code int) {
+               if cpuProfile != "" {
+                       pprof.StopCPUProfile()
+               }
+               if memProfile != "" {
+                       f, err := os.Create(memProfile)
+                       if err != nil {
+                               panic(err)
+                       }
+                       runtime.GC()
+                       pprof.WriteHeapProfile(f)
+               }
+               os.Exit(code)
+       }
+       if cpuProfile != "" {
+               f, err := os.Create(cpuProfile)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               pprof.StartCPUProfile(f)
+       }
+
+       if debugVersion {
+               version.Verbose()
+               exit(0)
+       }
+
+       if printVersion {
+               version.Print()
+               exit(0)
+       }
+
+       // Validate that the tags argument is well-formed. go/packages
+       // doesn't detect malformed build flags and returns unhelpful
+       // errors.
+       tf := buildutil.TagsFlag{}
+       if err := tf.Set(tags); err != nil {
+               fmt.Fprintln(os.Stderr, fmt.Errorf("invalid value %q for flag -tags: %s", tags, err))
+               exit(1)
+       }
+
+       if explain != "" {
+               var haystack []*analysis.Analyzer
+               haystack = append(haystack, cs...)
+               for _, cum := range cums {
+                       haystack = append(haystack, cum.Analyzer())
+               }
+               check, ok := findCheck(haystack, explain)
+               if !ok {
+                       fmt.Fprintln(os.Stderr, "Couldn't find check", explain)
+                       exit(1)
+               }
+               if check.Doc == "" {
+                       fmt.Fprintln(os.Stderr, explain, "has no documentation")
+                       exit(1)
+               }
+               fmt.Println(check.Doc)
+               exit(0)
+       }
+
+       ps, err := Lint(cs, cums, fs.Args(), &Options{
+               Tags:                     tags,
+               LintTests:                tests,
+               GoVersion:                goVersion,
+               Config:                   cfg,
+               PrintAnalyzerMeasurement: measureAnalyzers,
+               RepeatAnalyzers:          debugRepeat,
+       })
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               exit(1)
+       }
+
+       var f format.Formatter
+       switch formatter {
+       case "text":
+               f = format.Text{W: os.Stdout}
+       case "stylish":
+               f = &format.Stylish{W: os.Stdout}
+       case "json":
+               f = format.JSON{W: os.Stdout}
+       default:
+               fmt.Fprintf(os.Stderr, "unsupported output format %q\n", formatter)
+               exit(2)
+       }
+
+       var (
+               total    int
+               errors   int
+               warnings int
+               ignored  int
+       )
+
+       fail := *fs.Lookup("fail").Value.(*list)
+       analyzers := make([]*analysis.Analyzer, len(cs), len(cs)+len(cums))
+       copy(analyzers, cs)
+       for _, cum := range cums {
+               analyzers = append(analyzers, cum.Analyzer())
+       }
+       shouldExit := lint.FilterChecks(analyzers, fail)
+       shouldExit["compile"] = true
+
+       total = len(ps)
+       for _, p := range ps {
+               if p.Check == "compile" && debugNoCompile {
+                       continue
+               }
+               if p.Severity == lint.Ignored && !showIgnored {
+                       ignored++
+                       continue
+               }
+               if shouldExit[p.Check] {
+                       errors++
+               } else {
+                       p.Severity = lint.Warning
+                       warnings++
+               }
+               f.Format(p)
+       }
+       if f, ok := f.(format.Statter); ok {
+               f.Stats(total, errors, warnings, ignored)
+       }
+       if errors > 0 {
+               exit(1)
+       }
+       exit(0)
+}
+
+type Options struct {
+       Config config.Config
+
+       Tags                     string
+       LintTests                bool
+       GoVersion                int
+       PrintAnalyzerMeasurement func(analysis *analysis.Analyzer, pkg *lint.Package, d time.Duration)
+       RepeatAnalyzers          uint
+}
+
+func computeSalt() ([]byte, error) {
+       if version.Version != "devel" {
+               return []byte(version.Version), nil
+       }
+       p, err := os.Executable()
+       if err != nil {
+               return nil, err
+       }
+       f, err := os.Open(p)
+       if err != nil {
+               return nil, err
+       }
+       defer f.Close()
+       h := sha256.New()
+       if _, err := io.Copy(h, f); err != nil {
+               return nil, err
+       }
+       return h.Sum(nil), nil
+}
+
+func Lint(cs []*analysis.Analyzer, cums []lint.CumulativeChecker, paths []string, opt *Options) ([]lint.Problem, error) {
+       salt, err := computeSalt()
+       if err != nil {
+               return nil, fmt.Errorf("could not compute salt for cache: %s", err)
+       }
+       cache.SetSalt(salt)
+
+       if opt == nil {
+               opt = &Options{}
+       }
+
+       l := &lint.Linter{
+               Checkers:           cs,
+               CumulativeCheckers: cums,
+               GoVersion:          opt.GoVersion,
+               Config:             opt.Config,
+               RepeatAnalyzers:    opt.RepeatAnalyzers,
+       }
+       l.Stats.PrintAnalyzerMeasurement = opt.PrintAnalyzerMeasurement
+       cfg := &packages.Config{}
+       if opt.LintTests {
+               cfg.Tests = true
+       }
+       if opt.Tags != "" {
+               cfg.BuildFlags = append(cfg.BuildFlags, "-tags", opt.Tags)
+       }
+
+       printStats := func() {
+               // Individual stats are read atomically, but overall there
+               // is no synchronisation. For printing rough progress
+               // information, this doesn't matter.
+               switch atomic.LoadUint32(&l.Stats.State) {
+               case lint.StateInitializing:
+                       fmt.Fprintln(os.Stderr, "Status: initializing")
+               case lint.StateGraph:
+                       fmt.Fprintln(os.Stderr, "Status: loading package graph")
+               case lint.StateProcessing:
+                       fmt.Fprintf(os.Stderr, "Packages: %d/%d initial, %d/%d total; Workers: %d/%d; Problems: %d\n",
+                               atomic.LoadUint32(&l.Stats.ProcessedInitialPackages),
+                               atomic.LoadUint32(&l.Stats.InitialPackages),
+                               atomic.LoadUint32(&l.Stats.ProcessedPackages),
+                               atomic.LoadUint32(&l.Stats.TotalPackages),
+                               atomic.LoadUint32(&l.Stats.ActiveWorkers),
+                               atomic.LoadUint32(&l.Stats.TotalWorkers),
+                               atomic.LoadUint32(&l.Stats.Problems),
+                       )
+               case lint.StateCumulative:
+                       fmt.Fprintln(os.Stderr, "Status: processing cumulative checkers")
+               }
+       }
+       if len(infoSignals) > 0 {
+               ch := make(chan os.Signal, 1)
+               signal.Notify(ch, infoSignals...)
+               defer signal.Stop(ch)
+               go func() {
+                       for range ch {
+                               printStats()
+                       }
+               }()
+       }
+
+       ps, err := l.Lint(cfg, paths)
+       return ps, err
+}
+
+var posRe = regexp.MustCompile(`^(.+?):(\d+)(?::(\d+)?)?$`)
+
+func parsePos(pos string) token.Position {
+       if pos == "-" || pos == "" {
+               return token.Position{}
+       }
+       parts := posRe.FindStringSubmatch(pos)
+       if parts == nil {
+               panic(fmt.Sprintf("internal error: malformed position %q", pos))
+       }
+       file := parts[1]
+       line, _ := strconv.Atoi(parts[2])
+       col, _ := strconv.Atoi(parts[3])
+       return token.Position{
+               Filename: file,
+               Line:     line,
+               Column:   col,
+       }
+}
+
+func InitializeAnalyzers(docs map[string]*lint.Documentation, analyzers map[string]*analysis.Analyzer) map[string]*analysis.Analyzer {
+       out := make(map[string]*analysis.Analyzer, len(analyzers))
+       for k, v := range analyzers {
+               vc := *v
+               out[k] = &vc
+
+               vc.Name = k
+               doc, ok := docs[k]
+               if !ok {
+                       panic(fmt.Sprintf("missing documentation for check %s", k))
+               }
+               vc.Doc = doc.String()
+               if vc.Flags.Usage == nil {
+                       fs := flag.NewFlagSet("", flag.PanicOnError)
+                       fs.Var(NewVersionFlag(), "go", "Target Go version")
+                       vc.Flags = *fs
+               }
+       }
+       return out
+}