go.tools/cmd/godex: better argument handling

1) Split a path.name argument at the last '.' that
   is not part of the path.

2) Try various importers always in the same order
   for consistent results (use lists instead of maps).

LGTM=adonovan
R=adonovan
CC=golang-codereviews
https://golang.org/cl/80790043
This commit is contained in:
Robert Griesemer 2014-03-26 09:54:20 -07:00
parent 8648e1a481
commit 03478d3d3e
1 changed files with 38 additions and 40 deletions

View File

@ -9,21 +9,21 @@ import (
"flag" "flag"
"fmt" "fmt"
"os" "os"
"path/filepath"
"strings" "strings"
"code.google.com/p/go.tools/go/types" "code.google.com/p/go.tools/go/types"
) )
// BUG(gri) cannot specify package paths with dots (code.google.com/p/go.tools/cmd/ssadump)
var ( var (
source = flag.String("s", "", "only consider packages from this source") source = flag.String("s", "", "only consider packages from this source")
verbose = flag.Bool("v", false, "verbose mode") verbose = flag.Bool("v", false, "verbose mode")
) )
var ( var (
sources []string // sources of export data corresponding to importers
importers []types.Importer // importers for corresponding sources
importFailed = errors.New("import failed") importFailed = errors.New("import failed")
importers = make(map[string]types.Importer)
packages = make(map[string]*types.Package) packages = make(map[string]*types.Package)
) )
@ -48,29 +48,16 @@ func main() {
imp := tryImport imp := tryImport
if *source != "" { if *source != "" {
imp = importers[*source] imp = lookup(*source)
if imp == nil { if imp == nil {
report("source must be one of: " + importersList()) report("source (-s argument) must be one of: " + strings.Join(sources, ", "))
} }
} }
for _, arg := range flag.Args() { for _, arg := range flag.Args() {
path, name := splitPathIdent(arg)
if *verbose { if *verbose {
fmt.Fprintf(os.Stderr, "(processing %s)\n", arg) fmt.Fprintf(os.Stderr, "(processing %q: path = %q, name = %s)\n", arg, path, name)
}
// determine import path, object name
var path, name string
elems := strings.Split(arg, ".")
switch len(elems) {
case 2:
name = elems[1]
fallthrough
case 1:
path = elems[0]
default:
fmt.Fprintf(os.Stderr, "ignoring %q: invalid path or (qualified) identifier\n", arg)
continue
} }
// import package // import package
@ -81,7 +68,7 @@ func main() {
} }
// filter objects if needed // filter objects if needed
filter := exportFilter filter := types.Object.Exported
if name != "" { if name != "" {
f := filter f := filter
filter = func(obj types.Object) bool { filter = func(obj types.Object) bool {
@ -109,9 +96,9 @@ func protect(imp types.Importer) types.Importer {
} }
func tryImport(packages map[string]*types.Package, path string) (pkg *types.Package, err error) { func tryImport(packages map[string]*types.Package, path string) (pkg *types.Package, err error) {
for source, imp := range importers { for i, imp := range importers {
if *verbose { if *verbose {
fmt.Fprintf(os.Stderr, "(trying as %s)\n", source) fmt.Fprintf(os.Stderr, "(trying source: %s)\n", sources[i])
} }
pkg, err = imp(packages, path) pkg, err = imp(packages, path)
if err == nil { if err == nil {
@ -121,25 +108,36 @@ func tryImport(packages map[string]*types.Package, path string) (pkg *types.Pack
return return
} }
func register(source string, imp types.Importer) { // splitPathIdent splits a path.name argument into its components.
if _, ok := importers[source]; ok { // All but the last path element may contain dots.
panic(source + " importer already registered") // TODO(gri) document this also in doc.go.
func splitPathIdent(arg string) (path, name string) {
const sep = string(filepath.Separator)
if i := strings.LastIndex(arg, "."); i >= 0 {
if j := strings.LastIndex(arg, sep); j < i {
// '.' is not part of path
path = arg[:i]
name = arg[i+1:]
return
} }
importers[source] = imp }
path = arg
return
} }
func importersList() string { func register(src string, imp types.Importer) {
var s string if lookup(src) != nil {
for n := range importers { panic(src + " importer already registered")
if len(s) == 0 {
s = n
} else {
s = s + ", " + n
} }
} sources = append(sources, src)
return s importers = append(importers, imp)
} }
func exportFilter(obj types.Object) bool { func lookup(src string) types.Importer {
return obj.Exported() for i, s := range sources {
if s == src {
return importers[i]
}
}
return nil
} }