.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.1-0.20210319172145-bda8f5cee399 / go / buildutil / allpackages.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.1-0.20210319172145-bda8f5cee399/go/buildutil/allpackages.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.1-0.20210319172145-bda8f5cee399/go/buildutil/allpackages.go
new file mode 100644 (file)
index 0000000..c0cb03e
--- /dev/null
@@ -0,0 +1,198 @@
+// Copyright 2014 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 buildutil provides utilities related to the go/build
+// package in the standard library.
+//
+// All I/O is done via the build.Context file system interface, which must
+// be concurrency-safe.
+package buildutil // import "golang.org/x/tools/go/buildutil"
+
+import (
+       "go/build"
+       "os"
+       "path/filepath"
+       "sort"
+       "strings"
+       "sync"
+)
+
+// AllPackages returns the package path of each Go package in any source
+// directory of the specified build context (e.g. $GOROOT or an element
+// of $GOPATH).  Errors are ignored.  The results are sorted.
+// All package paths are canonical, and thus may contain "/vendor/".
+//
+// The result may include import paths for directories that contain no
+// *.go files, such as "archive" (in $GOROOT/src).
+//
+// All I/O is done via the build.Context file system interface,
+// which must be concurrency-safe.
+//
+func AllPackages(ctxt *build.Context) []string {
+       var list []string
+       ForEachPackage(ctxt, func(pkg string, _ error) {
+               list = append(list, pkg)
+       })
+       sort.Strings(list)
+       return list
+}
+
+// ForEachPackage calls the found function with the package path of
+// each Go package it finds in any source directory of the specified
+// build context (e.g. $GOROOT or an element of $GOPATH).
+// All package paths are canonical, and thus may contain "/vendor/".
+//
+// If the package directory exists but could not be read, the second
+// argument to the found function provides the error.
+//
+// All I/O is done via the build.Context file system interface,
+// which must be concurrency-safe.
+//
+func ForEachPackage(ctxt *build.Context, found func(importPath string, err error)) {
+       ch := make(chan item)
+
+       var wg sync.WaitGroup
+       for _, root := range ctxt.SrcDirs() {
+               root := root
+               wg.Add(1)
+               go func() {
+                       allPackages(ctxt, root, ch)
+                       wg.Done()
+               }()
+       }
+       go func() {
+               wg.Wait()
+               close(ch)
+       }()
+
+       // All calls to found occur in the caller's goroutine.
+       for i := range ch {
+               found(i.importPath, i.err)
+       }
+}
+
+type item struct {
+       importPath string
+       err        error // (optional)
+}
+
+// We use a process-wide counting semaphore to limit
+// the number of parallel calls to ReadDir.
+var ioLimit = make(chan bool, 20)
+
+func allPackages(ctxt *build.Context, root string, ch chan<- item) {
+       root = filepath.Clean(root) + string(os.PathSeparator)
+
+       var wg sync.WaitGroup
+
+       var walkDir func(dir string)
+       walkDir = func(dir string) {
+               // Avoid .foo, _foo, and testdata directory trees.
+               base := filepath.Base(dir)
+               if base == "" || base[0] == '.' || base[0] == '_' || base == "testdata" {
+                       return
+               }
+
+               pkg := filepath.ToSlash(strings.TrimPrefix(dir, root))
+
+               // Prune search if we encounter any of these import paths.
+               switch pkg {
+               case "builtin":
+                       return
+               }
+
+               ioLimit <- true
+               files, err := ReadDir(ctxt, dir)
+               <-ioLimit
+               if pkg != "" || err != nil {
+                       ch <- item{pkg, err}
+               }
+               for _, fi := range files {
+                       fi := fi
+                       if fi.IsDir() {
+                               wg.Add(1)
+                               go func() {
+                                       walkDir(filepath.Join(dir, fi.Name()))
+                                       wg.Done()
+                               }()
+                       }
+               }
+       }
+
+       walkDir(root)
+       wg.Wait()
+}
+
+// ExpandPatterns returns the set of packages matched by patterns,
+// which may have the following forms:
+//
+//             golang.org/x/tools/cmd/guru     # a single package
+//             golang.org/x/tools/...          # all packages beneath dir
+//             ...                             # the entire workspace.
+//
+// Order is significant: a pattern preceded by '-' removes matching
+// packages from the set.  For example, these patterns match all encoding
+// packages except encoding/xml:
+//
+//     encoding/... -encoding/xml
+//
+// A trailing slash in a pattern is ignored.  (Path components of Go
+// package names are separated by slash, not the platform's path separator.)
+//
+func ExpandPatterns(ctxt *build.Context, patterns []string) map[string]bool {
+       // TODO(adonovan): support other features of 'go list':
+       // - "std"/"cmd"/"all" meta-packages
+       // - "..." not at the end of a pattern
+       // - relative patterns using "./" or "../" prefix
+
+       pkgs := make(map[string]bool)
+       doPkg := func(pkg string, neg bool) {
+               if neg {
+                       delete(pkgs, pkg)
+               } else {
+                       pkgs[pkg] = true
+               }
+       }
+
+       // Scan entire workspace if wildcards are present.
+       // TODO(adonovan): opt: scan only the necessary subtrees of the workspace.
+       var all []string
+       for _, arg := range patterns {
+               if strings.HasSuffix(arg, "...") {
+                       all = AllPackages(ctxt)
+                       break
+               }
+       }
+
+       for _, arg := range patterns {
+               if arg == "" {
+                       continue
+               }
+
+               neg := arg[0] == '-'
+               if neg {
+                       arg = arg[1:]
+               }
+
+               if arg == "..." {
+                       // ... matches all packages
+                       for _, pkg := range all {
+                               doPkg(pkg, neg)
+                       }
+               } else if dir := strings.TrimSuffix(arg, "/..."); dir != arg {
+                       // dir/... matches all packages beneath dir
+                       for _, pkg := range all {
+                               if strings.HasPrefix(pkg, dir) &&
+                                       (len(pkg) == len(dir) || pkg[len(dir)] == '/') {
+                                       doPkg(pkg, neg)
+                               }
+                       }
+               } else {
+                       // single package
+                       doPkg(strings.TrimSuffix(arg, "/"), neg)
+               }
+       }
+
+       return pkgs
+}