Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / go / packages / external.go
1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // This file enables an external tool to intercept package requests.
6 // If the tool is present then its results are used in preference to
7 // the go list command.
8
9 package packages
10
11 import (
12         "bytes"
13         "encoding/json"
14         "fmt"
15         "os"
16         "os/exec"
17         "strings"
18 )
19
20 // The Driver Protocol
21 //
22 // The driver, given the inputs to a call to Load, returns metadata about the packages specified.
23 // This allows for different build systems to support go/packages by telling go/packages how the
24 // packages' source is organized.
25 // The driver is a binary, either specified by the GOPACKAGESDRIVER environment variable or in
26 // the path as gopackagesdriver. It's given the inputs to load in its argv. See the package
27 // documentation in doc.go for the full description of the patterns that need to be supported.
28 // A driver receives as a JSON-serialized driverRequest struct in standard input and will
29 // produce a JSON-serialized driverResponse (see definition in packages.go) in its standard output.
30
31 // driverRequest is used to provide the portion of Load's Config that is needed by a driver.
32 type driverRequest struct {
33         Mode LoadMode `json:"mode"`
34         // Env specifies the environment the underlying build system should be run in.
35         Env []string `json:"env"`
36         // BuildFlags are flags that should be passed to the underlying build system.
37         BuildFlags []string `json:"build_flags"`
38         // Tests specifies whether the patterns should also return test packages.
39         Tests bool `json:"tests"`
40         // Overlay maps file paths (relative to the driver's working directory) to the byte contents
41         // of overlay files.
42         Overlay map[string][]byte `json:"overlay"`
43 }
44
45 // findExternalDriver returns the file path of a tool that supplies
46 // the build system package structure, or "" if not found."
47 // If GOPACKAGESDRIVER is set in the environment findExternalTool returns its
48 // value, otherwise it searches for a binary named gopackagesdriver on the PATH.
49 func findExternalDriver(cfg *Config) driver {
50         const toolPrefix = "GOPACKAGESDRIVER="
51         tool := ""
52         for _, env := range cfg.Env {
53                 if val := strings.TrimPrefix(env, toolPrefix); val != env {
54                         tool = val
55                 }
56         }
57         if tool != "" && tool == "off" {
58                 return nil
59         }
60         if tool == "" {
61                 var err error
62                 tool, err = exec.LookPath("gopackagesdriver")
63                 if err != nil {
64                         return nil
65                 }
66         }
67         return func(cfg *Config, words ...string) (*driverResponse, error) {
68                 req, err := json.Marshal(driverRequest{
69                         Mode:       cfg.Mode,
70                         Env:        cfg.Env,
71                         BuildFlags: cfg.BuildFlags,
72                         Tests:      cfg.Tests,
73                         Overlay:    cfg.Overlay,
74                 })
75                 if err != nil {
76                         return nil, fmt.Errorf("failed to encode message to driver tool: %v", err)
77                 }
78
79                 buf := new(bytes.Buffer)
80                 stderr := new(bytes.Buffer)
81                 cmd := exec.CommandContext(cfg.Context, tool, words...)
82                 cmd.Dir = cfg.Dir
83                 cmd.Env = cfg.Env
84                 cmd.Stdin = bytes.NewReader(req)
85                 cmd.Stdout = buf
86                 cmd.Stderr = stderr
87
88                 if err := cmd.Run(); err != nil {
89                         return nil, fmt.Errorf("%v: %v: %s", tool, err, cmd.Stderr)
90                 }
91                 if len(stderr.Bytes()) != 0 && os.Getenv("GOPACKAGESPRINTDRIVERERRORS") != "" {
92                         fmt.Fprintf(os.Stderr, "%s stderr: <<%s>>\n", cmdDebugStr(cmd, words...), stderr)
93                 }
94
95                 var response driverResponse
96                 if err := json.Unmarshal(buf.Bytes(), &response); err != nil {
97                         return nil, err
98                 }
99                 return &response, nil
100         }
101 }