// Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build go1.15 // Package pkgsite is not for external use. May change at any time without // warning. // // Copied from // https://github.com/golang/pkgsite/blob/ff1e697b104e751da362159cf6c7743898eea3fe/internal/fetch/dochtml/internal/render/ // and // https://github.com/golang/pkgsite/tree/88f8a28ab2102416529d05d11e8135a43e146d46/internal/fetch/dochtml. package pkgsite import ( "bytes" "fmt" "go/ast" "go/printer" "go/token" "strconv" "strings" ) // PrintType returns a string representation of the decl. func PrintType(fset *token.FileSet, decl ast.Decl) string { v := &declVisitor{} ast.Walk(v, decl) var b bytes.Buffer p := printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 4} p.Fprint(&b, fset, &printer.CommentedNode{Node: decl, Comments: v.Comments}) return b.String() } // declVisitor is used to walk over the AST and trim large string // literals and arrays before package documentation is rendered. // Comments are added to Comments to indicate that a part of the // original code is not displayed. type declVisitor struct { Comments []*ast.CommentGroup } // Visit implements ast.Visitor. func (v *declVisitor) Visit(n ast.Node) ast.Visitor { switch n := n.(type) { 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: stringBasicLitSize(n.Value), }}}) n.Value = `""` } case *ast.CompositeLit: if len(n.Elts) > 100 { 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] } } return v } // stringBasicLitSize computes the number of bytes in the given string basic literal. // // See noder.basicLit and syntax.StringLit cases in cmd/compile/internal/gc/noder.go. func stringBasicLitSize(s string) string { if len(s) > 0 && s[0] == '`' { // strip carriage returns from raw string s = strings.ReplaceAll(s, "\r", "") } u, err := strconv.Unquote(s) if err != nil { return fmt.Sprintf("/* invalid %d byte string literal not displayed */", len(s)) } return fmt.Sprintf("/* %d byte string literal not displayed */", len(u)) }