mirror of
https://github.com/golang/go
synced 2024-11-18 20:04:52 -07:00
go/packages: use "=" instead of ":" for special queries
This change updates the language accepted through the arguments to packages.Load to make it more consistent. There are now two layers. A pattern containing an "=" is considered to be a special query, and the part of the pattern up to the first "=" is considered the query type. All other patterns are to be interpreted as the build system interprets it. For now two special queries exist. file= has the behavior that contains: did: finding packages containing the given file. The query type pattern= is used to pass through a pattern to be interpreted by the build system. pattern= is a type of escaping to allow passing through patterns that contain an "=" to be interpreted by the underlying buildsystem. To allow for new query types to be introduced, packages.Load will report an error if the qury type is not understood. We expect name= to be added in an upcoming change. "contains:" changes to "file=". A new Change-Id: I1b208d1c998c67d5556cdc872d7694273cedb7e4 Reviewed-on: https://go-review.googlesource.com/c/141681 Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
parent
5e66757b83
commit
13ebad898d
@ -15,9 +15,29 @@ The Load function takes as input a list of patterns and return a list of Package
|
||||
structs describing individual packages matched by those patterns.
|
||||
The LoadMode controls the amount of detail in the loaded packages.
|
||||
|
||||
The patterns are used as arguments to the underlying build tool,
|
||||
such as the go command or Bazel, and are interpreted according to
|
||||
that tool's conventions.
|
||||
Load passes most patterns directly to the underlying build tool,
|
||||
but all patterns with the prefix "query=", where query is a
|
||||
non-empty string of letters from [a-z], are reserved and may be
|
||||
interpreted as query operators.
|
||||
|
||||
Only two query operators are currently supported, "file" and "pattern".
|
||||
|
||||
The query "file=path/to/file.go" matches the package or packages enclosing
|
||||
the Go source file path/to/file.go. For example "file=~/go/src/fmt/print.go"
|
||||
might returns the packages "fmt" and "fmt [fmt.test]".
|
||||
|
||||
The query "pattern=string" causes "string" to be passed directly to
|
||||
the underlying build tool. In most cases this is unnecessary,
|
||||
but an application can use Load("pattern=" + x) as an escaping mechanism
|
||||
to ensure that x is not interpreted as a query operator if it contains '='.
|
||||
|
||||
A third query "name=identifier" will be added soon.
|
||||
It will match packages whose package declaration contains the specified identifier.
|
||||
For example, "name=rand" would match the packages "math/rand" and "crypto/rand",
|
||||
and "name=main" would match all executables.
|
||||
|
||||
All other query operators are reserved for future use and currently
|
||||
cause Load to report an error.
|
||||
|
||||
The Package struct provides basic information about the package, including
|
||||
|
||||
|
@ -28,6 +28,38 @@ func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) {
|
||||
// Determine files requested in contains patterns
|
||||
var containFiles []string
|
||||
restPatterns := make([]string, 0, len(patterns))
|
||||
// Extract file= and other [querytype]= patterns. Report an error if querytype
|
||||
// doesn't exist.
|
||||
extractQueries:
|
||||
for _, pattern := range patterns {
|
||||
eqidx := strings.Index(pattern, "=")
|
||||
if eqidx < 0 {
|
||||
restPatterns = append(restPatterns, pattern)
|
||||
} else {
|
||||
query, value := pattern[:eqidx], pattern[eqidx+len("="):]
|
||||
switch query {
|
||||
case "file":
|
||||
containFiles = append(containFiles, value)
|
||||
case "pattern":
|
||||
restPatterns = append(containFiles, value)
|
||||
case "": // not a reserved query
|
||||
restPatterns = append(restPatterns, pattern)
|
||||
default:
|
||||
for _, rune := range query {
|
||||
if rune < 'a' || rune > 'z' { // not a reserved query
|
||||
restPatterns = append(restPatterns, pattern)
|
||||
continue extractQueries
|
||||
}
|
||||
}
|
||||
// Reject all other patterns containing "="
|
||||
return nil, fmt.Errorf("invalid query type %q in query pattern %q", query, pattern)
|
||||
}
|
||||
}
|
||||
}
|
||||
patterns = restPatterns
|
||||
// Look for the deprecated contains: syntax.
|
||||
// TODO(matloob): delete this around mid-October 2018.
|
||||
restPatterns = restPatterns[:0]
|
||||
for _, pattern := range patterns {
|
||||
if strings.HasPrefix(pattern, "contains:") {
|
||||
containFile := strings.TrimPrefix(pattern, "contains:")
|
||||
|
@ -1013,7 +1013,7 @@ func TestAbsoluteFilenames(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestContains(t *testing.T) {
|
||||
func TestFile(t *testing.T) {
|
||||
tmp, cleanup := makeTree(t, map[string]string{
|
||||
"src/a/a.go": `package a; import "b"`,
|
||||
"src/b/b.go": `package b; import "c"`,
|
||||
@ -1026,7 +1026,7 @@ func TestContains(t *testing.T) {
|
||||
Dir: tmp,
|
||||
Env: append(os.Environ(), "GOPATH="+tmp, "GO111MODULE=off"),
|
||||
}
|
||||
initial, err := packages.Load(cfg, "contains:src/b/b.go")
|
||||
initial, err := packages.Load(cfg, "file=src/b/b.go")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -1093,7 +1093,7 @@ func TestContains_FallbackSticks(t *testing.T) {
|
||||
Dir: tmp,
|
||||
Env: append(os.Environ(), "GOPATH="+tmp, "GO111MODULE=off"),
|
||||
}
|
||||
initial, err := packages.Load(cfg, "a", "contains:src/b/b.go")
|
||||
initial, err := packages.Load(cfg, "a", "file=src/b/b.go")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -1261,6 +1261,46 @@ func TestJSON(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRejectInvalidQueries(t *testing.T) {
|
||||
queries := []string{"=", "key=", "key=value", "file/a/b=c/..."}
|
||||
cfg := &packages.Config{
|
||||
Mode: packages.LoadImports,
|
||||
Env: append(os.Environ(), "GO111MODULE=off"),
|
||||
}
|
||||
for _, q := range queries {
|
||||
if _, err := packages.Load(cfg, q); err == nil {
|
||||
t.Errorf("packages.Load(%q) succeeded. Expected \"invalid query type\" error", q)
|
||||
} else if !strings.Contains(err.Error(), "invalid query type") {
|
||||
t.Errorf("packages.Load(%q): got error %v, want \"invalid query type\" error", q, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPatternPassthrough(t *testing.T) {
|
||||
tmp, cleanup := makeTree(t, map[string]string{
|
||||
"src/a/a.go": `package a;`,
|
||||
})
|
||||
defer cleanup()
|
||||
|
||||
cfg := &packages.Config{
|
||||
Mode: packages.LoadImports,
|
||||
Env: append(os.Environ(), "GOPATH="+tmp, "GO111MODULE=off"),
|
||||
}
|
||||
initial, err := packages.Load(cfg, "pattern=a")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
graph, _ := importGraph(initial)
|
||||
wantGraph := `
|
||||
* a
|
||||
`[1:]
|
||||
if graph != wantGraph {
|
||||
t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestConfigDefaultEnv(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
// TODO(jayconrod): write an equivalent batch script for windows.
|
||||
|
Loading…
Reference in New Issue
Block a user