53 lines
1.6 KiB
Go
53 lines
1.6 KiB
Go
// Copyright 2014 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package typeutil
|
|
|
|
// This file defines utilities for user interfaces that display types.
|
|
|
|
import "go/types"
|
|
|
|
// IntuitiveMethodSet returns the intuitive method set of a type T,
|
|
// which is the set of methods you can call on an addressable value of
|
|
// that type.
|
|
//
|
|
// The result always contains MethodSet(T), and is exactly MethodSet(T)
|
|
// for interface types and for pointer-to-concrete types.
|
|
// For all other concrete types T, the result additionally
|
|
// contains each method belonging to *T if there is no identically
|
|
// named method on T itself.
|
|
//
|
|
// This corresponds to user intuition about method sets;
|
|
// this function is intended only for user interfaces.
|
|
//
|
|
// The order of the result is as for types.MethodSet(T).
|
|
//
|
|
func IntuitiveMethodSet(T types.Type, msets *MethodSetCache) []*types.Selection {
|
|
isPointerToConcrete := func(T types.Type) bool {
|
|
ptr, ok := T.(*types.Pointer)
|
|
return ok && !types.IsInterface(ptr.Elem())
|
|
}
|
|
|
|
var result []*types.Selection
|
|
mset := msets.MethodSet(T)
|
|
if types.IsInterface(T) || isPointerToConcrete(T) {
|
|
for i, n := 0, mset.Len(); i < n; i++ {
|
|
result = append(result, mset.At(i))
|
|
}
|
|
} else {
|
|
// T is some other concrete type.
|
|
// Report methods of T and *T, preferring those of T.
|
|
pmset := msets.MethodSet(types.NewPointer(T))
|
|
for i, n := 0, pmset.Len(); i < n; i++ {
|
|
meth := pmset.At(i)
|
|
if m := mset.Lookup(meth.Obj().Pkg(), meth.Obj().Name()); m != nil {
|
|
meth = m
|
|
}
|
|
result = append(result, meth)
|
|
}
|
|
|
|
}
|
|
return result
|
|
}
|