Skip to content

Commit 997b354

Browse files
committed
go/types: change {Type,Object,Selection}String to accept a Qualifier function
The optional Qualifier function determines what prefix to attach to package-level names, enabling clients to qualify packages in different ways, for example, using only the package name instead of its complete path, or using the locally appropriate name for package given a set of (possibly renaming) imports. Prior to this change, clients wanting this behavior had to copy hundreds of lines of complex printing logic. Fun fact: (*types.Package).Path and (*types.Package).Name are valid Qualifier functions. We provide the RelativeTo helper function to create Qualifiers so that the old behavior remains a one-liner. Fixes #11133 Change-Id: Ibd63f639c7b3aa1738826d6165f2d810efeb8293 Reviewed-on: https://go-review.googlesource.com/11692 Reviewed-by: Robert Griesemer <gri@golang.org>
1 parent 749901c commit 997b354

File tree

19 files changed

+186
-123
lines changed

19 files changed

+186
-123
lines changed

go/callgraph/rta/rta_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func printResult(res *rta.Result, from *types.Package) string {
126126
var rtypes []string
127127
res.RuntimeTypes.Iterate(func(key types.Type, value interface{}) {
128128
if value == false { // accessible to reflection
129-
rtypes = append(rtypes, types.TypeString(from, key))
129+
rtypes = append(rtypes, types.TypeString(key, types.RelativeTo(from)))
130130
}
131131
})
132132
writeSorted(rtypes)

go/gccgoimporter/importer_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func runImporterTest(t *testing.T, imp types.Importer, initmap map[*types.Packag
3434
return
3535
}
3636

37-
got := types.ObjectString(pkg, obj)
37+
got := types.ObjectString(obj, types.RelativeTo(pkg))
3838
if got != test.want {
3939
t.Errorf("%s: got %q; want %q", test.name, got, test.want)
4040
}

go/gcimporter/gcimporter_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ func TestImportedTypes(t *testing.T) {
177177
continue
178178
}
179179

180-
got := types.ObjectString(pkg, obj)
180+
got := types.ObjectString(obj, types.RelativeTo(pkg))
181181
if got != test.want {
182182
t.Errorf("%s: got %q; want %q", test.name, got, test.want)
183183
}

go/loader/stdlib_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ func TestStdlib(t *testing.T) {
6262
for pkg := range prog.AllPackages {
6363
fmt.Printf("Package %s:\n", pkg.Path())
6464
scope := pkg.Scope()
65+
qualifier := types.RelativeTo(pkg)
6566
for _, name := range scope.Names() {
6667
if ast.IsExported(name) {
67-
fmt.Printf("\t%s\n", types.ObjectString(pkg, scope.Lookup(name)))
68+
fmt.Printf("\t%s\n", types.ObjectString(scope.Lookup(name), qualifier))
6869
}
6970
}
7071
fmt.Println()

go/ssa/func.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,11 +522,11 @@ func writeSignature(buf *bytes.Buffer, from *types.Package, name string, sig *ty
522522
buf.WriteString(n)
523523
buf.WriteString(" ")
524524
}
525-
types.WriteType(buf, from, params[0].Type())
525+
types.WriteType(buf, params[0].Type(), types.RelativeTo(from))
526526
buf.WriteString(") ")
527527
}
528528
buf.WriteString(name)
529-
types.WriteSignature(buf, from, sig)
529+
types.WriteSignature(buf, sig, types.RelativeTo(from))
530530
}
531531

532532
func (f *Function) pkgobj() *types.Package {

go/ssa/print.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func relName(v Value, i Instruction) string {
3939
}
4040

4141
func relType(t types.Type, from *types.Package) string {
42-
return types.TypeString(from, t)
42+
return types.TypeString(t, types.RelativeTo(from))
4343
}
4444

4545
func relString(m Member, from *types.Package) string {
@@ -407,7 +407,7 @@ func WritePackage(buf *bytes.Buffer, p *Package) {
407407
fmt.Fprintf(buf, " type %-*s %s\n",
408408
maxname, name, relType(mem.Type().Underlying(), from))
409409
for _, meth := range typeutil.IntuitiveMethodSet(mem.Type(), &p.Prog.MethodSets) {
410-
fmt.Fprintf(buf, " %s\n", types.SelectionString(from, meth))
410+
fmt.Fprintf(buf, " %s\n", types.SelectionString(meth, types.RelativeTo(from)))
411411
}
412412

413413
case *Global:

go/types/errors.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ func unreachable() {
2323
panic("unreachable")
2424
}
2525

26+
func (check *Checker) qualifier(pkg *Package) string {
27+
if pkg != check.pkg {
28+
return pkg.path
29+
}
30+
return ""
31+
}
32+
2633
func (check *Checker) sprintf(format string, args ...interface{}) string {
2734
for i, arg := range args {
2835
switch a := arg.(type) {
@@ -31,15 +38,15 @@ func (check *Checker) sprintf(format string, args ...interface{}) string {
3138
case operand:
3239
panic("internal error: should always pass *operand")
3340
case *operand:
34-
arg = operandString(check.pkg, a)
41+
arg = operandString(a, check.qualifier)
3542
case token.Pos:
3643
arg = check.fset.Position(a).String()
3744
case ast.Expr:
3845
arg = ExprString(a)
3946
case Object:
40-
arg = ObjectString(check.pkg, a)
47+
arg = ObjectString(a, check.qualifier)
4148
case Type:
42-
arg = TypeString(check.pkg, a)
49+
arg = TypeString(a, check.qualifier)
4350
}
4451
args[i] = arg
4552
}

go/types/object.go

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
208208
// function or method obj.
209209
func (obj *Func) FullName() string {
210210
var buf bytes.Buffer
211-
writeFuncName(&buf, nil, obj)
211+
writeFuncName(&buf, obj, nil)
212212
return buf.String()
213213
}
214214

@@ -242,7 +242,7 @@ type Nil struct {
242242
object
243243
}
244244

245-
func writeObject(buf *bytes.Buffer, this *Package, obj Object) {
245+
func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) {
246246
typ := obj.Type()
247247
switch obj := obj.(type) {
248248
case *PkgName:
@@ -268,9 +268,9 @@ func writeObject(buf *bytes.Buffer, this *Package, obj Object) {
268268

269269
case *Func:
270270
buf.WriteString("func ")
271-
writeFuncName(buf, this, obj)
271+
writeFuncName(buf, obj, qf)
272272
if typ != nil {
273-
WriteSignature(buf, this, typ.(*Signature))
273+
WriteSignature(buf, typ.(*Signature), qf)
274274
}
275275
return
276276

@@ -292,39 +292,52 @@ func writeObject(buf *bytes.Buffer, this *Package, obj Object) {
292292

293293
buf.WriteByte(' ')
294294

295-
// For package-level objects, package-qualify the name,
296-
// except for intra-package references (this != nil).
297-
if pkg := obj.Pkg(); pkg != nil && this != pkg && pkg.scope.Lookup(obj.Name()) == obj {
298-
buf.WriteString(pkg.path)
299-
buf.WriteByte('.')
295+
// For package-level objects, qualify the name.
296+
if obj.Pkg() != nil && obj.Pkg().scope.Lookup(obj.Name()) == obj {
297+
writePackage(buf, obj.Pkg(), qf)
300298
}
301299
buf.WriteString(obj.Name())
302300
if typ != nil {
303301
buf.WriteByte(' ')
304-
WriteType(buf, this, typ)
302+
WriteType(buf, typ, qf)
303+
}
304+
}
305+
306+
func writePackage(buf *bytes.Buffer, pkg *Package, qf Qualifier) {
307+
if pkg == nil {
308+
return
309+
}
310+
var s string
311+
if qf != nil {
312+
s = qf(pkg)
313+
} else {
314+
s = pkg.Path()
315+
}
316+
if s != "" {
317+
buf.WriteString(s)
318+
buf.WriteByte('.')
305319
}
306320
}
307321

308322
// ObjectString returns the string form of obj.
309-
// Object and type names are printed package-qualified
310-
// only if they do not belong to this package.
311-
//
312-
func ObjectString(this *Package, obj Object) string {
323+
// The Qualifier controls the printing of
324+
// package-level objects, and may be nil.
325+
func ObjectString(obj Object, qf Qualifier) string {
313326
var buf bytes.Buffer
314-
writeObject(&buf, this, obj)
327+
writeObject(&buf, obj, qf)
315328
return buf.String()
316329
}
317330

318-
func (obj *PkgName) String() string { return ObjectString(nil, obj) }
319-
func (obj *Const) String() string { return ObjectString(nil, obj) }
320-
func (obj *TypeName) String() string { return ObjectString(nil, obj) }
321-
func (obj *Var) String() string { return ObjectString(nil, obj) }
322-
func (obj *Func) String() string { return ObjectString(nil, obj) }
323-
func (obj *Label) String() string { return ObjectString(nil, obj) }
324-
func (obj *Builtin) String() string { return ObjectString(nil, obj) }
325-
func (obj *Nil) String() string { return ObjectString(nil, obj) }
331+
func (obj *PkgName) String() string { return ObjectString(obj, nil) }
332+
func (obj *Const) String() string { return ObjectString(obj, nil) }
333+
func (obj *TypeName) String() string { return ObjectString(obj, nil) }
334+
func (obj *Var) String() string { return ObjectString(obj, nil) }
335+
func (obj *Func) String() string { return ObjectString(obj, nil) }
336+
func (obj *Label) String() string { return ObjectString(obj, nil) }
337+
func (obj *Builtin) String() string { return ObjectString(obj, nil) }
338+
func (obj *Nil) String() string { return ObjectString(obj, nil) }
326339

327-
func writeFuncName(buf *bytes.Buffer, this *Package, f *Func) {
340+
func writeFuncName(buf *bytes.Buffer, f *Func, qf Qualifier) {
328341
if f.typ != nil {
329342
sig := f.typ.(*Signature)
330343
if recv := sig.Recv(); recv != nil {
@@ -336,13 +349,12 @@ func writeFuncName(buf *bytes.Buffer, this *Package, f *Func) {
336349
// Don't print it in full.
337350
buf.WriteString("interface")
338351
} else {
339-
WriteType(buf, this, recv.Type())
352+
WriteType(buf, recv.Type(), qf)
340353
}
341354
buf.WriteByte(')')
342355
buf.WriteByte('.')
343-
} else if f.pkg != nil && f.pkg != this {
344-
buf.WriteString(f.pkg.path)
345-
buf.WriteByte('.')
356+
} else if f.pkg != nil {
357+
writePackage(buf, f.pkg, qf)
346358
}
347359
}
348360
buf.WriteString(f.name)

go/types/operand.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func (x *operand) pos() token.Pos {
9494
// commaok <expr> (<untyped kind> <mode> )
9595
// commaok <expr> ( <mode> of type <typ>)
9696
//
97-
func operandString(this *Package, x *operand) string {
97+
func operandString(x *operand, qf Qualifier) string {
9898
var buf bytes.Buffer
9999

100100
var expr string
@@ -105,7 +105,7 @@ func operandString(this *Package, x *operand) string {
105105
case builtin:
106106
expr = predeclaredFuncs[x.id].name
107107
case typexpr:
108-
expr = TypeString(this, x.typ)
108+
expr = TypeString(x.typ, qf)
109109
case constant:
110110
expr = x.val.String()
111111
}
@@ -147,7 +147,7 @@ func operandString(this *Package, x *operand) string {
147147
if hasType {
148148
if x.typ != Typ[Invalid] {
149149
buf.WriteString(" of type ")
150-
WriteType(&buf, this, x.typ)
150+
WriteType(&buf, x.typ, qf)
151151
} else {
152152
buf.WriteString(" with invalid type")
153153
}
@@ -162,7 +162,7 @@ func operandString(this *Package, x *operand) string {
162162
}
163163

164164
func (x *operand) String() string {
165-
return operandString(nil, x)
165+
return operandString(x, nil)
166166
}
167167

168168
// setConst sets x to the untyped constant for literal lit.

go/types/selection.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,18 +105,18 @@ func (s *Selection) Index() []int { return s.index }
105105
// x to f in x.f.
106106
func (s *Selection) Indirect() bool { return s.indirect }
107107

108-
func (s *Selection) String() string { return SelectionString(nil, s) }
108+
func (s *Selection) String() string { return SelectionString(s, nil) }
109109

110110
// SelectionString returns the string form of s.
111-
// Type names are printed package-qualified
112-
// only if they do not belong to this package.
111+
// The Qualifier controls the printing of
112+
// package-level objects, and may be nil.
113113
//
114114
// Examples:
115115
// "field (T) f int"
116116
// "method (T) f(X) Y"
117117
// "method expr (T) f(X) Y"
118118
//
119-
func SelectionString(this *Package, s *Selection) string {
119+
func SelectionString(s *Selection, qf Qualifier) string {
120120
var k string
121121
switch s.kind {
122122
case FieldVal:
@@ -131,13 +131,13 @@ func SelectionString(this *Package, s *Selection) string {
131131
var buf bytes.Buffer
132132
buf.WriteString(k)
133133
buf.WriteByte('(')
134-
WriteType(&buf, this, s.Recv())
134+
WriteType(&buf, s.Recv(), qf)
135135
fmt.Fprintf(&buf, ") %s", s.obj.Name())
136136
if T := s.Type(); s.kind == FieldVal {
137137
buf.WriteByte(' ')
138-
WriteType(&buf, this, T)
138+
WriteType(&buf, T, qf)
139139
} else {
140-
WriteSignature(&buf, this, T.(*Signature))
140+
WriteSignature(&buf, T.(*Signature), qf)
141141
}
142142
return buf.String()
143143
}

go/types/type.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -441,14 +441,14 @@ func (t *Map) Underlying() Type { return t }
441441
func (t *Chan) Underlying() Type { return t }
442442
func (t *Named) Underlying() Type { return t.underlying }
443443

444-
func (t *Basic) String() string { return TypeString(nil, t) }
445-
func (t *Array) String() string { return TypeString(nil, t) }
446-
func (t *Slice) String() string { return TypeString(nil, t) }
447-
func (t *Struct) String() string { return TypeString(nil, t) }
448-
func (t *Pointer) String() string { return TypeString(nil, t) }
449-
func (t *Tuple) String() string { return TypeString(nil, t) }
450-
func (t *Signature) String() string { return TypeString(nil, t) }
451-
func (t *Interface) String() string { return TypeString(nil, t) }
452-
func (t *Map) String() string { return TypeString(nil, t) }
453-
func (t *Chan) String() string { return TypeString(nil, t) }
454-
func (t *Named) String() string { return TypeString(nil, t) }
444+
func (t *Basic) String() string { return TypeString(t, nil) }
445+
func (t *Array) String() string { return TypeString(t, nil) }
446+
func (t *Slice) String() string { return TypeString(t, nil) }
447+
func (t *Struct) String() string { return TypeString(t, nil) }
448+
func (t *Pointer) String() string { return TypeString(t, nil) }
449+
func (t *Tuple) String() string { return TypeString(t, nil) }
450+
func (t *Signature) String() string { return TypeString(t, nil) }
451+
func (t *Interface) String() string { return TypeString(t, nil) }
452+
func (t *Map) String() string { return TypeString(t, nil) }
453+
func (t *Chan) String() string { return TypeString(t, nil) }
454+
func (t *Named) String() string { return TypeString(t, nil) }

0 commit comments

Comments
 (0)