.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.0 / go / buildutil / util.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.0/go/buildutil/util.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.0/go/buildutil/util.go
new file mode 100644 (file)
index 0000000..fc923d7
--- /dev/null
@@ -0,0 +1,212 @@
+// 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
+
+import (
+       "fmt"
+       "go/ast"
+       "go/build"
+       "go/parser"
+       "go/token"
+       "io"
+       "io/ioutil"
+       "os"
+       "path"
+       "path/filepath"
+       "strings"
+)
+
+// ParseFile behaves like parser.ParseFile,
+// but uses the build context's file system interface, if any.
+//
+// If file is not absolute (as defined by IsAbsPath), the (dir, file)
+// components are joined using JoinPath; dir must be absolute.
+//
+// The displayPath function, if provided, is used to transform the
+// filename that will be attached to the ASTs.
+//
+// TODO(adonovan): call this from go/loader.parseFiles when the tree thaws.
+//
+func ParseFile(fset *token.FileSet, ctxt *build.Context, displayPath func(string) string, dir string, file string, mode parser.Mode) (*ast.File, error) {
+       if !IsAbsPath(ctxt, file) {
+               file = JoinPath(ctxt, dir, file)
+       }
+       rd, err := OpenFile(ctxt, file)
+       if err != nil {
+               return nil, err
+       }
+       defer rd.Close() // ignore error
+       if displayPath != nil {
+               file = displayPath(file)
+       }
+       return parser.ParseFile(fset, file, rd, mode)
+}
+
+// ContainingPackage returns the package containing filename.
+//
+// If filename is not absolute, it is interpreted relative to working directory dir.
+// All I/O is via the build context's file system interface, if any.
+//
+// The '...Files []string' fields of the resulting build.Package are not
+// populated (build.FindOnly mode).
+//
+func ContainingPackage(ctxt *build.Context, dir, filename string) (*build.Package, error) {
+       if !IsAbsPath(ctxt, filename) {
+               filename = JoinPath(ctxt, dir, filename)
+       }
+
+       // We must not assume the file tree uses
+       // "/" always,
+       // `\` always,
+       // or os.PathSeparator (which varies by platform),
+       // but to make any progress, we are forced to assume that
+       // paths will not use `\` unless the PathSeparator
+       // is also `\`, thus we can rely on filepath.ToSlash for some sanity.
+
+       dirSlash := path.Dir(filepath.ToSlash(filename)) + "/"
+
+       // We assume that no source root (GOPATH[i] or GOROOT) contains any other.
+       for _, srcdir := range ctxt.SrcDirs() {
+               srcdirSlash := filepath.ToSlash(srcdir) + "/"
+               if importPath, ok := HasSubdir(ctxt, srcdirSlash, dirSlash); ok {
+                       return ctxt.Import(importPath, dir, build.FindOnly)
+               }
+       }
+
+       return nil, fmt.Errorf("can't find package containing %s", filename)
+}
+
+// -- Effective methods of file system interface -------------------------
+
+// (go/build.Context defines these as methods, but does not export them.)
+
+// hasSubdir calls ctxt.HasSubdir (if not nil) or else uses
+// the local file system to answer the question.
+func HasSubdir(ctxt *build.Context, root, dir string) (rel string, ok bool) {
+       if f := ctxt.HasSubdir; f != nil {
+               return f(root, dir)
+       }
+
+       // Try using paths we received.
+       if rel, ok = hasSubdir(root, dir); ok {
+               return
+       }
+
+       // Try expanding symlinks and comparing
+       // expanded against unexpanded and
+       // expanded against expanded.
+       rootSym, _ := filepath.EvalSymlinks(root)
+       dirSym, _ := filepath.EvalSymlinks(dir)
+
+       if rel, ok = hasSubdir(rootSym, dir); ok {
+               return
+       }
+       if rel, ok = hasSubdir(root, dirSym); ok {
+               return
+       }
+       return hasSubdir(rootSym, dirSym)
+}
+
+func hasSubdir(root, dir string) (rel string, ok bool) {
+       const sep = string(filepath.Separator)
+       root = filepath.Clean(root)
+       if !strings.HasSuffix(root, sep) {
+               root += sep
+       }
+
+       dir = filepath.Clean(dir)
+       if !strings.HasPrefix(dir, root) {
+               return "", false
+       }
+
+       return filepath.ToSlash(dir[len(root):]), true
+}
+
+// FileExists returns true if the specified file exists,
+// using the build context's file system interface.
+func FileExists(ctxt *build.Context, path string) bool {
+       if ctxt.OpenFile != nil {
+               r, err := ctxt.OpenFile(path)
+               if err != nil {
+                       return false
+               }
+               r.Close() // ignore error
+               return true
+       }
+       _, err := os.Stat(path)
+       return err == nil
+}
+
+// OpenFile behaves like os.Open,
+// but uses the build context's file system interface, if any.
+func OpenFile(ctxt *build.Context, path string) (io.ReadCloser, error) {
+       if ctxt.OpenFile != nil {
+               return ctxt.OpenFile(path)
+       }
+       return os.Open(path)
+}
+
+// IsAbsPath behaves like filepath.IsAbs,
+// but uses the build context's file system interface, if any.
+func IsAbsPath(ctxt *build.Context, path string) bool {
+       if ctxt.IsAbsPath != nil {
+               return ctxt.IsAbsPath(path)
+       }
+       return filepath.IsAbs(path)
+}
+
+// JoinPath behaves like filepath.Join,
+// but uses the build context's file system interface, if any.
+func JoinPath(ctxt *build.Context, path ...string) string {
+       if ctxt.JoinPath != nil {
+               return ctxt.JoinPath(path...)
+       }
+       return filepath.Join(path...)
+}
+
+// IsDir behaves like os.Stat plus IsDir,
+// but uses the build context's file system interface, if any.
+func IsDir(ctxt *build.Context, path string) bool {
+       if ctxt.IsDir != nil {
+               return ctxt.IsDir(path)
+       }
+       fi, err := os.Stat(path)
+       return err == nil && fi.IsDir()
+}
+
+// ReadDir behaves like ioutil.ReadDir,
+// but uses the build context's file system interface, if any.
+func ReadDir(ctxt *build.Context, path string) ([]os.FileInfo, error) {
+       if ctxt.ReadDir != nil {
+               return ctxt.ReadDir(path)
+       }
+       return ioutil.ReadDir(path)
+}
+
+// SplitPathList behaves like filepath.SplitList,
+// but uses the build context's file system interface, if any.
+func SplitPathList(ctxt *build.Context, s string) []string {
+       if ctxt.SplitPathList != nil {
+               return ctxt.SplitPathList(s)
+       }
+       return filepath.SplitList(s)
+}
+
+// sameFile returns true if x and y have the same basename and denote
+// the same file.
+//
+func sameFile(x, y string) bool {
+       if path.Clean(x) == path.Clean(y) {
+               return true
+       }
+       if filepath.Base(x) == filepath.Base(y) { // (optimisation)
+               if xi, err := os.Stat(x); err == nil {
+                       if yi, err := os.Stat(y); err == nil {
+                               return os.SameFile(xi, yi)
+                       }
+               }
+       }
+       return false
+}