aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Donovan <adonovan@google.com>2015-09-01 22:24:58 +0000
committerandroid-build-merger <android-build-merger@google.com>2015-09-01 22:24:58 +0000
commit150171df577da7c3753e3656bbea587ebcf9ea54 (patch)
tree9e314a55ea0b2d4098b8938c05a293b83ab36d3e
parentb07db0248f6bd1e19d807acc4c2e31d857f9bc75 (diff)
parent997b3545fd86c3a2d8e5fe6366174d7786e71278 (diff)
downloadtools-150171df577da7c3753e3656bbea587ebcf9ea54.tar.gz
go/types: change {Type,Object,Selection}String to accept a Qualifier function
automerge: 997b354 * commit '997b3545fd86c3a2d8e5fe6366174d7786e71278': go/types: change {Type,Object,Selection}String to accept a Qualifier function
-rw-r--r--go/callgraph/rta/rta_test.go2
-rw-r--r--go/gccgoimporter/importer_test.go2
-rw-r--r--go/gcimporter/gcimporter_test.go2
-rw-r--r--go/loader/stdlib_test.go3
-rw-r--r--go/ssa/func.go4
-rw-r--r--go/ssa/print.go4
-rw-r--r--go/types/errors.go13
-rw-r--r--go/types/object.go68
-rw-r--r--go/types/operand.go8
-rw-r--r--go/types/selection.go14
-rw-r--r--go/types/type.go22
-rw-r--r--go/types/typestring.go96
-rw-r--r--go/types/typestring_test.go8
-rw-r--r--godoc/analysis/callgraph.go2
-rw-r--r--godoc/analysis/typeinfo.go19
-rw-r--r--oracle/describe.go14
-rw-r--r--oracle/freevars.go3
-rw-r--r--oracle/oracle.go6
-rw-r--r--refactor/lexical/lexical.go19
19 files changed, 186 insertions, 123 deletions
diff --git a/go/callgraph/rta/rta_test.go b/go/callgraph/rta/rta_test.go
index aef788d..26eec49 100644
--- a/go/callgraph/rta/rta_test.go
+++ b/go/callgraph/rta/rta_test.go
@@ -126,7 +126,7 @@ func printResult(res *rta.Result, from *types.Package) string {
var rtypes []string
res.RuntimeTypes.Iterate(func(key types.Type, value interface{}) {
if value == false { // accessible to reflection
- rtypes = append(rtypes, types.TypeString(from, key))
+ rtypes = append(rtypes, types.TypeString(key, types.RelativeTo(from)))
}
})
writeSorted(rtypes)
diff --git a/go/gccgoimporter/importer_test.go b/go/gccgoimporter/importer_test.go
index c7adb45..ee47425 100644
--- a/go/gccgoimporter/importer_test.go
+++ b/go/gccgoimporter/importer_test.go
@@ -34,7 +34,7 @@ func runImporterTest(t *testing.T, imp types.Importer, initmap map[*types.Packag
return
}
- got := types.ObjectString(pkg, obj)
+ got := types.ObjectString(obj, types.RelativeTo(pkg))
if got != test.want {
t.Errorf("%s: got %q; want %q", test.name, got, test.want)
}
diff --git a/go/gcimporter/gcimporter_test.go b/go/gcimporter/gcimporter_test.go
index e72c30f..73a4747 100644
--- a/go/gcimporter/gcimporter_test.go
+++ b/go/gcimporter/gcimporter_test.go
@@ -177,7 +177,7 @@ func TestImportedTypes(t *testing.T) {
continue
}
- got := types.ObjectString(pkg, obj)
+ got := types.ObjectString(obj, types.RelativeTo(pkg))
if got != test.want {
t.Errorf("%s: got %q; want %q", test.name, got, test.want)
}
diff --git a/go/loader/stdlib_test.go b/go/loader/stdlib_test.go
index d14928a..f5c45ab 100644
--- a/go/loader/stdlib_test.go
+++ b/go/loader/stdlib_test.go
@@ -62,9 +62,10 @@ func TestStdlib(t *testing.T) {
for pkg := range prog.AllPackages {
fmt.Printf("Package %s:\n", pkg.Path())
scope := pkg.Scope()
+ qualifier := types.RelativeTo(pkg)
for _, name := range scope.Names() {
if ast.IsExported(name) {
- fmt.Printf("\t%s\n", types.ObjectString(pkg, scope.Lookup(name)))
+ fmt.Printf("\t%s\n", types.ObjectString(scope.Lookup(name), qualifier))
}
}
fmt.Println()
diff --git a/go/ssa/func.go b/go/ssa/func.go
index fec527b..a9c0f75 100644
--- a/go/ssa/func.go
+++ b/go/ssa/func.go
@@ -522,11 +522,11 @@ func writeSignature(buf *bytes.Buffer, from *types.Package, name string, sig *ty
buf.WriteString(n)
buf.WriteString(" ")
}
- types.WriteType(buf, from, params[0].Type())
+ types.WriteType(buf, params[0].Type(), types.RelativeTo(from))
buf.WriteString(") ")
}
buf.WriteString(name)
- types.WriteSignature(buf, from, sig)
+ types.WriteSignature(buf, sig, types.RelativeTo(from))
}
func (f *Function) pkgobj() *types.Package {
diff --git a/go/ssa/print.go b/go/ssa/print.go
index 9fda3a4..88c31f6 100644
--- a/go/ssa/print.go
+++ b/go/ssa/print.go
@@ -39,7 +39,7 @@ func relName(v Value, i Instruction) string {
}
func relType(t types.Type, from *types.Package) string {
- return types.TypeString(from, t)
+ return types.TypeString(t, types.RelativeTo(from))
}
func relString(m Member, from *types.Package) string {
@@ -407,7 +407,7 @@ func WritePackage(buf *bytes.Buffer, p *Package) {
fmt.Fprintf(buf, " type %-*s %s\n",
maxname, name, relType(mem.Type().Underlying(), from))
for _, meth := range typeutil.IntuitiveMethodSet(mem.Type(), &p.Prog.MethodSets) {
- fmt.Fprintf(buf, " %s\n", types.SelectionString(from, meth))
+ fmt.Fprintf(buf, " %s\n", types.SelectionString(meth, types.RelativeTo(from)))
}
case *Global:
diff --git a/go/types/errors.go b/go/types/errors.go
index 0a9dd0e..0c0049b 100644
--- a/go/types/errors.go
+++ b/go/types/errors.go
@@ -23,6 +23,13 @@ func unreachable() {
panic("unreachable")
}
+func (check *Checker) qualifier(pkg *Package) string {
+ if pkg != check.pkg {
+ return pkg.path
+ }
+ return ""
+}
+
func (check *Checker) sprintf(format string, args ...interface{}) string {
for i, arg := range args {
switch a := arg.(type) {
@@ -31,15 +38,15 @@ func (check *Checker) sprintf(format string, args ...interface{}) string {
case operand:
panic("internal error: should always pass *operand")
case *operand:
- arg = operandString(check.pkg, a)
+ arg = operandString(a, check.qualifier)
case token.Pos:
arg = check.fset.Position(a).String()
case ast.Expr:
arg = ExprString(a)
case Object:
- arg = ObjectString(check.pkg, a)
+ arg = ObjectString(a, check.qualifier)
case Type:
- arg = TypeString(check.pkg, a)
+ arg = TypeString(a, check.qualifier)
}
args[i] = arg
}
diff --git a/go/types/object.go b/go/types/object.go
index 0b44804..a9b6c43 100644
--- a/go/types/object.go
+++ b/go/types/object.go
@@ -208,7 +208,7 @@ func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
// function or method obj.
func (obj *Func) FullName() string {
var buf bytes.Buffer
- writeFuncName(&buf, nil, obj)
+ writeFuncName(&buf, obj, nil)
return buf.String()
}
@@ -242,7 +242,7 @@ type Nil struct {
object
}
-func writeObject(buf *bytes.Buffer, this *Package, obj Object) {
+func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) {
typ := obj.Type()
switch obj := obj.(type) {
case *PkgName:
@@ -268,9 +268,9 @@ func writeObject(buf *bytes.Buffer, this *Package, obj Object) {
case *Func:
buf.WriteString("func ")
- writeFuncName(buf, this, obj)
+ writeFuncName(buf, obj, qf)
if typ != nil {
- WriteSignature(buf, this, typ.(*Signature))
+ WriteSignature(buf, typ.(*Signature), qf)
}
return
@@ -292,39 +292,52 @@ func writeObject(buf *bytes.Buffer, this *Package, obj Object) {
buf.WriteByte(' ')
- // For package-level objects, package-qualify the name,
- // except for intra-package references (this != nil).
- if pkg := obj.Pkg(); pkg != nil && this != pkg && pkg.scope.Lookup(obj.Name()) == obj {
- buf.WriteString(pkg.path)
- buf.WriteByte('.')
+ // For package-level objects, qualify the name.
+ if obj.Pkg() != nil && obj.Pkg().scope.Lookup(obj.Name()) == obj {
+ writePackage(buf, obj.Pkg(), qf)
}
buf.WriteString(obj.Name())
if typ != nil {
buf.WriteByte(' ')
- WriteType(buf, this, typ)
+ WriteType(buf, typ, qf)
+ }
+}
+
+func writePackage(buf *bytes.Buffer, pkg *Package, qf Qualifier) {
+ if pkg == nil {
+ return
+ }
+ var s string
+ if qf != nil {
+ s = qf(pkg)
+ } else {
+ s = pkg.Path()
+ }
+ if s != "" {
+ buf.WriteString(s)
+ buf.WriteByte('.')
}
}
// ObjectString returns the string form of obj.
-// Object and type names are printed package-qualified
-// only if they do not belong to this package.
-//
-func ObjectString(this *Package, obj Object) string {
+// The Qualifier controls the printing of
+// package-level objects, and may be nil.
+func ObjectString(obj Object, qf Qualifier) string {
var buf bytes.Buffer
- writeObject(&buf, this, obj)
+ writeObject(&buf, obj, qf)
return buf.String()
}
-func (obj *PkgName) String() string { return ObjectString(nil, obj) }
-func (obj *Const) String() string { return ObjectString(nil, obj) }
-func (obj *TypeName) String() string { return ObjectString(nil, obj) }
-func (obj *Var) String() string { return ObjectString(nil, obj) }
-func (obj *Func) String() string { return ObjectString(nil, obj) }
-func (obj *Label) String() string { return ObjectString(nil, obj) }
-func (obj *Builtin) String() string { return ObjectString(nil, obj) }
-func (obj *Nil) String() string { return ObjectString(nil, obj) }
+func (obj *PkgName) String() string { return ObjectString(obj, nil) }
+func (obj *Const) String() string { return ObjectString(obj, nil) }
+func (obj *TypeName) String() string { return ObjectString(obj, nil) }
+func (obj *Var) String() string { return ObjectString(obj, nil) }
+func (obj *Func) String() string { return ObjectString(obj, nil) }
+func (obj *Label) String() string { return ObjectString(obj, nil) }
+func (obj *Builtin) String() string { return ObjectString(obj, nil) }
+func (obj *Nil) String() string { return ObjectString(obj, nil) }
-func writeFuncName(buf *bytes.Buffer, this *Package, f *Func) {
+func writeFuncName(buf *bytes.Buffer, f *Func, qf Qualifier) {
if f.typ != nil {
sig := f.typ.(*Signature)
if recv := sig.Recv(); recv != nil {
@@ -336,13 +349,12 @@ func writeFuncName(buf *bytes.Buffer, this *Package, f *Func) {
// Don't print it in full.
buf.WriteString("interface")
} else {
- WriteType(buf, this, recv.Type())
+ WriteType(buf, recv.Type(), qf)
}
buf.WriteByte(')')
buf.WriteByte('.')
- } else if f.pkg != nil && f.pkg != this {
- buf.WriteString(f.pkg.path)
- buf.WriteByte('.')
+ } else if f.pkg != nil {
+ writePackage(buf, f.pkg, qf)
}
}
buf.WriteString(f.name)
diff --git a/go/types/operand.go b/go/types/operand.go
index 7418eef..0ac6767 100644
--- a/go/types/operand.go
+++ b/go/types/operand.go
@@ -94,7 +94,7 @@ func (x *operand) pos() token.Pos {
// commaok <expr> (<untyped kind> <mode> )
// commaok <expr> ( <mode> of type <typ>)
//
-func operandString(this *Package, x *operand) string {
+func operandString(x *operand, qf Qualifier) string {
var buf bytes.Buffer
var expr string
@@ -105,7 +105,7 @@ func operandString(this *Package, x *operand) string {
case builtin:
expr = predeclaredFuncs[x.id].name
case typexpr:
- expr = TypeString(this, x.typ)
+ expr = TypeString(x.typ, qf)
case constant:
expr = x.val.String()
}
@@ -147,7 +147,7 @@ func operandString(this *Package, x *operand) string {
if hasType {
if x.typ != Typ[Invalid] {
buf.WriteString(" of type ")
- WriteType(&buf, this, x.typ)
+ WriteType(&buf, x.typ, qf)
} else {
buf.WriteString(" with invalid type")
}
@@ -162,7 +162,7 @@ func operandString(this *Package, x *operand) string {
}
func (x *operand) String() string {
- return operandString(nil, x)
+ return operandString(x, nil)
}
// setConst sets x to the untyped constant for literal lit.
diff --git a/go/types/selection.go b/go/types/selection.go
index 1c70165..124e0d3 100644
--- a/go/types/selection.go
+++ b/go/types/selection.go
@@ -105,18 +105,18 @@ func (s *Selection) Index() []int { return s.index }
// x to f in x.f.
func (s *Selection) Indirect() bool { return s.indirect }
-func (s *Selection) String() string { return SelectionString(nil, s) }
+func (s *Selection) String() string { return SelectionString(s, nil) }
// SelectionString returns the string form of s.
-// Type names are printed package-qualified
-// only if they do not belong to this package.
+// The Qualifier controls the printing of
+// package-level objects, and may be nil.
//
// Examples:
// "field (T) f int"
// "method (T) f(X) Y"
// "method expr (T) f(X) Y"
//
-func SelectionString(this *Package, s *Selection) string {
+func SelectionString(s *Selection, qf Qualifier) string {
var k string
switch s.kind {
case FieldVal:
@@ -131,13 +131,13 @@ func SelectionString(this *Package, s *Selection) string {
var buf bytes.Buffer
buf.WriteString(k)
buf.WriteByte('(')
- WriteType(&buf, this, s.Recv())
+ WriteType(&buf, s.Recv(), qf)
fmt.Fprintf(&buf, ") %s", s.obj.Name())
if T := s.Type(); s.kind == FieldVal {
buf.WriteByte(' ')
- WriteType(&buf, this, T)
+ WriteType(&buf, T, qf)
} else {
- WriteSignature(&buf, this, T.(*Signature))
+ WriteSignature(&buf, T.(*Signature), qf)
}
return buf.String()
}
diff --git a/go/types/type.go b/go/types/type.go
index 3d1af20..1df8b45 100644
--- a/go/types/type.go
+++ b/go/types/type.go
@@ -441,14 +441,14 @@ func (t *Map) Underlying() Type { return t }
func (t *Chan) Underlying() Type { return t }
func (t *Named) Underlying() Type { return t.underlying }
-func (t *Basic) String() string { return TypeString(nil, t) }
-func (t *Array) String() string { return TypeString(nil, t) }
-func (t *Slice) String() string { return TypeString(nil, t) }
-func (t *Struct) String() string { return TypeString(nil, t) }
-func (t *Pointer) String() string { return TypeString(nil, t) }
-func (t *Tuple) String() string { return TypeString(nil, t) }
-func (t *Signature) String() string { return TypeString(nil, t) }
-func (t *Interface) String() string { return TypeString(nil, t) }
-func (t *Map) String() string { return TypeString(nil, t) }
-func (t *Chan) String() string { return TypeString(nil, t) }
-func (t *Named) String() string { return TypeString(nil, t) }
+func (t *Basic) String() string { return TypeString(t, nil) }
+func (t *Array) String() string { return TypeString(t, nil) }
+func (t *Slice) String() string { return TypeString(t, nil) }
+func (t *Struct) String() string { return TypeString(t, nil) }
+func (t *Pointer) String() string { return TypeString(t, nil) }
+func (t *Tuple) String() string { return TypeString(t, nil) }
+func (t *Signature) String() string { return TypeString(t, nil) }
+func (t *Interface) String() string { return TypeString(t, nil) }
+func (t *Map) String() string { return TypeString(t, nil) }
+func (t *Chan) String() string { return TypeString(t, nil) }
+func (t *Named) String() string { return TypeString(t, nil) }
diff --git a/go/types/typestring.go b/go/types/typestring.go
index 9a537e8..abee8ab 100644
--- a/go/types/typestring.go
+++ b/go/types/typestring.go
@@ -11,6 +11,33 @@ import (
"fmt"
)
+// A Qualifier controls how named package-level objects are printed in
+// calls to TypeString, ObjectString, and SelectionString.
+//
+// These three formatting routines call the Qualifier for each
+// package-level object O, and if the Qualifier returns a non-empty
+// string p, the object is printed in the form p.O.
+// If it returns an empty string, only the object name O is printed.
+//
+// Using a nil Qualifier is equivalent to using (*Package).Path: the
+// object is qualified by the import path, e.g., "encoding/json.Marshal".
+//
+type Qualifier func(*Package) string
+
+// RelativeTo(pkg) returns a Qualifier that fully qualifies members of
+// all packages other than pkg.
+func RelativeTo(pkg *Package) Qualifier {
+ if pkg == nil {
+ return nil
+ }
+ return func(other *Package) string {
+ if pkg == other {
+ return "" // same package; unqualified
+ }
+ return other.Path()
+ }
+}
+
// If GcCompatibilityMode is set, printing of types is modified
// to match the representation of some types in the gc compiler:
//
@@ -28,22 +55,22 @@ import (
var GcCompatibilityMode bool
// TypeString returns the string representation of typ.
-// Named types are printed package-qualified if they
-// do not belong to this package.
-func TypeString(this *Package, typ Type) string {
+// The Qualifier controls the printing of
+// package-level objects, and may be nil.
+func TypeString(typ Type, qf Qualifier) string {
var buf bytes.Buffer
- WriteType(&buf, this, typ)
+ WriteType(&buf, typ, qf)
return buf.String()
}
// WriteType writes the string representation of typ to buf.
-// Named types are printed package-qualified if they
-// do not belong to this package.
-func WriteType(buf *bytes.Buffer, this *Package, typ Type) {
- writeType(buf, this, typ, make([]Type, 8))
+// The Qualifier controls the printing of
+// package-level objects, and may be nil.
+func WriteType(buf *bytes.Buffer, typ Type, qf Qualifier) {
+ writeType(buf, typ, qf, make([]Type, 8))
}
-func writeType(buf *bytes.Buffer, this *Package, typ Type, visited []Type) {
+func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
// Theoretically, this is a quadratic lookup algorithm, but in
// practice deeply nested composite types with unnamed component
// types are uncommon. This code is likely more efficient than
@@ -77,11 +104,11 @@ func writeType(buf *bytes.Buffer, this *Package, typ Type, visited []Type) {
case *Array:
fmt.Fprintf(buf, "[%d]", t.len)
- writeType(buf, this, t.elem, visited)
+ writeType(buf, t.elem, qf, visited)
case *Slice:
buf.WriteString("[]")
- writeType(buf, this, t.elem, visited)
+ writeType(buf, t.elem, qf, visited)
case *Struct:
buf.WriteString("struct{")
@@ -93,7 +120,7 @@ func writeType(buf *bytes.Buffer, this *Package, typ Type, visited []Type) {
buf.WriteString(f.name)
buf.WriteByte(' ')
}
- writeType(buf, this, f.typ, visited)
+ writeType(buf, f.typ, qf, visited)
if tag := t.Tag(i); tag != "" {
fmt.Fprintf(buf, " %q", tag)
}
@@ -102,14 +129,14 @@ func writeType(buf *bytes.Buffer, this *Package, typ Type, visited []Type) {
case *Pointer:
buf.WriteByte('*')
- writeType(buf, this, t.base, visited)
+ writeType(buf, t.base, qf, visited)
case *Tuple:
- writeTuple(buf, this, t, false, visited)
+ writeTuple(buf, t, false, qf, visited)
case *Signature:
buf.WriteString("func")
- writeSignature(buf, this, t, visited)
+ writeSignature(buf, t, qf, visited)
case *Interface:
// We write the source-level methods and embedded types rather
@@ -132,7 +159,7 @@ func writeType(buf *bytes.Buffer, this *Package, typ Type, visited []Type) {
buf.WriteString("; ")
}
buf.WriteString(m.name)
- writeSignature(buf, this, m.typ.(*Signature), visited)
+ writeSignature(buf, m.typ.(*Signature), qf, visited)
}
} else {
// print explicit interface methods and embedded types
@@ -141,22 +168,22 @@ func writeType(buf *bytes.Buffer, this *Package, typ Type, visited []Type) {
buf.WriteString("; ")
}
buf.WriteString(m.name)
- writeSignature(buf, this, m.typ.(*Signature), visited)
+ writeSignature(buf, m.typ.(*Signature), qf, visited)
}
for i, typ := range t.embeddeds {
if i > 0 || len(t.methods) > 0 {
buf.WriteString("; ")
}
- writeType(buf, this, typ, visited)
+ writeType(buf, typ, qf, visited)
}
}
buf.WriteByte('}')
case *Map:
buf.WriteString("map[")
- writeType(buf, this, t.key, visited)
+ writeType(buf, t.key, qf, visited)
buf.WriteByte(']')
- writeType(buf, this, t.elem, visited)
+ writeType(buf, t.elem, qf, visited)
case *Chan:
var s string
@@ -179,7 +206,7 @@ func writeType(buf *bytes.Buffer, this *Package, typ Type, visited []Type) {
if parens {
buf.WriteByte('(')
}
- writeType(buf, this, t.elem, visited)
+ writeType(buf, t.elem, qf, visited)
if parens {
buf.WriteByte(')')
}
@@ -187,9 +214,8 @@ func writeType(buf *bytes.Buffer, this *Package, typ Type, visited []Type) {
case *Named:
s := "<Named w/o object>"
if obj := t.obj; obj != nil {
- if pkg := obj.pkg; pkg != nil && pkg != this {
- buf.WriteString(pkg.path)
- buf.WriteByte('.')
+ if obj.pkg != nil {
+ writePackage(buf, obj.pkg, qf)
}
// TODO(gri): function-local named types should be displayed
// differently from named types at package level to avoid
@@ -204,7 +230,7 @@ func writeType(buf *bytes.Buffer, this *Package, typ Type, visited []Type) {
}
}
-func writeTuple(buf *bytes.Buffer, this *Package, tup *Tuple, variadic bool, visited []Type) {
+func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visited []Type) {
buf.WriteByte('(')
if tup != nil {
for i, v := range tup.vars {
@@ -226,12 +252,12 @@ func writeTuple(buf *bytes.Buffer, this *Package, tup *Tuple, variadic bool, vis
if t, ok := typ.Underlying().(*Basic); !ok || t.kind != String {
panic("internal error: string type expected")
}
- writeType(buf, this, typ, visited)
+ writeType(buf, typ, qf, visited)
buf.WriteString("...")
continue
}
}
- writeType(buf, this, typ, visited)
+ writeType(buf, typ, qf, visited)
}
}
buf.WriteByte(')')
@@ -239,14 +265,14 @@ func writeTuple(buf *bytes.Buffer, this *Package, tup *Tuple, variadic bool, vis
// WriteSignature writes the representation of the signature sig to buf,
// without a leading "func" keyword.
-// Named types are printed package-qualified if they
-// do not belong to this package.
-func WriteSignature(buf *bytes.Buffer, this *Package, sig *Signature) {
- writeSignature(buf, this, sig, make([]Type, 8))
+// The Qualifier controls the printing of
+// package-level objects, and may be nil.
+func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) {
+ writeSignature(buf, sig, qf, make([]Type, 8))
}
-func writeSignature(buf *bytes.Buffer, this *Package, sig *Signature, visited []Type) {
- writeTuple(buf, this, sig.params, sig.variadic, visited)
+func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) {
+ writeTuple(buf, sig.params, sig.variadic, qf, visited)
n := sig.results.Len()
if n == 0 {
@@ -257,10 +283,10 @@ func writeSignature(buf *bytes.Buffer, this *Package, sig *Signature, visited []
buf.WriteByte(' ')
if n == 1 && sig.results.vars[0].name == "" {
// single unnamed result
- writeType(buf, this, sig.results.vars[0].typ, visited)
+ writeType(buf, sig.results.vars[0].typ, qf, visited)
return
}
// multiple or named result(s)
- writeTuple(buf, this, sig.results, false, visited)
+ writeTuple(buf, sig.results, false, qf, visited)
}
diff --git a/go/types/typestring_test.go b/go/types/typestring_test.go
index 8693687..975b623 100644
--- a/go/types/typestring_test.go
+++ b/go/types/typestring_test.go
@@ -152,7 +152,13 @@ func TestQualifiedTypeString(t *testing.T) {
{NewPointer(pT), p, "*T"},
{NewPointer(pT), q, "*p.T"},
} {
- if got := TypeString(test.this, test.typ); got != test.want {
+ qualifier := func(pkg *Package) string {
+ if pkg != test.this {
+ return pkg.Name()
+ }
+ return ""
+ }
+ if got := TypeString(test.typ, qualifier); got != test.want {
t.Errorf("TypeString(%s, %s) = %s, want %s",
test.this, test.typ, got, test.want)
}
diff --git a/godoc/analysis/callgraph.go b/godoc/analysis/callgraph.go
index 149b60c..a98d294 100644
--- a/godoc/analysis/callgraph.go
+++ b/godoc/analysis/callgraph.go
@@ -237,7 +237,7 @@ func funcToken(fn *ssa.Function) token.Pos {
func prettyFunc(this *types.Package, fn *ssa.Function) string {
if fn.Parent() != nil {
return fmt.Sprintf("%s in %s",
- types.TypeString(this, fn.Signature),
+ types.TypeString(fn.Signature, types.RelativeTo(this)),
prettyFunc(this, fn.Parent()))
}
if fn.Synthetic != "" && fn.Name() == "init" {
diff --git a/godoc/analysis/typeinfo.go b/godoc/analysis/typeinfo.go
index bd1b0c1..83e19c1 100644
--- a/godoc/analysis/typeinfo.go
+++ b/godoc/analysis/typeinfo.go
@@ -69,6 +69,7 @@ func (a *analysis) doTypeInfo(info *loader.PackageInfo, implements map[*types.Na
}
// RESOLUTION
+ qualifier := types.RelativeTo(info.Pkg)
for id, obj := range info.Uses {
// Position of the object definition.
pos := obj.Pos()
@@ -92,7 +93,7 @@ func (a *analysis) doTypeInfo(info *loader.PackageInfo, implements map[*types.Na
fi.addLink(aLink{
start: offset,
end: offset + len(id.Name),
- title: types.ObjectString(info.Pkg, obj),
+ title: types.ObjectString(obj, qualifier),
href: a.posURL(pos, Len),
})
}
@@ -106,7 +107,7 @@ func (a *analysis) doTypeInfo(info *loader.PackageInfo, implements map[*types.Na
}
func (a *analysis) namedType(obj *types.TypeName, implements map[*types.Named]implementsFacts) {
- this := obj.Pkg()
+ qualifier := types.RelativeTo(obj.Pkg())
T := obj.Type().(*types.Named)
v := &TypeInfoJSON{
Name: obj.Name(),
@@ -130,7 +131,7 @@ func (a *analysis) namedType(obj *types.TypeName, implements map[*types.Named]im
ByKind: byKind,
Other: anchorJSON{
Href: a.posURL(Tobj.Pos(), len(Tobj.Name())),
- Text: types.TypeString(this, T),
+ Text: types.TypeString(T, qualifier),
},
})
}
@@ -142,7 +143,7 @@ func (a *analysis) namedType(obj *types.TypeName, implements map[*types.Named]im
// "T is implemented by <iface>"...
// "T implements <iface>"...
group := implGroupJSON{
- Descr: types.TypeString(this, T),
+ Descr: types.TypeString(T, qualifier),
}
// Show concrete types first; use two passes.
for _, sub := range r.to {
@@ -164,7 +165,7 @@ func (a *analysis) namedType(obj *types.TypeName, implements map[*types.Named]im
if r.from != nil {
// "T implements <iface>"...
group := implGroupJSON{
- Descr: types.TypeString(this, T),
+ Descr: types.TypeString(T, qualifier),
}
for _, super := range r.from {
addFact(&group, super, false)
@@ -174,7 +175,7 @@ func (a *analysis) namedType(obj *types.TypeName, implements map[*types.Named]im
if r.fromPtr != nil {
// "*C implements <iface>"...
group := implGroupJSON{
- Descr: "*" + types.TypeString(this, T),
+ Descr: "*" + types.TypeString(T, qualifier),
}
for _, psuper := range r.fromPtr {
addFact(&group, psuper, false)
@@ -190,7 +191,7 @@ func (a *analysis) namedType(obj *types.TypeName, implements map[*types.Named]im
pos := meth.Pos() // may be 0 for error.Error
v.Methods = append(v.Methods, anchorJSON{
Href: a.posURL(pos, len(meth.Name())),
- Text: types.SelectionString(this, sel),
+ Text: types.SelectionString(sel, qualifier),
})
}
@@ -207,9 +208,9 @@ func (a *analysis) namedType(obj *types.TypeName, implements map[*types.Named]im
// Add info for exported package-level types to the package info.
if obj.Exported() && isPackageLevel(obj) {
- // TODO(adonovan): this.Path() is not unique!
+ // TODO(adonovan): Path is not unique!
// It is possible to declare a non-test package called x_test.
- a.result.pkgInfo(this.Path()).addType(v)
+ a.result.pkgInfo(obj.Pkg().Path()).addType(v)
}
}
diff --git a/oracle/describe.go b/oracle/describe.go
index 00c0525..ea1c5ec 100644
--- a/oracle/describe.go
+++ b/oracle/describe.go
@@ -590,20 +590,21 @@ func (r *describePackageResult) display(printf printfFunc) {
for _, mem := range r.members {
printf(mem.obj, "\t%s", formatMember(mem.obj, maxname))
for _, meth := range mem.methods {
- printf(meth.Obj(), "\t\t%s", types.SelectionString(r.pkg, meth))
+ printf(meth.Obj(), "\t\t%s", types.SelectionString(meth, types.RelativeTo(r.pkg)))
}
}
}
func formatMember(obj types.Object, maxname int) string {
+ qualifier := types.RelativeTo(obj.Pkg())
var buf bytes.Buffer
fmt.Fprintf(&buf, "%-5s %-*s", tokenOf(obj), maxname, obj.Name())
switch obj := obj.(type) {
case *types.Const:
- fmt.Fprintf(&buf, " %s = %s", types.TypeString(obj.Pkg(), obj.Type()), obj.Val().String())
+ fmt.Fprintf(&buf, " %s = %s", types.TypeString(obj.Type(), qualifier), obj.Val().String())
case *types.Func:
- fmt.Fprintf(&buf, " %s", types.TypeString(obj.Pkg(), obj.Type()))
+ fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type(), qualifier))
case *types.TypeName:
// Abbreviate long aggregate type names.
@@ -619,13 +620,13 @@ func formatMember(obj types.Object, maxname int) string {
}
}
if abbrev == "" {
- fmt.Fprintf(&buf, " %s", types.TypeString(obj.Pkg(), obj.Type().Underlying()))
+ fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type().Underlying(), qualifier))
} else {
fmt.Fprintf(&buf, " %s", abbrev)
}
case *types.Var:
- fmt.Fprintf(&buf, " %s", types.TypeString(obj.Pkg(), obj.Type()))
+ fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type(), qualifier))
}
return buf.String()
}
@@ -746,12 +747,13 @@ func isAccessibleFrom(obj types.Object, pkg *types.Package) bool {
}
func methodsToSerial(this *types.Package, methods []*types.Selection, fset *token.FileSet) []serial.DescribeMethod {
+ qualifier := types.RelativeTo(this)
var jmethods []serial.DescribeMethod
for _, meth := range methods {
var ser serial.DescribeMethod
if meth != nil { // may contain nils when called by implements (on a method)
ser = serial.DescribeMethod{
- Name: types.SelectionString(this, meth),
+ Name: types.SelectionString(meth, qualifier),
Pos: fset.Position(meth.Obj().Pos()).String(),
}
}
diff --git a/oracle/freevars.go b/oracle/freevars.go
index 580c97b..400a118 100644
--- a/oracle/freevars.go
+++ b/oracle/freevars.go
@@ -180,11 +180,12 @@ func (r *freevarsResult) display(printf printfFunc) {
printf(r.qpos, "No free identifiers.")
} else {
printf(r.qpos, "Free identifiers:")
+ qualifier := types.RelativeTo(r.qpos.info.Pkg)
for _, ref := range r.refs {
// Avoid printing "type T T".
var typstr string
if ref.kind != "type" {
- typstr = " " + types.TypeString(r.qpos.info.Pkg, ref.typ)
+ typstr = " " + types.TypeString(ref.typ, qualifier)
}
printf(ref.obj, "%s %s%s", ref.kind, ref.ref, typstr)
}
diff --git a/oracle/oracle.go b/oracle/oracle.go
index 65ac9ed..544cfa4 100644
--- a/oracle/oracle.go
+++ b/oracle/oracle.go
@@ -58,17 +58,17 @@ type queryPos struct {
// TypeString prints type T relative to the query position.
func (qpos *queryPos) typeString(T types.Type) string {
- return types.TypeString(qpos.info.Pkg, T)
+ return types.TypeString(T, types.RelativeTo(qpos.info.Pkg))
}
// ObjectString prints object obj relative to the query position.
func (qpos *queryPos) objectString(obj types.Object) string {
- return types.ObjectString(qpos.info.Pkg, obj)
+ return types.ObjectString(obj, types.RelativeTo(qpos.info.Pkg))
}
// SelectionString prints selection sel relative to the query position.
func (qpos *queryPos) selectionString(sel *types.Selection) string {
- return types.SelectionString(qpos.info.Pkg, sel)
+ return types.SelectionString(sel, types.RelativeTo(qpos.info.Pkg))
}
// A Query specifies a single oracle query.
diff --git a/refactor/lexical/lexical.go b/refactor/lexical/lexical.go
index 55ec391..c6567e4 100644
--- a/refactor/lexical/lexical.go
+++ b/refactor/lexical/lexical.go
@@ -189,6 +189,13 @@ func (r *resolver) setBlock(kind string, syntax ast.Node) *Block {
return b
}
+func (r *resolver) qualifier(pkg *types.Package) string {
+ if pkg == r.pkg {
+ return "" // unqualified intra-package reference
+ }
+ return pkg.Path()
+}
+
func (r *resolver) use(id *ast.Ident, env Environment) {
if id.Name == "_" {
return // an error
@@ -199,12 +206,12 @@ func (r *resolver) use(id *ast.Ident, env Environment) {
} else if want := r.info.Uses[id]; obj != want {
// sanity check against go/types resolver
logf("%s: internal error: lookup of %s yielded wrong object: got %v (%s), want %v\n",
- r.fset.Position(id.Pos()), id.Name, types.ObjectString(r.pkg, obj),
+ r.fset.Position(id.Pos()), id.Name, types.ObjectString(obj, r.qualifier),
r.fset.Position(obj.Pos()),
want)
}
if trace {
- logf("use %s = %v in %s\n", id.Name, types.ObjectString(r.pkg, obj), env)
+ logf("use %s = %v in %s\n", id.Name, types.ObjectString(obj, r.qualifier), env)
}
r.result.Refs[obj] = append(r.result.Refs[obj], Reference{id, env})
@@ -248,7 +255,7 @@ func (r *resolver) defineObject(b *Block, name string, obj types.Object) {
b.bindings = append(b.bindings, obj)
b.index[name] = i
if trace {
- logf("def %s = %s in %s\n", name, types.ObjectString(r.pkg, obj), b)
+ logf("def %s = %s in %s\n", name, types.ObjectString(obj, r.qualifier), b)
}
r.result.Defs[obj] = b
}
@@ -323,7 +330,7 @@ func (r *resolver) expr(n ast.Expr) {
// id := kv.Key.(*ast.Ident)
// obj := r.info.Uses[id]
// logf("use %s = %v (field)\n",
- // id.Name, types.ObjectString(r.pkg, obj))
+ // id.Name, types.ObjectString(obj, r.qualifier))
// TODO make a fake FieldVal selection?
} else {
r.expr(elt)
@@ -344,10 +351,10 @@ func (r *resolver) expr(n ast.Expr) {
// switch sel.Kind() {
// case types.FieldVal:
// logf("use %s = %v (field)\n",
- // n.Sel.Name, types.ObjectString(r.pkg, sel.Obj()))
+ // n.Sel.Name, types.ObjectString(sel.Obj(), r.qualifier))
// case types.MethodExpr, types.MethodVal:
// logf("use %s = %v (method)\n",
- // n.Sel.Name, types.ObjectString(r.pkg, sel.Obj()))
+ // n.Sel.Name, types.ObjectString(sel.Obj(), r.qualifier))
// }
// } else { // qualified identifier
// obj := r.info.Uses[n.Sel]