type Path … const opType … const opElem … const opKey … const opParams … const opResults … const opUnderlying … const opTypeParam … const opRecvTypeParam … const opConstraint … const opRhs … const opAt … const opField … const opMethod … const opObj … // For is equivalent to new(Encoder).For(obj). // // It may be more efficient to reuse a single Encoder across several calls. func For(obj types.Object) (Path, error) { … } type Encoder … // For returns the path to an object relative to its package, // or an error if the object is not accessible from the package's Scope. // // The For function guarantees to return a path only for the following objects: // - package-level types // - exported package-level non-types // - methods // - parameter and result variables // - struct fields // These objects are sufficient to define the API of their package. // The objects described by a package's export data are drawn from this set. // // The set of objects accessible from a package's Scope depends on // whether the package was produced by type-checking syntax, or // reading export data; the latter may have a smaller Scope since // export data trims objects that are not reachable from an exported // declaration. For example, the For function will return a path for // an exported method of an unexported type that is not reachable // from any public declaration; this path will cause the Object // function to fail if called on a package loaded from export data. // TODO(adonovan): is this a bug or feature? Should this package // compute accessibility in the same way? // // For does not return a path for predeclared names, imported package // names, local names, and unexported package-level names (except // types). // // Example: given this definition, // // package p // // type T interface { // f() (a string, b struct{ X int }) // } // // For(X) would return a path that denotes the following sequence of operations: // // p.Scope().Lookup("T") (TypeName T) // .Type().Underlying().Method(0). (method Func f) // .Type().Results().At(1) (field Var b) // .Type().Field(0) (field Var X) // // where p is the package (*types.Package) to which X belongs. func (enc *Encoder) For(obj types.Object) (Path, error) { … } func appendOpArg(path []byte, op byte, arg int) []byte { … } // concreteMethod returns the path for meth, which must have a non-nil receiver. // The second return value indicates success and may be false if the method is // an interface method or if it is an instantiated method. // // This function is just an optimization that avoids the general scope walking // approach. You are expected to fall back to the general approach if this // function fails. func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) { … } // find finds obj within type T, returning the path to it, or nil if not found. // // The seen map is used to short circuit cycles through type parameters. If // nil, it will be allocated as necessary. func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]bool) []byte { … } func findTypeParam(obj types.Object, list *types.TypeParamList, path []byte, op byte, seen map[*types.TypeName]bool) []byte { … } // Object returns the object denoted by path p within the package pkg. func Object(pkg *types.Package, p Path) (types.Object, error) { … } // scopeObjects is a memoization of scope objects. // Callers must not modify the result. func (enc *Encoder) scopeObjects(scope *types.Scope) []types.Object { … }