func (v *declVisitor) Visit(n ast.Node) ast.Visitor { switch n := n.(type) { case *ast.TypeSpec: v.addAnnoation(anchorAnnotation, "", n.Pos()) name := n.Name.Name switch n := n.Type.(type) { case *ast.InterfaceType: for _, f := range n.Methods.List { for _, n := range f.Names { v.addAnnoation(anchorAnnotation, name, n.Pos()) } ast.Walk(v, f.Type) } case *ast.StructType: for _, f := range n.Fields.List { for _, n := range f.Names { v.addAnnoation(anchorAnnotation, name, n.Pos()) } ast.Walk(v, f.Type) } default: ast.Walk(v, n) } case *ast.FuncDecl: if n.Recv == nil { v.addAnnoation(anchorAnnotation, "", n.Name.NamePos) } else { ast.Walk(v, n.Recv) if len(n.Recv.List) > 0 { typ := n.Recv.List[0].Type if se, ok := typ.(*ast.StarExpr); ok { typ = se.X } if id, ok := typ.(*ast.Ident); ok { v.addAnnoation(anchorAnnotation, id.Name, n.Name.NamePos) } } } ast.Walk(v, n.Type) case *ast.Field: for _ = range n.Names { v.ignoreName() } ast.Walk(v, n.Type) case *ast.ValueSpec: for _, n := range n.Names { v.addAnnoation(anchorAnnotation, "", n.Pos()) } if n.Type != nil { ast.Walk(v, n.Type) } for _, x := range n.Values { ast.Walk(v, x) } case *ast.Ident: switch { case n.Obj == nil && predeclared[n.Name] != notPredeclared: v.addAnnoation(linkAnnotation, "builtin", 0) case n.Obj != nil && ast.IsExported(n.Name): v.addAnnoation(linkAnnotation, "", 0) default: v.ignoreName() } case *ast.SelectorExpr: if x, _ := n.X.(*ast.Ident); x != nil { if obj := x.Obj; obj != nil && obj.Kind == ast.Pkg { if spec, _ := obj.Decl.(*ast.ImportSpec); spec != nil { if path, err := strconv.Unquote(spec.Path.Value); err == nil { if path == "C" { v.ignoreName() v.ignoreName() } else if n.Sel.Pos()-x.End() == 1 { v.addAnnoation(startLinkAnnotation, path, 0) v.addAnnoation(endLinkAnnotation, path, 0) } else { v.addAnnoation(packageLinkAnnoation, path, 0) v.addAnnoation(linkAnnotation, path, 0) } return nil } } } } ast.Walk(v, n.X) v.ignoreName() case *ast.BasicLit: if n.Kind == token.STRING && len(n.Value) > 128 { v.comments = append(v.comments, &ast.CommentGroup{List: []*ast.Comment{{ Slash: n.Pos(), Text: fmt.Sprintf("/* %d byte string literal not displayed */", len(n.Value)), }}}) n.Value = `""` } else { return v } case *ast.CompositeLit: if len(n.Elts) > 100 { if n.Type != nil { ast.Walk(v, n.Type) } v.comments = append(v.comments, &ast.CommentGroup{List: []*ast.Comment{{ Slash: n.Lbrace, Text: fmt.Sprintf("/* %d elements not displayed */", len(n.Elts)), }}}) n.Elts = n.Elts[:0] } else { return v } default: return v } return nil }