1
0
mirror of https://github.com/golang/go synced 2024-11-18 18:44:42 -07:00

go.tools/oracle: describe package: simplify to use only types.Package, not ssa.Package.

R=crawshaw
CC=golang-dev
https://golang.org/cl/13396050
This commit is contained in:
Alan Donovan 2013-09-10 14:19:11 -04:00
parent 0725e5a5b3
commit c18d759e6b
4 changed files with 78 additions and 96 deletions

View File

@ -703,8 +703,7 @@ func (r *describeTypeResult) toJSON(res *json.Result, fset *token.FileSet) {
func describePackage(o *oracle, path []ast.Node) (*describePackageResult, error) {
var description string
var pkg *ssa.Package
var importPath string
var pkg *types.Package
switch n := path[0].(type) {
case *ast.ImportSpec:
// Most ImportSpecs have no .Name Ident so we can't
@ -712,37 +711,26 @@ func describePackage(o *oracle, path []ast.Node) (*describePackageResult, error)
// We could use the types.Info.Implicits mechanism,
// but it's easier just to look it up by name.
description = "import of package " + n.Path.Value
importPath, _ = strconv.Unquote(n.Path.Value)
pkg = o.prog.ImportedPackage(importPath)
importPath, _ := strconv.Unquote(n.Path.Value)
pkg = o.prog.ImportedPackage(importPath).Object
case *ast.Ident:
obj := o.queryPkgInfo.ObjectOf(n).(*types.Package)
importPath = obj.Path()
pkg = o.queryPkgInfo.ObjectOf(n).(*types.Package)
if _, isDef := path[1].(*ast.File); isDef {
// e.g. package id
pkg = o.prog.Package(obj)
description = fmt.Sprintf("definition of package %q", importPath)
description = fmt.Sprintf("definition of package %q", pkg.Path())
} else {
// e.g. import id
// or id.F()
// TODO(gri): go/types internally creates a new
// Package object for each import, so the packages
// for 'package x' and 'import "x"' differ!
//
// Here, this should be an invariant, but is not:
// o.prog.ImportedPackage(obj.Path()).Pkg == obj
//
// So we must use the name of the non-canonical package
// to do another lookup.
pkg = o.prog.ImportedPackage(importPath)
// go/types internally creates a new Package
// object for each import, so the packages for
// 'package x' and 'import "x"' differ.
// Call Primary() to get the real thing.
pkg = pkg.Primary()
description = fmt.Sprintf("reference to package %q", importPath)
}
if importPath == "" {
// TODO(gri): fix.
return nil, o.errorf(n, "types.Package.Path() returned \"\"\n")
description = fmt.Sprintf("reference to package %q", pkg.Path())
}
default:
@ -751,45 +739,39 @@ func describePackage(o *oracle, path []ast.Node) (*describePackageResult, error)
}
var members []*describeMember
// NB: "unsafe" has no ssa.Package
// TODO(adonovan): simplify by using types.Packages not ssa.Packages.
// NB: "unsafe" has no types.Package
if pkg != nil {
// Compute set of exported package members in lexicographic order.
var names []string
for name := range pkg.Members {
if pkg.Object == o.queryPkgInfo.Pkg || ast.IsExported(name) {
names = append(names, name)
}
}
sort.Strings(names)
// Enumerate the accessible package members
// in lexicographic order.
for _, name := range pkg.Scope().Names() {
if pkg == o.queryPkgInfo.Pkg || ast.IsExported(name) {
mem := pkg.Scope().Lookup(name)
var methods []*types.Selection
if mem, ok := mem.(*types.TypeName); ok {
methods = accessibleMethods(mem.Type(), o.queryPkgInfo.Pkg)
}
members = append(members, &describeMember{
mem,
methods,
})
// Enumerate the package members.
for _, name := range names {
mem := pkg.Members[name]
var methods []*types.Selection
if mem, ok := mem.(*ssa.Type); ok {
methods = accessibleMethods(mem.Type(), o.queryPkgInfo.Pkg)
}
members = append(members, &describeMember{
mem,
methods,
})
}
}
return &describePackageResult{o.prog.Fset, path[0], description, importPath, members}, nil
return &describePackageResult{o.prog.Fset, path[0], description, pkg, members}, nil
}
type describePackageResult struct {
fset *token.FileSet
node ast.Node
description string
path string
pkg *types.Package
members []*describeMember // in lexicographic name order
}
type describeMember struct {
mem ssa.Member
obj types.Object
methods []*types.Selection // in types.MethodSet order
}
@ -799,33 +781,33 @@ func (r *describePackageResult) display(printf printfFunc) {
// Compute max width of name "column".
maxname := 0
for _, mem := range r.members {
if l := len(mem.mem.Name()); l > maxname {
if l := len(mem.obj.Name()); l > maxname {
maxname = l
}
}
for _, mem := range r.members {
printf(mem.mem, "\t%s", formatMember(mem.mem, maxname))
printf(mem.obj, "\t%s", formatMember(mem.obj, maxname))
for _, meth := range mem.methods {
printf(meth.Obj(), "\t\t%s", meth)
}
}
}
func formatMember(mem ssa.Member, maxname int) string {
func formatMember(obj types.Object, maxname int) string {
var buf bytes.Buffer
fmt.Fprintf(&buf, "%-5s %-*s", mem.Token(), maxname, mem.Name())
switch mem := mem.(type) {
case *ssa.NamedConst:
fmt.Fprintf(&buf, " %s = %s", mem.Type(), mem.Value.Name())
fmt.Fprintf(&buf, "%-5s %-*s", tokenOf(obj), maxname, obj.Name())
switch obj := obj.(type) {
case *types.Const:
fmt.Fprintf(&buf, " %s = %s", obj.Type(), obj.Val().String())
case *ssa.Function:
fmt.Fprintf(&buf, " %s", mem.Type())
case *types.Func:
fmt.Fprintf(&buf, " %s", obj.Type())
case *ssa.Type:
case *types.TypeName:
// Abbreviate long aggregate type names.
var abbrev string
switch t := mem.Type().Underlying().(type) {
switch t := obj.Type().Underlying().(type) {
case *types.Interface:
if t.NumMethods() > 1 {
abbrev = "interface{...}"
@ -836,13 +818,13 @@ func formatMember(mem ssa.Member, maxname int) string {
}
}
if abbrev == "" {
fmt.Fprintf(&buf, " %s", mem.Type().Underlying())
fmt.Fprintf(&buf, " %s", obj.Type().Underlying())
} else {
fmt.Fprintf(&buf, " %s", abbrev)
}
case *ssa.Global:
fmt.Fprintf(&buf, " %s", deref(mem.Type()))
case *types.Var:
fmt.Fprintf(&buf, " %s", obj.Type())
}
return buf.String()
}
@ -850,22 +832,20 @@ func formatMember(mem ssa.Member, maxname int) string {
func (r *describePackageResult) toJSON(res *json.Result, fset *token.FileSet) {
var members []*json.DescribeMember
for _, mem := range r.members {
typ := mem.mem.Type()
typ := mem.obj.Type()
var val string
switch mem := mem.mem.(type) {
case *ssa.NamedConst:
val = mem.Value.Value.String()
case *ssa.Type:
switch mem := mem.obj.(type) {
case *types.Const:
val = mem.Val().String()
case *types.TypeName:
typ = typ.Underlying()
case *ssa.Global:
typ = deref(typ)
}
members = append(members, &json.DescribeMember{
Name: mem.mem.Name(),
Name: mem.obj.Name(),
Type: typ.String(),
Value: val,
Pos: fset.Position(mem.mem.Pos()).String(),
Kind: mem.mem.Token().String(),
Pos: fset.Position(mem.obj.Pos()).String(),
Kind: tokenOf(mem.obj),
Methods: methodsToJSON(mem.methods, fset),
})
}
@ -874,12 +854,28 @@ func (r *describePackageResult) toJSON(res *json.Result, fset *token.FileSet) {
Pos: fset.Position(r.node.Pos()).String(),
Detail: "package",
Package: &json.DescribePackage{
Path: r.path,
Path: r.pkg.Path(),
Members: members,
},
}
}
func tokenOf(o types.Object) string {
switch o.(type) {
case *types.Func:
return "func"
case *types.Var:
return "var"
case *types.TypeName:
return "type"
case *types.Const:
return "const"
case *types.Package:
return "package"
}
panic(o)
}
// ---- STATEMENT ------------------------------------------------------------
func describeStmt(o *oracle, path []ast.Node) (*describeStmtResult, error) {

View File

@ -44,18 +44,6 @@
}
]
},
{
"name": "init",
"type": "func()",
"pos": "-",
"kind": "func"
},
{
"name": "init$guard",
"type": "bool",
"pos": "-",
"kind": "var"
},
{
"name": "main",
"type": "func()",

View File

@ -1,19 +1,17 @@
-------- @describe pkgdecl --------
definition of package "describe"
type C int
type C int
method (*describe.C) f()
type D struct{}
type D struct{}
method (describe.D) f()
type I interface{f()}
type I interface{f()}
method (describe.I) f()
type cake float64
func deadcode func()
var global *string
func init func()
var init$guard bool
func main func()
const pi untyped float = 3141/1000:untyped float
const pie describe.cake = 1768225803696341/562949953421312:describe.cake
type cake float64
func deadcode func()
var global *string
func main func()
const pi untyped float = 3141/1000
const pie describe.cake = 1768225803696341/562949953421312
-------- @describe type-ref-builtin --------
reference to built-in type float64

View File

@ -1,6 +1,6 @@
-------- @describe ref-pkg-import --------
import of package "lib"
const Const untyped integer = 3:untyped integer
const Const untyped integer = 3
func Func func()
type Type int
method (lib.Type) Method(x *int) *int
@ -36,7 +36,7 @@ value may point to these labels:
-------- @describe ref-pkg --------
reference to package "lib"
const Const untyped integer = 3:untyped integer
const Const untyped integer = 3
func Func func()
type Type int
method (lib.Type) Method(x *int) *int