Skip to content

Commit a987ef7

Browse files
adonovangopherbot
authored andcommitted
go/packages: publish Driver{Request,Response}
and update the documentation. Fixes golang/go#64608 Change-Id: Icc65d1fb838d9fcb8e56e5f5bfcc175a83a4b706 Reviewed-on: https://go-review.googlesource.com/c/tools/+/557056 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Michael Matloob <[email protected]> Auto-Submit: Alan Donovan <[email protected]>
1 parent e1555a3 commit a987ef7

File tree

4 files changed

+94
-82
lines changed

4 files changed

+94
-82
lines changed

go/packages/doc.go

+25-15
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,10 @@ Load passes most patterns directly to the underlying build tool.
1515
The default build tool is the go command.
1616
Its supported patterns are described at
1717
https://pkg.go.dev/cmd/go#hdr-Package_lists_and_patterns.
18+
Other build systems may be supported by providing a "driver";
19+
see [The driver protocol].
1820
19-
Load may be used in Go projects that use alternative build systems, by
20-
installing an appropriate "driver" program for the build system and
21-
specifying its location in the GOPACKAGESDRIVER environment variable.
22-
For example,
23-
https://github.com/bazelbuild/rules_go/wiki/Editor-and-tool-integration
24-
explains how to use the driver for Bazel.
25-
The driver program is responsible for interpreting patterns in its
26-
preferred notation and reporting information about the packages that
27-
they identify.
28-
(See driverRequest and driverResponse types for the JSON
29-
schema used by the protocol.
30-
Though the protocol is supported, these types are currently unexported;
31-
see #64608 for a proposal to publish them.)
32-
33-
Regardless of driver, all patterns with the prefix "query=", where query is a
21+
All patterns with the prefix "query=", where query is a
3422
non-empty string of letters from [a-z], are reserved and may be
3523
interpreted as query operators.
3624
@@ -86,7 +74,29 @@ for details.
8674
Most tools should pass their command-line arguments (after any flags)
8775
uninterpreted to [Load], so that it can interpret them
8876
according to the conventions of the underlying build system.
77+
8978
See the Example function for typical usage.
79+
80+
# The driver protocol
81+
82+
[Load] may be used to load Go packages even in Go projects that use
83+
alternative build systems, by installing an appropriate "driver"
84+
program for the build system and specifying its location in the
85+
GOPACKAGESDRIVER environment variable.
86+
For example,
87+
https://github.com/bazelbuild/rules_go/wiki/Editor-and-tool-integration
88+
explains how to use the driver for Bazel.
89+
90+
The driver program is responsible for interpreting patterns in its
91+
preferred notation and reporting information about the packages that
92+
those patterns identify. Drivers must also support the special "file="
93+
and "pattern=" patterns described above.
94+
95+
The patterns are provided as positional command-line arguments. A
96+
JSON-encoded [DriverRequest] message providing additional information
97+
is written to the driver's standard input. The driver must write a
98+
JSON-encoded [DriverResponse] message to its standard output. (This
99+
message differs from the JSON schema produced by 'go list'.)
90100
*/
91101
package packages // import "golang.org/x/tools/go/packages"
92102

go/packages/external.go

+58-19
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

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-
95
package packages
106

7+
// This file defines the protocol that enables an external "driver"
8+
// tool to supply package metadata in place of 'go list'.
9+
1110
import (
1211
"bytes"
1312
"encoding/json"
@@ -17,31 +16,71 @@ import (
1716
"strings"
1817
)
1918

20-
// The Driver Protocol
19+
// DriverRequest defines the schema of a request for package metadata
20+
// from an external driver program. The JSON-encoded DriverRequest
21+
// message is provided to the driver program's standard input. The
22+
// query patterns are provided as command-line arguments.
2123
//
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 {
24+
// See the package documentation for an overview.
25+
type DriverRequest struct {
3326
Mode LoadMode `json:"mode"`
27+
3428
// Env specifies the environment the underlying build system should be run in.
3529
Env []string `json:"env"`
30+
3631
// BuildFlags are flags that should be passed to the underlying build system.
3732
BuildFlags []string `json:"build_flags"`
33+
3834
// Tests specifies whether the patterns should also return test packages.
3935
Tests bool `json:"tests"`
36+
4037
// Overlay maps file paths (relative to the driver's working directory) to the byte contents
4138
// of overlay files.
4239
Overlay map[string][]byte `json:"overlay"`
4340
}
4441

42+
// DriverResponse defines the schema of a response from an external
43+
// driver program, providing the results of a query for package
44+
// metadata. The driver program must write a JSON-encoded
45+
// DriverResponse message to its standard output.
46+
//
47+
// See the package documentation for an overview.
48+
type DriverResponse struct {
49+
// NotHandled is returned if the request can't be handled by the current
50+
// driver. If an external driver returns a response with NotHandled, the
51+
// rest of the DriverResponse is ignored, and go/packages will fallback
52+
// to the next driver. If go/packages is extended in the future to support
53+
// lists of multiple drivers, go/packages will fall back to the next driver.
54+
NotHandled bool
55+
56+
// Compiler and Arch are the arguments pass of types.SizesFor
57+
// to get a types.Sizes to use when type checking.
58+
Compiler string
59+
Arch string
60+
61+
// Roots is the set of package IDs that make up the root packages.
62+
// We have to encode this separately because when we encode a single package
63+
// we cannot know if it is one of the roots as that requires knowledge of the
64+
// graph it is part of.
65+
Roots []string `json:",omitempty"`
66+
67+
// Packages is the full set of packages in the graph.
68+
// The packages are not connected into a graph.
69+
// The Imports if populated will be stubs that only have their ID set.
70+
// Imports will be connected and then type and syntax information added in a
71+
// later pass (see refine).
72+
Packages []*Package
73+
74+
// GoVersion is the minor version number used by the driver
75+
// (e.g. the go command on the PATH) when selecting .go files.
76+
// Zero means unknown.
77+
GoVersion int
78+
}
79+
80+
// driver is the type for functions that query the build system for the
81+
// packages named by the patterns.
82+
type driver func(cfg *Config, patterns ...string) (*DriverResponse, error)
83+
4584
// findExternalDriver returns the file path of a tool that supplies
4685
// the build system package structure, or "" if not found."
4786
// If GOPACKAGESDRIVER is set in the environment findExternalTool returns its
@@ -64,8 +103,8 @@ func findExternalDriver(cfg *Config) driver {
64103
return nil
65104
}
66105
}
67-
return func(cfg *Config, words ...string) (*driverResponse, error) {
68-
req, err := json.Marshal(driverRequest{
106+
return func(cfg *Config, words ...string) (*DriverResponse, error) {
107+
req, err := json.Marshal(DriverRequest{
69108
Mode: cfg.Mode,
70109
Env: cfg.Env,
71110
BuildFlags: cfg.BuildFlags,
@@ -92,7 +131,7 @@ func findExternalDriver(cfg *Config) driver {
92131
fmt.Fprintf(os.Stderr, "%s stderr: <<%s>>\n", cmdDebugStr(cmd), stderr)
93132
}
94133

95-
var response driverResponse
134+
var response DriverResponse
96135
if err := json.Unmarshal(buf.Bytes(), &response); err != nil {
97136
return nil, err
98137
}

go/packages/golist.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,23 @@ type goTooOldError struct {
3535
error
3636
}
3737

38-
// responseDeduper wraps a driverResponse, deduplicating its contents.
38+
// responseDeduper wraps a DriverResponse, deduplicating its contents.
3939
type responseDeduper struct {
4040
seenRoots map[string]bool
4141
seenPackages map[string]*Package
42-
dr *driverResponse
42+
dr *DriverResponse
4343
}
4444

4545
func newDeduper() *responseDeduper {
4646
return &responseDeduper{
47-
dr: &driverResponse{},
47+
dr: &DriverResponse{},
4848
seenRoots: map[string]bool{},
4949
seenPackages: map[string]*Package{},
5050
}
5151
}
5252

53-
// addAll fills in r with a driverResponse.
54-
func (r *responseDeduper) addAll(dr *driverResponse) {
53+
// addAll fills in r with a DriverResponse.
54+
func (r *responseDeduper) addAll(dr *DriverResponse) {
5555
for _, pkg := range dr.Packages {
5656
r.addPackage(pkg)
5757
}
@@ -128,7 +128,7 @@ func (state *golistState) mustGetEnv() map[string]string {
128128
// goListDriver uses the go list command to interpret the patterns and produce
129129
// the build system package structure.
130130
// See driver for more details.
131-
func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) {
131+
func goListDriver(cfg *Config, patterns ...string) (*DriverResponse, error) {
132132
// Make sure that any asynchronous go commands are killed when we return.
133133
parentCtx := cfg.Context
134134
if parentCtx == nil {
@@ -266,7 +266,7 @@ func (state *golistState) runContainsQueries(response *responseDeduper, queries
266266

267267
// adhocPackage attempts to load or construct an ad-hoc package for a given
268268
// query, if the original call to the driver produced inadequate results.
269-
func (state *golistState) adhocPackage(pattern, query string) (*driverResponse, error) {
269+
func (state *golistState) adhocPackage(pattern, query string) (*DriverResponse, error) {
270270
response, err := state.createDriverResponse(query)
271271
if err != nil {
272272
return nil, err
@@ -357,7 +357,7 @@ func otherFiles(p *jsonPackage) [][]string {
357357

358358
// createDriverResponse uses the "go list" command to expand the pattern
359359
// words and return a response for the specified packages.
360-
func (state *golistState) createDriverResponse(words ...string) (*driverResponse, error) {
360+
func (state *golistState) createDriverResponse(words ...string) (*DriverResponse, error) {
361361
// go list uses the following identifiers in ImportPath and Imports:
362362
//
363363
// "p" -- importable package or main (command)
@@ -384,7 +384,7 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse
384384
pkgs := make(map[string]*Package)
385385
additionalErrors := make(map[string][]Error)
386386
// Decode the JSON and convert it to Package form.
387-
response := &driverResponse{
387+
response := &DriverResponse{
388388
GoVersion: goVersion,
389389
}
390390
for dec := json.NewDecoder(buf); dec.More(); {

go/packages/packages.go

+2-39
Original file line numberDiff line numberDiff line change
@@ -206,43 +206,6 @@ type Config struct {
206206
Overlay map[string][]byte
207207
}
208208

209-
// driver is the type for functions that query the build system for the
210-
// packages named by the patterns.
211-
type driver func(cfg *Config, patterns ...string) (*driverResponse, error)
212-
213-
// driverResponse contains the results for a driver query.
214-
type driverResponse struct {
215-
// NotHandled is returned if the request can't be handled by the current
216-
// driver. If an external driver returns a response with NotHandled, the
217-
// rest of the driverResponse is ignored, and go/packages will fallback
218-
// to the next driver. If go/packages is extended in the future to support
219-
// lists of multiple drivers, go/packages will fall back to the next driver.
220-
NotHandled bool
221-
222-
// Compiler and Arch are the arguments pass of types.SizesFor
223-
// to get a types.Sizes to use when type checking.
224-
Compiler string
225-
Arch string
226-
227-
// Roots is the set of package IDs that make up the root packages.
228-
// We have to encode this separately because when we encode a single package
229-
// we cannot know if it is one of the roots as that requires knowledge of the
230-
// graph it is part of.
231-
Roots []string `json:",omitempty"`
232-
233-
// Packages is the full set of packages in the graph.
234-
// The packages are not connected into a graph.
235-
// The Imports if populated will be stubs that only have their ID set.
236-
// Imports will be connected and then type and syntax information added in a
237-
// later pass (see refine).
238-
Packages []*Package
239-
240-
// GoVersion is the minor version number used by the driver
241-
// (e.g. the go command on the PATH) when selecting .go files.
242-
// Zero means unknown.
243-
GoVersion int
244-
}
245-
246209
// Load loads and returns the Go packages named by the given patterns.
247210
//
248211
// Config specifies loading options;
@@ -291,7 +254,7 @@ func Load(cfg *Config, patterns ...string) ([]*Package, error) {
291254
// no external driver, or the driver returns a response with NotHandled set,
292255
// defaultDriver will fall back to the go list driver.
293256
// The boolean result indicates that an external driver handled the request.
294-
func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, bool, error) {
257+
func defaultDriver(cfg *Config, patterns ...string) (*DriverResponse, bool, error) {
295258
if driver := findExternalDriver(cfg); driver != nil {
296259
response, err := driver(cfg, patterns...)
297260
if err != nil {
@@ -648,7 +611,7 @@ func newLoader(cfg *Config) *loader {
648611

649612
// refine connects the supplied packages into a graph and then adds type
650613
// and syntax information as requested by the LoadMode.
651-
func (ld *loader) refine(response *driverResponse) ([]*Package, error) {
614+
func (ld *loader) refine(response *DriverResponse) ([]*Package, error) {
652615
roots := response.Roots
653616
rootMap := make(map[string]int, len(roots))
654617
for i, root := range roots {

0 commit comments

Comments
 (0)