github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/compiler/internal/symbol/symbol.go (about) 1 package symbol 2 3 import ( 4 "go/types" 5 "strings" 6 ) 7 8 // Name uniquely identifies a named symbol within a program. 9 // 10 // This is a logical equivalent of a symbol name used by traditional linkers. 11 // The following properties should hold true: 12 // 13 // - Each named symbol within a program has a unique Name. 14 // - Similarly named methods of different types will have different symbol names. 15 // - The string representation is opaque and should not be attempted to reversed 16 // to a struct form. 17 type Name struct { 18 PkgPath string // Full package import path. 19 Name string // Symbol name. 20 } 21 22 // New constructs SymName for a given named symbol. 23 func New(o types.Object) Name { 24 if fun, ok := o.(*types.Func); ok { 25 sig := fun.Type().(*types.Signature) 26 if recv := sig.Recv(); recv != nil { 27 // Special case: disambiguate names for different types' methods. 28 typ := recv.Type() 29 if ptr, ok := typ.(*types.Pointer); ok { 30 return Name{ 31 PkgPath: o.Pkg().Path(), 32 Name: "(*" + ptr.Elem().(*types.Named).Obj().Name() + ")." + o.Name(), 33 } 34 } 35 return Name{ 36 PkgPath: o.Pkg().Path(), 37 Name: typ.(*types.Named).Obj().Name() + "." + o.Name(), 38 } 39 } 40 } 41 return Name{ 42 PkgPath: o.Pkg().Path(), 43 Name: o.Name(), 44 } 45 } 46 47 func (n Name) String() string { return n.PkgPath + "." + n.Name } 48 49 func (n Name) IsMethod() (recv string, method string, ok bool) { 50 pos := strings.IndexByte(n.Name, '.') 51 if pos == -1 { 52 return 53 } 54 recv, method, ok = n.Name[:pos], n.Name[pos+1:], true 55 size := len(recv) 56 if size > 2 && recv[0] == '(' && recv[size-1] == ')' { 57 recv = recv[1 : size-1] 58 } 59 return 60 }