1
0
mirror of https://github.com/golang/go synced 2024-10-01 05:18:33 -06:00

go/buildutil: add ExpandPatterns utility

This will be used by the guru command's -scope argument.

+ test

Change-Id: I5bf38b544809e4518e2c22a73ec3349a5d2c09fc
Reviewed-on: https://go-review.googlesource.com/19746
Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
Alan Donovan 2016-02-20 19:26:39 -05:00
parent 54fa7477e2
commit ba766134cc
2 changed files with 110 additions and 0 deletions

View File

@ -123,3 +123,73 @@ func allPackages(ctxt *build.Context, root string, ch chan<- item) {
walkDir(root) walkDir(root)
wg.Wait() wg.Wait()
} }
// ExpandPatterns returns the set of packages matched by patterns,
// which may have the following forms:
//
// golang.org/x/tools/cmd/guru # a single package
// golang.org/x/tools/... # all packages beneath dir
// ... # the entire workspace.
//
// Order is significant: a pattern preceded by '-' removes matching
// packages from the set. For example, these patterns match all encoding
// packages except encoding/xml:
//
// encoding/... -encoding/xml
//
func ExpandPatterns(ctxt *build.Context, patterns []string) map[string]bool {
// TODO(adonovan): support other features of 'go list':
// - "std"/"cmd"/"all" meta-packages
// - "..." not at the end of a pattern
// - relative patterns using "./" or "../" prefix
pkgs := make(map[string]bool)
doPkg := func(pkg string, neg bool) {
if neg {
delete(pkgs, pkg)
} else {
pkgs[pkg] = true
}
}
// Scan entire workspace if wildcards are present.
// TODO(adonovan): opt: scan only the necessary subtrees of the workspace.
var all []string
for _, arg := range patterns {
if strings.HasSuffix(arg, "...") {
all = AllPackages(ctxt)
break
}
}
for _, arg := range patterns {
if arg == "" {
continue
}
neg := arg[0] == '-'
if neg {
arg = arg[1:]
}
if arg == "..." {
// ... matches all packages
for _, pkg := range all {
doPkg(pkg, neg)
}
} else if dir := strings.TrimSuffix(arg, "/..."); dir != arg {
// dir/... matches all packages beneath dir
for _, pkg := range all {
if strings.HasPrefix(pkg, dir) &&
(len(pkg) == len(dir) || pkg[len(dir)] == '/') {
doPkg(pkg, neg)
}
}
} else {
// single package
doPkg(arg, neg)
}
}
return pkgs
}

View File

@ -10,6 +10,8 @@ package buildutil_test
import ( import (
"go/build" "go/build"
"sort"
"strings"
"testing" "testing"
"golang.org/x/tools/go/buildutil" "golang.org/x/tools/go/buildutil"
@ -34,3 +36,41 @@ func TestAllPackages(t *testing.T) {
} }
} }
} }
func TestExpandPatterns(t *testing.T) {
tree := make(map[string]map[string]string)
for _, pkg := range []string{
"encoding",
"encoding/xml",
"encoding/hex",
"encoding/json",
"fmt",
} {
tree[pkg] = make(map[string]string)
}
ctxt := buildutil.FakeContext(tree)
for _, test := range []struct {
patterns string
want string
}{
{"", ""},
{"fmt", "fmt"},
{"nosuchpkg", "nosuchpkg"},
{"nosuchdir/...", ""},
{"...", "encoding encoding/hex encoding/json encoding/xml fmt"},
{"encoding/... -encoding/xml", "encoding encoding/hex encoding/json"},
{"... -encoding/...", "fmt"},
} {
var pkgs []string
for pkg := range buildutil.ExpandPatterns(ctxt, strings.Fields(test.patterns)) {
pkgs = append(pkgs, pkg)
}
sort.Strings(pkgs)
got := strings.Join(pkgs, " ")
if got != test.want {
t.Errorf("ExpandPatterns(%s) = %s, want %s",
test.patterns, got, test.want)
}
}
}