golang.org/x/tools@v0.21.0/go/types/typeutil/ui.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package typeutil 6 7 // This file defines utilities for user interfaces that display types. 8 9 import ( 10 "go/types" 11 12 "golang.org/x/tools/internal/aliases" 13 ) 14 15 // IntuitiveMethodSet returns the intuitive method set of a type T, 16 // which is the set of methods you can call on an addressable value of 17 // that type. 18 // 19 // The result always contains MethodSet(T), and is exactly MethodSet(T) 20 // for interface types and for pointer-to-concrete types. 21 // For all other concrete types T, the result additionally 22 // contains each method belonging to *T if there is no identically 23 // named method on T itself. 24 // 25 // This corresponds to user intuition about method sets; 26 // this function is intended only for user interfaces. 27 // 28 // The order of the result is as for types.MethodSet(T). 29 func IntuitiveMethodSet(T types.Type, msets *MethodSetCache) []*types.Selection { 30 isPointerToConcrete := func(T types.Type) bool { 31 ptr, ok := aliases.Unalias(T).(*types.Pointer) 32 return ok && !types.IsInterface(ptr.Elem()) 33 } 34 35 var result []*types.Selection 36 mset := msets.MethodSet(T) 37 if types.IsInterface(T) || isPointerToConcrete(T) { 38 for i, n := 0, mset.Len(); i < n; i++ { 39 result = append(result, mset.At(i)) 40 } 41 } else { 42 // T is some other concrete type. 43 // Report methods of T and *T, preferring those of T. 44 pmset := msets.MethodSet(types.NewPointer(T)) 45 for i, n := 0, pmset.Len(); i < n; i++ { 46 meth := pmset.At(i) 47 if m := mset.Lookup(meth.Obj().Pkg(), meth.Obj().Name()); m != nil { 48 meth = m 49 } 50 result = append(result, meth) 51 } 52 53 } 54 return result 55 }