1
0
mirror of https://github.com/golang/go synced 2024-11-18 23:24:39 -07:00

go/package/gopackages: update gopackages to use the new tool library for its main function

Change-Id: I06f13024c021d14e4a759ca9ec24aa54f9d1b97f
Reviewed-on: https://go-review.googlesource.com/c/154558
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
Ian Cottrell 2018-12-17 13:21:31 -05:00
parent e063def13b
commit 7cb465e007

View File

@ -9,116 +9,73 @@
package main package main
import ( import (
"context"
"encoding/json" "encoding/json"
"flag" "flag"
"fmt" "fmt"
"go/types" "go/types"
"log"
"os" "os"
"runtime"
"runtime/pprof"
"runtime/trace"
"sort" "sort"
"strings" "strings"
"golang.org/x/tools/go/packages" "golang.org/x/tools/go/packages"
"golang.org/x/tools/go/types/typeutil" "golang.org/x/tools/go/types/typeutil"
"golang.org/x/tools/internal/tool"
) )
// flags func main() {
var ( tool.Main(context.Background(), &application{Mode: "imports"}, os.Args[1:])
depsFlag = flag.Bool("deps", false, "show dependencies too")
testFlag = flag.Bool("test", false, "include any tests implied by the patterns")
mode = flag.String("mode", "imports", "mode (one of files, imports, types, syntax, allsyntax)")
private = flag.Bool("private", false, "show non-exported declarations too")
printJSON = flag.Bool("json", false, "print package in JSON form")
cpuprofile = flag.String("cpuprofile", "", "write CPU profile to this file")
memprofile = flag.String("memprofile", "", "write memory profile to this file")
traceFlag = flag.String("trace", "", "write trace log to this file")
buildFlags stringListValue
)
func init() {
flag.Var(&buildFlags, "buildflag", "pass argument to underlying build system (may be repeated)")
} }
func usage() { type application struct {
fmt.Fprintln(os.Stderr, `Usage: gopackages [-deps] [-cgo] [-mode=...] [-private] package... // Embed the basic profiling flags supported by the tool package
tool.Profile
The gopackages command loads, parses, type-checks, Deps bool `flag:"deps" help:"show dependencies too"`
and prints one or more Go packages. Test bool `flag:"test" help:"include any tests implied by the patterns"`
Mode string `flag:"mode" help:"mode (one of files, imports, types, syntax, allsyntax)"`
Private bool `flag:"private" help:"show non-exported declarations too"`
PrintJSON bool `flag:"json" help:"print package in JSON form"`
BuildFlags stringListValue `flag:"buildflag" help:"pass argument to underlying build system (may be repeated)"`
}
// Name implements tool.Application returning the binary name.
func (app *application) Name() string { return "gopackages" }
// Usage implements tool.Application returning empty extra argument usage.
func (app *application) Usage() string { return "package..." }
// ShortHelp implements tool.Application returning the main binary help.
func (app *application) ShortHelp() string {
return "gopackages loads, parses, type-checks, and prints one or more Go packages."
}
// DetailedHelp implements tool.Application returning the main binary help.
func (app *application) DetailedHelp(f *flag.FlagSet) {
fmt.Fprint(f.Output(), `
Packages are specified using the notation of "go list", Packages are specified using the notation of "go list",
or other underlying build system. or other underlying build system.
Flags:`) Flags:
flag.PrintDefaults() `)
f.PrintDefaults()
} }
func main() { // Run takes the args after flag processing and performs the specified query.
log.SetPrefix("gopackages: ") func (app *application) Run(ctx context.Context, args ...string) error {
log.SetFlags(0) if len(args) == 0 {
flag.Usage = usage return tool.CommandLineErrorf("not enough arguments")
flag.Parse()
if len(flag.Args()) == 0 {
usage()
os.Exit(1)
}
if *cpuprofile != "" {
f, err := os.Create(*cpuprofile)
if err != nil {
log.Fatal(err)
}
if err := pprof.StartCPUProfile(f); err != nil {
log.Fatal(err)
}
// NB: profile won't be written in case of error.
defer pprof.StopCPUProfile()
}
if *traceFlag != "" {
f, err := os.Create(*traceFlag)
if err != nil {
log.Fatal(err)
}
if err := trace.Start(f); err != nil {
log.Fatal(err)
}
// NB: trace log won't be written in case of error.
defer func() {
trace.Stop()
log.Printf("To view the trace, run:\n$ go tool trace view %s", *traceFlag)
}()
}
if *memprofile != "" {
f, err := os.Create(*memprofile)
if err != nil {
log.Fatal(err)
}
// NB: memprofile won't be written in case of error.
defer func() {
runtime.GC() // get up-to-date statistics
if err := pprof.WriteHeapProfile(f); err != nil {
log.Fatalf("Writing memory profile: %v", err)
}
f.Close()
}()
} }
// Load, parse, and type-check the packages named on the command line. // Load, parse, and type-check the packages named on the command line.
cfg := &packages.Config{ cfg := &packages.Config{
Mode: packages.LoadSyntax, Mode: packages.LoadSyntax,
Tests: *testFlag, Tests: app.Test,
BuildFlags: buildFlags, BuildFlags: app.BuildFlags,
} }
// -mode flag // -mode flag
switch strings.ToLower(*mode) { switch strings.ToLower(app.Mode) {
case "files": case "files":
cfg.Mode = packages.LoadFiles cfg.Mode = packages.LoadFiles
case "imports": case "imports":
@ -130,16 +87,16 @@ func main() {
case "allsyntax": case "allsyntax":
cfg.Mode = packages.LoadAllSyntax cfg.Mode = packages.LoadAllSyntax
default: default:
log.Fatalf("invalid mode: %s", *mode) return tool.CommandLineErrorf("invalid mode: %s", app.Mode)
} }
lpkgs, err := packages.Load(cfg, flag.Args()...) lpkgs, err := packages.Load(cfg, args...)
if err != nil { if err != nil {
log.Fatal(err) return err
} }
// -deps: print dependencies too. // -deps: print dependencies too.
if *depsFlag { if app.Deps {
// We can't use packages.All because // We can't use packages.All because
// we need an ordered traversal. // we need an ordered traversal.
var all []*packages.Package // postorder var all []*packages.Package // postorder
@ -169,12 +126,13 @@ func main() {
} }
for _, lpkg := range lpkgs { for _, lpkg := range lpkgs {
print(lpkg) app.print(lpkg)
} }
return nil
} }
func print(lpkg *packages.Package) { func (app *application) print(lpkg *packages.Package) {
if *printJSON { if app.PrintJSON {
data, _ := json.MarshalIndent(lpkg, "", "\t") data, _ := json.MarshalIndent(lpkg, "", "\t")
os.Stdout.Write(data) os.Stdout.Write(data)
return return
@ -237,14 +195,14 @@ func print(lpkg *packages.Package) {
scope := lpkg.Types.Scope() scope := lpkg.Types.Scope()
for _, name := range scope.Names() { for _, name := range scope.Names() {
obj := scope.Lookup(name) obj := scope.Lookup(name)
if !obj.Exported() && !*private { if !obj.Exported() && !app.Private {
continue // skip unexported names continue // skip unexported names
} }
fmt.Printf("\t%s\n", types.ObjectString(obj, qual)) fmt.Printf("\t%s\n", types.ObjectString(obj, qual))
if _, ok := obj.(*types.TypeName); ok { if _, ok := obj.(*types.TypeName); ok {
for _, meth := range typeutil.IntuitiveMethodSet(obj.Type(), nil) { for _, meth := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {
if !meth.Obj().Exported() && !*private { if !meth.Obj().Exported() && !app.Private {
continue // skip unexported names continue // skip unexported names
} }
fmt.Printf("\t%s\n", types.SelectionString(meth, qual)) fmt.Printf("\t%s\n", types.SelectionString(meth, qual))