summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/tools/internal
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/tools/internal')
-rw-r--r--vendor/golang.org/x/tools/internal/gocommand/invoke.go96
-rw-r--r--vendor/golang.org/x/tools/internal/imports/fix.go28
-rw-r--r--vendor/golang.org/x/tools/internal/versions/types_go122.go2
3 files changed, 104 insertions, 22 deletions
diff --git a/vendor/golang.org/x/tools/internal/gocommand/invoke.go b/vendor/golang.org/x/tools/internal/gocommand/invoke.go
index eb7a8282f..af0ee6c61 100644
--- a/vendor/golang.org/x/tools/internal/gocommand/invoke.go
+++ b/vendor/golang.org/x/tools/internal/gocommand/invoke.go
@@ -8,12 +8,14 @@ package gocommand
import (
"bytes"
"context"
+ "encoding/json"
"errors"
"fmt"
"io"
"log"
"os"
"os/exec"
+ "path/filepath"
"reflect"
"regexp"
"runtime"
@@ -167,7 +169,9 @@ type Invocation struct {
// TODO(rfindley): remove, in favor of Args.
ModFile string
- // If Overlay is set, the go command is invoked with -overlay=Overlay.
+ // Overlay is the name of the JSON overlay file that describes
+ // unsaved editor buffers; see [WriteOverlays].
+ // If set, the go command is invoked with -overlay=Overlay.
// TODO(rfindley): remove, in favor of Args.
Overlay string
@@ -255,12 +259,15 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
waitDelay.Set(reflect.ValueOf(30 * time.Second))
}
- // On darwin the cwd gets resolved to the real path, which breaks anything that
- // expects the working directory to keep the original path, including the
+ // The cwd gets resolved to the real path. On Darwin, where
+ // /tmp is a symlink, this breaks anything that expects the
+ // working directory to keep the original path, including the
// go command when dealing with modules.
- // The Go stdlib has a special feature where if the cwd and the PWD are the
- // same node then it trusts the PWD, so by setting it in the env for the child
- // process we fix up all the paths returned by the go command.
+ //
+ // os.Getwd has a special feature where if the cwd and the PWD
+ // are the same node then it trusts the PWD, so by setting it
+ // in the env for the child process we fix up all the paths
+ // returned by the go command.
if !i.CleanEnv {
cmd.Env = os.Environ()
}
@@ -351,6 +358,7 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) {
}
}
+ startTime := time.Now()
err = cmd.Start()
if stdoutW != nil {
// The child process has inherited the pipe file,
@@ -377,7 +385,7 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) {
case err := <-resChan:
return err
case <-timer.C:
- HandleHangingGoCommand(cmd.Process)
+ HandleHangingGoCommand(startTime, cmd)
case <-ctx.Done():
}
} else {
@@ -411,7 +419,7 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) {
return <-resChan
}
-func HandleHangingGoCommand(proc *os.Process) {
+func HandleHangingGoCommand(start time.Time, cmd *exec.Cmd) {
switch runtime.GOOS {
case "linux", "darwin", "freebsd", "netbsd":
fmt.Fprintln(os.Stderr, `DETECTED A HANGING GO COMMAND
@@ -444,7 +452,7 @@ See golang/go#54461 for more details.`)
panic(fmt.Sprintf("running %s: %v", listFiles, err))
}
}
- panic(fmt.Sprintf("detected hanging go command (pid %d): see golang/go#54461 for more details", proc.Pid))
+ panic(fmt.Sprintf("detected hanging go command (golang/go#54461); waited %s\n\tcommand:%s\n\tpid:%d", time.Since(start), cmd, cmd.Process.Pid))
}
func cmdDebugStr(cmd *exec.Cmd) string {
@@ -468,3 +476,73 @@ func cmdDebugStr(cmd *exec.Cmd) string {
}
return fmt.Sprintf("GOROOT=%v GOPATH=%v GO111MODULE=%v GOPROXY=%v PWD=%v %v", env["GOROOT"], env["GOPATH"], env["GO111MODULE"], env["GOPROXY"], env["PWD"], strings.Join(args, " "))
}
+
+// WriteOverlays writes each value in the overlay (see the Overlay
+// field of go/packages.Config) to a temporary file and returns the name
+// of a JSON file describing the mapping that is suitable for the "go
+// list -overlay" flag.
+//
+// On success, the caller must call the cleanup function exactly once
+// when the files are no longer needed.
+func WriteOverlays(overlay map[string][]byte) (filename string, cleanup func(), err error) {
+ // Do nothing if there are no overlays in the config.
+ if len(overlay) == 0 {
+ return "", func() {}, nil
+ }
+
+ dir, err := os.MkdirTemp("", "gocommand-*")
+ if err != nil {
+ return "", nil, err
+ }
+
+ // The caller must clean up this directory,
+ // unless this function returns an error.
+ // (The cleanup operand of each return
+ // statement below is ignored.)
+ defer func() {
+ cleanup = func() {
+ os.RemoveAll(dir)
+ }
+ if err != nil {
+ cleanup()
+ cleanup = nil
+ }
+ }()
+
+ // Write each map entry to a temporary file.
+ overlays := make(map[string]string)
+ for k, v := range overlay {
+ // Use a unique basename for each file (001-foo.go),
+ // to avoid creating nested directories.
+ base := fmt.Sprintf("%d-%s.go", 1+len(overlays), filepath.Base(k))
+ filename := filepath.Join(dir, base)
+ err := os.WriteFile(filename, v, 0666)
+ if err != nil {
+ return "", nil, err
+ }
+ overlays[k] = filename
+ }
+
+ // Write the JSON overlay file that maps logical file names to temp files.
+ //
+ // OverlayJSON is the format overlay files are expected to be in.
+ // The Replace map maps from overlaid paths to replacement paths:
+ // the Go command will forward all reads trying to open
+ // each overlaid path to its replacement path, or consider the overlaid
+ // path not to exist if the replacement path is empty.
+ //
+ // From golang/go#39958.
+ type OverlayJSON struct {
+ Replace map[string]string `json:"replace,omitempty"`
+ }
+ b, err := json.Marshal(OverlayJSON{Replace: overlays})
+ if err != nil {
+ return "", nil, err
+ }
+ filename = filepath.Join(dir, "overlay.json")
+ if err := os.WriteFile(filename, b, 0666); err != nil {
+ return "", nil, err
+ }
+
+ return filename, nil, nil
+}
diff --git a/vendor/golang.org/x/tools/internal/imports/fix.go b/vendor/golang.org/x/tools/internal/imports/fix.go
index 93d49a6ef..4569313a0 100644
--- a/vendor/golang.org/x/tools/internal/imports/fix.go
+++ b/vendor/golang.org/x/tools/internal/imports/fix.go
@@ -104,7 +104,10 @@ type packageInfo struct {
// parseOtherFiles parses all the Go files in srcDir except filename, including
// test files if filename looks like a test.
-func parseOtherFiles(fset *token.FileSet, srcDir, filename string) []*ast.File {
+//
+// It returns an error only if ctx is cancelled. Files with parse errors are
+// ignored.
+func parseOtherFiles(ctx context.Context, fset *token.FileSet, srcDir, filename string) ([]*ast.File, error) {
// This could use go/packages but it doesn't buy much, and it fails
// with https://golang.org/issue/26296 in LoadFiles mode in some cases.
considerTests := strings.HasSuffix(filename, "_test.go")
@@ -112,11 +115,14 @@ func parseOtherFiles(fset *token.FileSet, srcDir, filename string) []*ast.File {
fileBase := filepath.Base(filename)
packageFileInfos, err := os.ReadDir(srcDir)
if err != nil {
- return nil
+ return nil, ctx.Err()
}
var files []*ast.File
for _, fi := range packageFileInfos {
+ if ctx.Err() != nil {
+ return nil, ctx.Err()
+ }
if fi.Name() == fileBase || !strings.HasSuffix(fi.Name(), ".go") {
continue
}
@@ -132,7 +138,7 @@ func parseOtherFiles(fset *token.FileSet, srcDir, filename string) []*ast.File {
files = append(files, f)
}
- return files
+ return files, ctx.Err()
}
// addGlobals puts the names of package vars into the provided map.
@@ -557,12 +563,7 @@ func (p *pass) addCandidate(imp *ImportInfo, pkg *packageInfo) {
// fixImports adds and removes imports from f so that all its references are
// satisfied and there are no unused imports.
-//
-// This is declared as a variable rather than a function so goimports can
-// easily be extended by adding a file with an init function.
-var fixImports = fixImportsDefault
-
-func fixImportsDefault(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv) error {
+func fixImports(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv) error {
fixes, err := getFixes(context.Background(), fset, f, filename, env)
if err != nil {
return err
@@ -592,7 +593,10 @@ func getFixes(ctx context.Context, fset *token.FileSet, f *ast.File, filename st
return fixes, nil
}
- otherFiles := parseOtherFiles(fset, srcDir, filename)
+ otherFiles, err := parseOtherFiles(ctx, fset, srcDir, filename)
+ if err != nil {
+ return nil, err
+ }
// Second pass: add information from other files in the same package,
// like their package vars and imports.
@@ -1192,7 +1196,7 @@ func addExternalCandidates(ctx context.Context, pass *pass, refs references, fil
if err != nil {
return err
}
- if err = resolver.scan(context.Background(), callback); err != nil {
+ if err = resolver.scan(ctx, callback); err != nil {
return err
}
@@ -1203,7 +1207,7 @@ func addExternalCandidates(ctx context.Context, pass *pass, refs references, fil
}
results := make(chan result, len(refs))
- ctx, cancel := context.WithCancel(context.TODO())
+ ctx, cancel := context.WithCancel(ctx)
var wg sync.WaitGroup
defer func() {
cancel()
diff --git a/vendor/golang.org/x/tools/internal/versions/types_go122.go b/vendor/golang.org/x/tools/internal/versions/types_go122.go
index e8180632a..aac5db62c 100644
--- a/vendor/golang.org/x/tools/internal/versions/types_go122.go
+++ b/vendor/golang.org/x/tools/internal/versions/types_go122.go
@@ -12,7 +12,7 @@ import (
"go/types"
)
-// FileVersions returns a file's Go version.
+// FileVersion returns a file's Go version.
// The reported version is an unknown Future version if a
// version cannot be determined.
func FileVersion(info *types.Info, file *ast.File) string {