func (p *printer) funcDecl(d *ast.FuncDecl) { p.setComment(d.Doc) p.print(d.Pos(), token.FUNC, blank) if d.Recv != nil { p.parameters(d.Recv) // method: print receiver p.print(blank) } p.expr(d.Name) p.signature(d.Type.Params, d.Type.Results) p.adjBlock(p.distanceFrom(d.Pos()), vtab, d.Body) }
// set creates the corresponding Func for f and adds it to mset. // If there are multiple f's with the same name, set keeps the first // one with documentation; conflicts are ignored. // func (mset methodSet) set(f *ast.FuncDecl) { name := f.Name.Name if g := mset[name]; g != nil && g.Doc != "" { // A function with the same name has already been registered; // since it has documentation, assume f is simply another // implementation and ignore it. This does not happen if the // caller is using go/build.ScanDir to determine the list of // files implementing a package. return } // function doesn't exist or has no documentation; use f recv := "" if f.Recv != nil { var typ ast.Expr // be careful in case of incorrect ASTs if list := f.Recv.List; len(list) == 1 { typ = list[0].Type } recv = recvString(typ) } mset[name] = &Func{ Doc: f.Doc.Text(), Name: name, Decl: f, Recv: recv, Orig: recv, } f.Doc = nil // doc consumed - remove from AST }
// readFunc processes a func or method declaration. // func (r *reader) readFunc(fun *ast.FuncDecl) { // strip function body fun.Body = nil // associate methods with the receiver type, if any if fun.Recv != nil { // method recvTypeName, imp := baseTypeName(fun.Recv.List[0].Type) if imp { // should not happen (incorrect AST); // don't show this method return } if typ := r.lookupType(recvTypeName); typ != nil { typ.methods.set(fun) } // otherwise ignore the method // TODO(gri): There may be exported methods of non-exported types // that can be called because of exported values (consts, vars, or // function results) of that type. Could determine if that is the // case and then show those methods in an appropriate section. return } // associate factory functions with the first visible result type, if any if fun.Type.Results.NumFields() >= 1 { res := fun.Type.Results.List[0] if len(res.Names) <= 1 { // exactly one (named or anonymous) result associated // with the first type in result signature (there may // be more than one result) if n, imp := baseTypeName(res.Type); !imp && r.isVisible(n) { if typ := r.lookupType(n); typ != nil { // associate function with typ typ.funcs.set(fun) return } } } } // just an ordinary function r.funcs.set(fun) }