type IfaceStubInfo … // GetIfaceStubInfo determines whether the "missing method error" // can be used to deduced what the concrete and interface types are. // // TODO(adonovan): this function (and its following 5 helpers) tries // to deduce a pair of (concrete, interface) types that are related by // an assignment, either explicitly or through a return statement or // function call. This is essentially what the refactor/satisfy does, // more generally. Refactor to share logic, after auditing 'satisfy' // for safety on ill-typed code. func GetIfaceStubInfo(fset *token.FileSet, info *types.Info, path []ast.Node, pos token.Pos) *IfaceStubInfo { … } // Emit writes to out the missing methods of si.Concrete required for it to implement si.Interface func (si *IfaceStubInfo) Emit(out *bytes.Buffer, qual types.Qualifier) error { … } // fromCallExpr tries to find an *ast.CallExpr's function declaration and // analyzes a function call's signature against the passed in parameter to deduce // the concrete and interface types. func fromCallExpr(fset *token.FileSet, info *types.Info, pos token.Pos, call *ast.CallExpr) *IfaceStubInfo { … } // fromReturnStmt analyzes a "return" statement to extract // a concrete type that is trying to be returned as an interface type. // // For example, func() io.Writer { return myType{} } // would return StubIfaceInfo with the interface being io.Writer and the concrete type being myType{}. func fromReturnStmt(fset *token.FileSet, info *types.Info, pos token.Pos, path []ast.Node, ret *ast.ReturnStmt) (*IfaceStubInfo, error) { … } // fromValueSpec returns *StubIfaceInfo from a variable declaration such as // var x io.Writer = &T{} func fromValueSpec(fset *token.FileSet, info *types.Info, spec *ast.ValueSpec, pos token.Pos) *IfaceStubInfo { … } // fromAssignStmt returns *StubIfaceInfo from a variable assignment such as // var x io.Writer // x = &T{} func fromAssignStmt(fset *token.FileSet, info *types.Info, assign *ast.AssignStmt, pos token.Pos) *IfaceStubInfo { … } // ifaceType returns the named interface type to which e refers, if any. func ifaceType(e ast.Expr, info *types.Info) *types.TypeName { … } func ifaceObjFromType(t types.Type) *types.TypeName { … } // concreteType tries to extract the *types.Named that defines // the concrete type given the ast.Expr where the "missing method" // or "conversion" errors happened. If the concrete type is something // that cannot have methods defined on it (such as basic types), this // method will return a nil *types.Named. The second return parameter // is a boolean that indicates whether the concreteType was defined as a // pointer or value. func concreteType(e ast.Expr, info *types.Info) (*types.Named, bool) { … } // enclosingFunction returns the signature and type of the function // enclosing the given position. func enclosingFunction(path []ast.Node, info *types.Info) *ast.FuncType { … }