go/buildutil: TagsFlag provides a flag.Value for setting build.Context.BuildTags from -tags flag.

Add -tags flag to oracle, ssadump, callgraph, gomvpkg, gorename, eg.

Change-Id: I4a818501b2331c4ea589caca37a3ad9d381dc8af
Reviewed-on: https://go-review.googlesource.com/9172
Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
Alan Donovan 2015-04-21 14:00:20 -04:00
parent b1aed1a596
commit ee9a07d373
8 changed files with 130 additions and 3 deletions

View File

@ -30,6 +30,7 @@ import (
"runtime" "runtime"
"text/template" "text/template"
"golang.org/x/tools/go/buildutil"
"golang.org/x/tools/go/callgraph" "golang.org/x/tools/go/callgraph"
"golang.org/x/tools/go/callgraph/cha" "golang.org/x/tools/go/callgraph/cha"
"golang.org/x/tools/go/callgraph/rta" "golang.org/x/tools/go/callgraph/rta"
@ -50,6 +51,10 @@ var formatFlag = flag.String("format",
"{{.Caller}}\t--{{.Dynamic}}-{{.Line}}:{{.Column}}-->\t{{.Callee}}", "{{.Caller}}\t--{{.Dynamic}}-{{.Line}}:{{.Column}}-->\t{{.Callee}}",
"A template expression specifying how to format an edge") "A template expression specifying how to format an edge")
func init() {
flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
}
const Usage = `callgraph: display the the call graph of a Go program. const Usage = `callgraph: display the the call graph of a Go program.
Usage: Usage:

View File

@ -6,6 +6,7 @@ package main // import "golang.org/x/tools/cmd/eg"
import ( import (
"flag" "flag"
"fmt" "fmt"
"go/build"
"go/parser" "go/parser"
"go/printer" "go/printer"
"go/token" "go/token"
@ -13,6 +14,7 @@ import (
"os/exec" "os/exec"
"strings" "strings"
"golang.org/x/tools/go/buildutil"
"golang.org/x/tools/go/loader" "golang.org/x/tools/go/loader"
"golang.org/x/tools/refactor/eg" "golang.org/x/tools/refactor/eg"
) )
@ -26,6 +28,10 @@ var (
verboseFlag = flag.Bool("v", false, "show verbose matcher diagnostics") verboseFlag = flag.Bool("v", false, "show verbose matcher diagnostics")
) )
func init() {
flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
}
const usage = `eg: an example-based refactoring tool. const usage = `eg: an example-based refactoring tool.
Usage: eg -t template.go [-w] [-transitive] <args>... Usage: eg -t template.go [-w] [-transitive] <args>...

View File

@ -12,6 +12,7 @@ import (
"go/build" "go/build"
"os" "os"
"golang.org/x/tools/go/buildutil"
"golang.org/x/tools/refactor/rename" "golang.org/x/tools/refactor/rename"
) )
@ -22,6 +23,10 @@ var (
helpFlag = flag.Bool("help", false, "show usage message") helpFlag = flag.Bool("help", false, "show usage message")
) )
func init() {
flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
}
const Usage = `gomvpkg: moves a package, updating import declarations const Usage = `gomvpkg: moves a package, updating import declarations
Usage: Usage:

View File

@ -14,6 +14,7 @@ import (
"os" "os"
"runtime" "runtime"
"golang.org/x/tools/go/buildutil"
"golang.org/x/tools/refactor/rename" "golang.org/x/tools/refactor/rename"
) )
@ -25,6 +26,7 @@ var (
) )
func init() { func init() {
flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
flag.BoolVar(&rename.Force, "force", false, "proceed, even if conflicts were reported") flag.BoolVar(&rename.Force, "force", false, "proceed, even if conflicts were reported")
flag.BoolVar(&rename.DryRun, "dryrun", false, "show the change, but do not apply it") flag.BoolVar(&rename.DryRun, "dryrun", false, "show the change, but do not apply it")
flag.BoolVar(&rename.Verbose, "v", false, "print verbose information") flag.BoolVar(&rename.Verbose, "v", false, "print verbose information")

View File

@ -23,6 +23,7 @@ import (
"runtime" "runtime"
"runtime/pprof" "runtime/pprof"
"golang.org/x/tools/go/buildutil"
"golang.org/x/tools/go/loader" "golang.org/x/tools/go/loader"
"golang.org/x/tools/oracle" "golang.org/x/tools/oracle"
) )
@ -38,6 +39,10 @@ var formatFlag = flag.String("format", "plain", "Output format. One of {plain,j
var reflectFlag = flag.Bool("reflect", false, "Analyze reflection soundly (slow).") var reflectFlag = flag.Bool("reflect", false, "Analyze reflection soundly (slow).")
func init() {
flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
}
const useHelp = "Run 'oracle -help' for more information.\n" const useHelp = "Run 'oracle -help' for more information.\n"
const helpMessage = `Go source code oracle. const helpMessage = `Go source code oracle.

View File

@ -13,6 +13,7 @@ import (
"runtime" "runtime"
"runtime/pprof" "runtime/pprof"
"golang.org/x/tools/go/buildutil"
"golang.org/x/tools/go/loader" "golang.org/x/tools/go/loader"
"golang.org/x/tools/go/ssa" "golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/interp" "golang.org/x/tools/go/ssa/interp"
@ -39,7 +40,7 @@ Usage: ssadump [<flag> ...] <args> ...
Use -help flag to display options. Use -help flag to display options.
Examples: Examples:
% ssadump -build=FP -importbin hello.go # quickly dump SSA form of a single package % ssadump -build=F hello.go # dump SSA form of a single package
% ssadump -run -interp=T hello.go # interpret a program, with tracing % ssadump -run -interp=T hello.go # interpret a program, with tracing
% ssadump -run -test unicode -- -test.v # interpret the unicode package's tests, verbosely % ssadump -run -test unicode -- -test.v # interpret the unicode package's tests, verbosely
` + loader.FromArgsUsage + ` + loader.FromArgsUsage +
@ -53,6 +54,8 @@ if set, it runs the tests of each package.
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
func init() { func init() {
flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
// If $GOMAXPROCS isn't set, use the full capacity of the machine. // If $GOMAXPROCS isn't set, use the full capacity of the machine.
// For small machines, use at least 4 threads. // For small machines, use at least 4 threads.
if os.Getenv("GOMAXPROCS") == "" { if os.Getenv("GOMAXPROCS") == "" {
@ -76,8 +79,8 @@ func doMain() error {
args := flag.Args() args := flag.Args()
conf := loader.Config{Build: &build.Default} conf := loader.Config{Build: &build.Default}
// TODO(adonovan): make go/types choose its default Sizes from
// build.Default or a specified *build.Context. // Choose types.Sizes from conf.Build.
var wordSize int64 = 8 var wordSize int64 = 8
switch conf.Build.GOARCH { switch conf.Build.GOARCH {
case "386", "arm": case "386", "arm":

73
go/buildutil/tags.go Normal file
View File

@ -0,0 +1,73 @@
package buildutil
// This logic was copied from stringsFlag from $GOROOT/src/cmd/go/build.go.
import "fmt"
const TagsFlagDoc = `'tag list'\ta list of build tags to consider satisfied during the build.
For more information about build tags, see the description of
build constraints in the documentation for the go/build package`
// TagsFlag is an implementation of the flag.Value interface that parses
// a flag value in the same manner as go build's -tags flag and
// populates a []string slice.
//
// See $GOROOT/src/go/build/doc.go for description of build tags.
// See $GOROOT/src/cmd/go/doc.go for description of 'go build -tags' flag.
//
// Example:
// flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsDoc)
type TagsFlag []string
func (v *TagsFlag) Set(s string) error {
var err error
*v, err = splitQuotedFields(s)
if *v == nil {
*v = []string{}
}
return err
}
func splitQuotedFields(s string) ([]string, error) {
// Split fields allowing '' or "" around elements.
// Quotes further inside the string do not count.
var f []string
for len(s) > 0 {
for len(s) > 0 && isSpaceByte(s[0]) {
s = s[1:]
}
if len(s) == 0 {
break
}
// Accepted quoted string. No unescaping inside.
if s[0] == '"' || s[0] == '\'' {
quote := s[0]
s = s[1:]
i := 0
for i < len(s) && s[i] != quote {
i++
}
if i >= len(s) {
return nil, fmt.Errorf("unterminated %c string", quote)
}
f = append(f, s[:i])
s = s[i+1:]
continue
}
i := 0
for i < len(s) && !isSpaceByte(s[i]) {
i++
}
f = append(f, s[:i])
s = s[i:]
}
return f, nil
}
func (v *TagsFlag) String() string {
return "<tagsFlag>"
}
func isSpaceByte(c byte) bool {
return c == ' ' || c == '\t' || c == '\n' || c == '\r'
}

28
go/buildutil/tags_test.go Normal file
View File

@ -0,0 +1,28 @@
package buildutil_test
import (
"flag"
"go/build"
"reflect"
"testing"
"golang.org/x/tools/go/buildutil"
)
func TestTags(t *testing.T) {
f := flag.NewFlagSet("TestTags", flag.PanicOnError)
var ctxt build.Context
f.Var((*buildutil.TagsFlag)(&ctxt.BuildTags), "tags", buildutil.TagsFlagDoc)
f.Parse([]string{"-tags", ` 'one'"two" 'three "four"'`, "rest"})
// BuildTags
want := []string{"one", "two", "three \"four\""}
if !reflect.DeepEqual(ctxt.BuildTags, want) {
t.Errorf("BuildTags = %q, want %q", ctxt.BuildTags, want)
}
// Args()
if want := []string{"rest"}; !reflect.DeepEqual(f.Args(), want) {
t.Errorf("f.Args() = %q, want %q", f.Args(), want)
}
}