go.tools/godoc: sanitize function signatures for object index
Fixes golang/go#7703. LGTM=bgarcia R=bgarcia CC=golang-codereviews https://golang.org/cl/84410045
This commit is contained in:
parent
93a9176852
commit
42a4cd3392
|
@ -76,6 +76,7 @@ func (p *Presentation) initFuncMap() {
|
||||||
"node_html": p.node_htmlFunc,
|
"node_html": p.node_htmlFunc,
|
||||||
"comment_html": comment_htmlFunc,
|
"comment_html": comment_htmlFunc,
|
||||||
"comment_text": comment_textFunc,
|
"comment_text": comment_textFunc,
|
||||||
|
"sanitize": sanitizeFunc,
|
||||||
|
|
||||||
// support for URL attributes
|
// support for URL attributes
|
||||||
"pkgLink": pkgLinkFunc,
|
"pkgLink": pkgLinkFunc,
|
||||||
|
@ -228,6 +229,50 @@ func comment_textFunc(comment, indent, preIndent string) string {
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sanitizeFunc sanitizes the argument src by replacing newlines with
|
||||||
|
// blanks, removing extra blanks, and by removing trailing whitespace
|
||||||
|
// and commas before closing parentheses.
|
||||||
|
func sanitizeFunc(src string) string {
|
||||||
|
buf := make([]byte, len(src))
|
||||||
|
j := 0 // buf index
|
||||||
|
comma := -1 // comma index if >= 0
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
ch := src[i]
|
||||||
|
switch ch {
|
||||||
|
case '\t', '\n', ' ':
|
||||||
|
// ignore whitespace at the beginning, after a blank, or after opening parentheses
|
||||||
|
if j == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if p := buf[j-1]; p == ' ' || p == '(' || p == '{' || p == '[' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// replace all whitespace with blanks
|
||||||
|
ch = ' '
|
||||||
|
case ',':
|
||||||
|
comma = j
|
||||||
|
case ')', '}', ']':
|
||||||
|
// remove any trailing comma
|
||||||
|
if comma >= 0 {
|
||||||
|
j = comma
|
||||||
|
}
|
||||||
|
// remove any trailing whitespace
|
||||||
|
if j > 0 && buf[j-1] == ' ' {
|
||||||
|
j--
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
comma = -1
|
||||||
|
}
|
||||||
|
buf[j] = ch
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
// remove trailing blank, if any
|
||||||
|
if j > 0 && buf[j-1] == ' ' {
|
||||||
|
j--
|
||||||
|
}
|
||||||
|
return string(buf[:j])
|
||||||
|
}
|
||||||
|
|
||||||
type PageInfo struct {
|
type PageInfo struct {
|
||||||
Dirname string // directory containing the package
|
Dirname string // directory containing the package
|
||||||
Err error // error or nil
|
Err error // error or nil
|
||||||
|
@ -576,7 +621,8 @@ func (p *Presentation) writeNode(w io.Writer, fset *token.FileSet, x interface{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteNote writes x to w.
|
// WriteNode writes x to w.
|
||||||
|
// TODO(bgarcia) Is this method needed? It's just a wrapper for p.writeNode.
|
||||||
func (p *Presentation) WriteNode(w io.Writer, fset *token.FileSet, x interface{}) {
|
func (p *Presentation) WriteNode(w io.Writer, fset *token.FileSet, x interface{}) {
|
||||||
p.writeNode(w, fset, x)
|
p.writeNode(w, fset, x)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,8 @@ func TestPkgLinkFunc(t *testing.T) {
|
||||||
{"/src/pkg/fmt", "pkg/fmt"},
|
{"/src/pkg/fmt", "pkg/fmt"},
|
||||||
{"/fmt", "pkg/fmt"},
|
{"/fmt", "pkg/fmt"},
|
||||||
} {
|
} {
|
||||||
if got, want := pkgLinkFunc(tc.path), tc.want; got != want {
|
if got := pkgLinkFunc(tc.path); got != tc.want {
|
||||||
t.Errorf("pkgLinkFunc(%v) = %v; want %v", tc.path, got, want)
|
t.Errorf("pkgLinkFunc(%v) = %v; want %v", tc.path, got, tc.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,8 @@ func TestSrcPosLinkFunc(t *testing.T) {
|
||||||
{"fmt/print.go", 0, 0, 0, "/src/pkg/fmt/print.go"},
|
{"fmt/print.go", 0, 0, 0, "/src/pkg/fmt/print.go"},
|
||||||
{"fmt/print.go", 0, 1, 5, "/src/pkg/fmt/print.go?s=1:5#L1"},
|
{"fmt/print.go", 0, 1, 5, "/src/pkg/fmt/print.go?s=1:5#L1"},
|
||||||
} {
|
} {
|
||||||
if got, want := srcPosLinkFunc(tc.src, tc.line, tc.low, tc.high), tc.want; got != want {
|
if got := srcPosLinkFunc(tc.src, tc.line, tc.low, tc.high); got != tc.want {
|
||||||
t.Errorf("srcLinkFunc(%v, %v, %v, %v) = %v; want %v", tc.src, tc.line, tc.low, tc.high, got, want)
|
t.Errorf("srcLinkFunc(%v, %v, %v, %v) = %v; want %v", tc.src, tc.line, tc.low, tc.high, got, tc.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,8 +54,8 @@ func TestSrcLinkFunc(t *testing.T) {
|
||||||
{"/fmt/print.go", "/src/pkg/fmt/print.go"},
|
{"/fmt/print.go", "/src/pkg/fmt/print.go"},
|
||||||
{"fmt/print.go", "/src/pkg/fmt/print.go"},
|
{"fmt/print.go", "/src/pkg/fmt/print.go"},
|
||||||
} {
|
} {
|
||||||
if got, want := srcLinkFunc(tc.src), tc.want; got != want {
|
if got := srcLinkFunc(tc.src); got != tc.want {
|
||||||
t.Errorf("srcLinkFunc(%v) = %v; want %v", tc.src, got, want)
|
t.Errorf("srcLinkFunc(%v) = %v; want %v", tc.src, got, tc.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,8 +72,8 @@ func TestQueryLinkFunc(t *testing.T) {
|
||||||
{"src/pkg/fmt/print.go", "EOF", 33, "/src/pkg/fmt/print.go?h=EOF#L33"},
|
{"src/pkg/fmt/print.go", "EOF", 33, "/src/pkg/fmt/print.go?h=EOF#L33"},
|
||||||
{"src/pkg/fmt/print.go", "a%3f+%26b", 1, "/src/pkg/fmt/print.go?h=a%3f+%26b#L1"},
|
{"src/pkg/fmt/print.go", "a%3f+%26b", 1, "/src/pkg/fmt/print.go?h=a%3f+%26b#L1"},
|
||||||
} {
|
} {
|
||||||
if got, want := queryLinkFunc(tc.src, tc.query, tc.line), tc.want; got != want {
|
if got := queryLinkFunc(tc.src, tc.query, tc.line); got != tc.want {
|
||||||
t.Errorf("queryLinkFunc(%v, %v, %v) = %v; want %v", tc.src, tc.query, tc.line, got, want)
|
t.Errorf("queryLinkFunc(%v, %v, %v) = %v; want %v", tc.src, tc.query, tc.line, got, tc.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,8 +87,30 @@ func TestDocLinkFunc(t *testing.T) {
|
||||||
{"/src/pkg/fmt", "Sprintf", "/pkg/fmt/#Sprintf"},
|
{"/src/pkg/fmt", "Sprintf", "/pkg/fmt/#Sprintf"},
|
||||||
{"/src/pkg/fmt", "EOF", "/pkg/fmt/#EOF"},
|
{"/src/pkg/fmt", "EOF", "/pkg/fmt/#EOF"},
|
||||||
} {
|
} {
|
||||||
if got, want := docLinkFunc(tc.src, tc.ident), tc.want; got != want {
|
if got := docLinkFunc(tc.src, tc.ident); got != tc.want {
|
||||||
t.Errorf("docLinkFunc(%v, %v) = %v; want %v", tc.src, tc.ident, got, want)
|
t.Errorf("docLinkFunc(%v, %v) = %v; want %v", tc.src, tc.ident, got, tc.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSanitizeFunc(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
src string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{},
|
||||||
|
{"foo", "foo"},
|
||||||
|
{"func f()", "func f()"},
|
||||||
|
{"func f(a int,)", "func f(a int)"},
|
||||||
|
{"func f(a int,\n)", "func f(a int)"},
|
||||||
|
{"func f(\n\ta int,\n\tb int,\n\tc int,\n)", "func f(a int, b int, c int)"},
|
||||||
|
{" ( a, b, c ) ", "(a, b, c)"},
|
||||||
|
{"( a, b, c int, foo bar , )", "(a, b, c int, foo bar)"},
|
||||||
|
{"{ a, b}", "{a, b}"},
|
||||||
|
{"[ a, b]", "[a, b]"},
|
||||||
|
} {
|
||||||
|
if got := sanitizeFunc(tc.src); got != tc.want {
|
||||||
|
t.Errorf("sanitizeFunc(%v) = %v; want %v", tc.src, got, tc.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,18 +65,18 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
{{range .Funcs}}
|
{{range .Funcs}}
|
||||||
{{$name_html := html .Name}}
|
{{$name_html := html .Name}}
|
||||||
<dd><a href="#{{$name_html}}">{{node_html $ .Decl false}}</a></dd>
|
<dd><a href="#{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{range .Types}}
|
{{range .Types}}
|
||||||
{{$tname_html := html .Name}}
|
{{$tname_html := html .Name}}
|
||||||
<dd><a href="#{{$tname_html}}">type {{$tname_html}}</a></dd>
|
<dd><a href="#{{$tname_html}}">type {{$tname_html}}</a></dd>
|
||||||
{{range .Funcs}}
|
{{range .Funcs}}
|
||||||
{{$name_html := html .Name}}
|
{{$name_html := html .Name}}
|
||||||
<dd> <a href="#{{$name_html}}">{{node_html $ .Decl false}}</a></dd>
|
<dd> <a href="#{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{range .Methods}}
|
{{range .Methods}}
|
||||||
{{$name_html := html .Name}}
|
{{$name_html := html .Name}}
|
||||||
<dd> <a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl false}}</a></dd>
|
<dd> <a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if $.Notes}}
|
{{if $.Notes}}
|
||||||
|
|
|
@ -1292,18 +1292,18 @@ function cgAddChild(tree, ul, cgn) {
|
||||||
{{end}}
|
{{end}}
|
||||||
{{range .Funcs}}
|
{{range .Funcs}}
|
||||||
{{$name_html := html .Name}}
|
{{$name_html := html .Name}}
|
||||||
<dd><a href="#{{$name_html}}">{{node_html $ .Decl false}}</a></dd>
|
<dd><a href="#{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{range .Types}}
|
{{range .Types}}
|
||||||
{{$tname_html := html .Name}}
|
{{$tname_html := html .Name}}
|
||||||
<dd><a href="#{{$tname_html}}">type {{$tname_html}}</a></dd>
|
<dd><a href="#{{$tname_html}}">type {{$tname_html}}</a></dd>
|
||||||
{{range .Funcs}}
|
{{range .Funcs}}
|
||||||
{{$name_html := html .Name}}
|
{{$name_html := html .Name}}
|
||||||
<dd> <a href="#{{$name_html}}">{{node_html $ .Decl false}}</a></dd>
|
<dd> <a href="#{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{range .Methods}}
|
{{range .Methods}}
|
||||||
{{$name_html := html .Name}}
|
{{$name_html := html .Name}}
|
||||||
<dd> <a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl false}}</a></dd>
|
<dd> <a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if $.Notes}}
|
{{if $.Notes}}
|
||||||
|
|
Loading…
Reference in New Issue