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  }