1
0
mirror of https://github.com/golang/go synced 2024-09-30 22:48:32 -06:00

go.tools/cmd/godex: fix prefix generation, filtering, formatting

Details:
- auto-generate prefixes for std lib (e.g., "godex big" works now)
- apply filtering to package-level objects only
- nicer formatting of single-entry const, var, or type declaration

TBR=adonovan
R=adonovan
CC=golang-codereviews
https://golang.org/cl/81360046
This commit is contained in:
Robert Griesemer 2014-03-28 12:21:51 -07:00
parent 069e8474de
commit 700390eaed
3 changed files with 75 additions and 59 deletions

View File

@ -76,12 +76,11 @@ func main() {
} }
// filter objects if needed // filter objects if needed
filter := types.Object.Exported var filter func(types.Object) bool
if name != "" { if name != "" {
f := filter
filter = func(obj types.Object) bool { filter = func(obj types.Object) bool {
// TODO(gri) perhaps use regular expression matching here? // TODO(gri) perhaps use regular expression matching here?
return f(obj) && obj.Name() == name return obj.Name() == name
} }
} }
@ -176,7 +175,8 @@ func lookup(src string) types.Importer {
func genPrefixes(out chan string) { func genPrefixes(out chan string) {
out <- "" // try no prefix out <- "" // try no prefix
platform := build.Default.GOOS + "_" + build.Default.GOARCH platform := build.Default.GOOS + "_" + build.Default.GOARCH
for _, dirname := range filepath.SplitList(build.Default.GOPATH) { dirnames := append([]string{build.Default.GOROOT}, filepath.SplitList(build.Default.GOPATH)...)
for _, dirname := range dirnames {
walkDir(filepath.Join(dirname, "pkg", platform), "", out) walkDir(filepath.Join(dirname, "pkg", platform), "", out)
} }
close(out) close(out)

View File

@ -12,8 +12,8 @@ import (
"code.google.com/p/go.tools/go/types" "code.google.com/p/go.tools/go/types"
) )
// TODO(gri) filter unexported fields of struct types?
// TODO(gri) use tabwriter for alignment? // TODO(gri) use tabwriter for alignment?
// TODO(gri) should print intuitive method sets
func print(w io.Writer, pkg *types.Package, filter func(types.Object) bool) { func print(w io.Writer, pkg *types.Package, filter func(types.Object) bool) {
var p printer var p printer
@ -62,28 +62,32 @@ func (p *printer) printPackage(pkg *types.Package, filter func(types.Object) boo
) )
scope := pkg.Scope() scope := pkg.Scope()
for _, name := range scope.Names() { for _, name := range scope.Names() {
if obj := scope.Lookup(name); filter(obj) { obj := scope.Lookup(name)
switch obj := obj.(type) { if obj.Exported() {
case *types.Const: // collect top-level exported and possibly filtered objects
consts = append(consts, obj) if filter == nil || filter(obj) {
case *types.TypeName: switch obj := obj.(type) {
// group into types with methods and types without case *types.Const:
// (for now this is only considering explicitly declared - not "inherited" methods) consts = append(consts, obj)
if named, _ := obj.Type().(*types.Named); named != nil && named.NumMethods() > 0 { case *types.TypeName:
typem = append(typem, named) // group into types with methods and types without
} else { // (for now this is only considering explicitly declared - not "inherited" methods)
typez = append(typez, obj) if named, _ := obj.Type().(*types.Named); named != nil && named.NumMethods() > 0 {
typem = append(typem, named)
} else {
typez = append(typez, obj)
}
case *types.Var:
vars = append(vars, obj)
case *types.Func:
funcs = append(funcs, obj)
case *types.Builtin:
// for unsafe.Sizeof, etc.
builtins = append(builtins, obj)
} }
case *types.Var:
vars = append(vars, obj)
case *types.Func:
funcs = append(funcs, obj)
case *types.Builtin:
// for unsafe.Sizeof, etc.
builtins = append(builtins, obj)
} }
} else { } else if filter == nil {
// type is filtered out but may contain visible methods // no filtering: collect top-level unexported types with methods
if obj, _ := obj.(*types.TypeName); obj != nil { if obj, _ := obj.(*types.TypeName); obj != nil {
// see case *types.TypeName above // see case *types.TypeName above
if named, _ := obj.Type().(*types.Named); named != nil && named.NumMethods() > 0 { if named, _ := obj.Type().(*types.Named); named != nil && named.NumMethods() > 0 {
@ -93,75 +97,88 @@ func (p *printer) printPackage(pkg *types.Package, filter func(types.Object) boo
} }
} }
p.printf("package %s // %q\n\n", pkg.Name(), pkg.Path()) p.printf("package %s // %q\n", pkg.Name(), pkg.Path())
if len(consts) > 0 { p.printDecl("const", len(consts), func() {
p.print("const (\n")
p.indent++
for _, obj := range consts { for _, obj := range consts {
p.printObj(obj) p.printObj(obj)
p.print("\n") p.print("\n")
} }
p.indent-- })
p.print(")\n\n")
}
if len(vars) > 0 { p.printDecl("var", len(vars), func() {
p.print("var (\n")
p.indent++
for _, obj := range vars { for _, obj := range vars {
p.printObj(obj) p.printObj(obj)
p.print("\n") p.print("\n")
} }
p.indent-- })
p.print(")\n\n")
}
if len(typez) > 0 { p.printDecl("type", len(typez), func() {
p.print("type (\n")
p.indent++
for _, obj := range typez { for _, obj := range typez {
p.printf("%s ", obj.Name()) p.printf("%s ", obj.Name())
p.writeType(p.pkg, obj.Type().Underlying()) p.writeType(p.pkg, obj.Type().Underlying())
p.print("\n") p.print("\n")
} }
p.indent-- })
p.print(")\n\n")
}
for _, typ := range typem { for _, typ := range typem {
hasEntries := false first := true
if obj := typ.Obj(); filter(obj) { if obj := typ.Obj(); obj.Exported() {
if first {
p.print("\n")
first = false
}
p.printf("type %s ", obj.Name()) p.printf("type %s ", obj.Name())
p.writeType(p.pkg, typ.Underlying()) p.writeType(p.pkg, typ.Underlying())
p.print("\n") p.print("\n")
hasEntries = true
} }
for i, n := 0, typ.NumMethods(); i < n; i++ { for i, n := 0, typ.NumMethods(); i < n; i++ {
if obj := typ.Method(i); filter(obj) { if obj := typ.Method(i); obj.Exported() {
if first {
p.print("\n")
first = false
}
p.printFunc(obj) p.printFunc(obj)
p.print("\n") p.print("\n")
hasEntries = true
} }
} }
if hasEntries { }
if len(funcs) > 0 {
p.print("\n")
for _, obj := range funcs {
p.printFunc(obj)
p.print("\n") p.print("\n")
} }
} }
for _, obj := range funcs {
p.printFunc(obj)
p.print("\n")
}
// TODO(gri) better handling of builtins (package unsafe only) // TODO(gri) better handling of builtins (package unsafe only)
for _, obj := range builtins { if len(builtins) > 0 {
p.printf("func %s() // builtin\n", obj.Name()) p.print("\n")
for _, obj := range builtins {
p.printf("func %s() // builtin\n", obj.Name())
}
} }
p.print("\n") p.print("\n")
} }
func (p *printer) printDecl(keyword string, n int, printGroup func()) {
switch n {
case 0:
// nothing to do
case 1:
p.printf("\n%s ", keyword)
printGroup()
default:
p.printf("\n%s (\n", keyword)
p.indent++
printGroup()
p.indent--
p.print(")\n")
}
}
func (p *printer) printObj(obj types.Object) { func (p *printer) printObj(obj types.Object) {
p.printf("%s", obj.Name()) p.printf("%s", obj.Name())
// don't write untyped types (for constants) // don't write untyped types (for constants)
@ -170,6 +187,7 @@ func (p *printer) printObj(obj types.Object) {
p.writeType(p.pkg, typ) p.writeType(p.pkg, typ)
} }
// write constant value // write constant value
// TODO(gri) use floating-point notation for exact floating-point numbers (fractions)
if obj, ok := obj.(*types.Const); ok { if obj, ok := obj.(*types.Const); ok {
p.printf(" = %s", obj.Val()) p.printf(" = %s", obj.Val())
} }

View File

@ -64,7 +64,6 @@ func (p *printer) writeTypeInternal(this *types.Package, typ types.Type, visited
p.writeTypeInternal(this, t.Elem(), visited) p.writeTypeInternal(this, t.Elem(), visited)
case *types.Struct: case *types.Struct:
// TODO(gri) filter fields?
n := t.NumFields() n := t.NumFields()
if n == 0 { if n == 0 {
p.print("struct{}") p.print("struct{}")
@ -110,7 +109,6 @@ func (p *printer) writeTypeInternal(this *types.Package, typ types.Type, visited
// m() interface{ T } // m() interface{ T }
// } // }
// //
// TODO(gri) filter methods?
n := t.NumMethods() n := t.NumMethods()
if n == 0 { if n == 0 {
p.print("interface{}") p.print("interface{}")