1
0
mirror of https://github.com/golang/go synced 2024-11-18 13:04:46 -07:00

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:
Robert Griesemer 2014-04-07 12:54:28 -07:00
parent 93a9176852
commit 42a4cd3392
4 changed files with 85 additions and 17 deletions

View File

@ -76,6 +76,7 @@ func (p *Presentation) initFuncMap() {
"node_html": p.node_htmlFunc,
"comment_html": comment_htmlFunc,
"comment_text": comment_textFunc,
"sanitize": sanitizeFunc,
// support for URL attributes
"pkgLink": pkgLinkFunc,
@ -228,6 +229,50 @@ func comment_textFunc(comment, indent, preIndent string) 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 {
Dirname string // directory containing the package
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{}) {
p.writeNode(w, fset, x)
}

View File

@ -16,8 +16,8 @@ func TestPkgLinkFunc(t *testing.T) {
{"/src/pkg/fmt", "pkg/fmt"},
{"/fmt", "pkg/fmt"},
} {
if got, want := pkgLinkFunc(tc.path), tc.want; got != want {
t.Errorf("pkgLinkFunc(%v) = %v; want %v", tc.path, got, want)
if got := pkgLinkFunc(tc.path); got != tc.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, 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 {
t.Errorf("srcLinkFunc(%v, %v, %v, %v) = %v; want %v", tc.src, tc.line, tc.low, tc.high, 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, 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"},
} {
if got, want := srcLinkFunc(tc.src), tc.want; got != want {
t.Errorf("srcLinkFunc(%v) = %v; want %v", tc.src, got, want)
if got := srcLinkFunc(tc.src); got != tc.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", "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 {
t.Errorf("queryLinkFunc(%v, %v, %v) = %v; want %v", tc.src, tc.query, tc.line, 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, tc.want)
}
}
}
@ -87,8 +87,30 @@ func TestDocLinkFunc(t *testing.T) {
{"/src/pkg/fmt", "Sprintf", "/pkg/fmt/#Sprintf"},
{"/src/pkg/fmt", "EOF", "/pkg/fmt/#EOF"},
} {
if got, want := docLinkFunc(tc.src, tc.ident), tc.want; got != want {
t.Errorf("docLinkFunc(%v, %v) = %v; want %v", tc.src, tc.ident, 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, 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)
}
}
}

View File

@ -65,18 +65,18 @@
{{end}}
{{range .Funcs}}
{{$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}}
{{range .Types}}
{{$tname_html := html .Name}}
<dd><a href="#{{$tname_html}}">type {{$tname_html}}</a></dd>
{{range .Funcs}}
{{$name_html := html .Name}}
<dd>&nbsp; &nbsp; <a href="#{{$name_html}}">{{node_html $ .Decl false}}</a></dd>
<dd>&nbsp; &nbsp; <a href="#{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
{{end}}
{{range .Methods}}
{{$name_html := html .Name}}
<dd>&nbsp; &nbsp; <a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl false}}</a></dd>
<dd>&nbsp; &nbsp; <a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
{{end}}
{{end}}
{{if $.Notes}}

View File

@ -1292,18 +1292,18 @@ function cgAddChild(tree, ul, cgn) {
{{end}}
{{range .Funcs}}
{{$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}}
{{range .Types}}
{{$tname_html := html .Name}}
<dd><a href="#{{$tname_html}}">type {{$tname_html}}</a></dd>
{{range .Funcs}}
{{$name_html := html .Name}}
<dd>&nbsp; &nbsp; <a href="#{{$name_html}}">{{node_html $ .Decl false}}</a></dd>
<dd>&nbsp; &nbsp; <a href="#{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
{{end}}
{{range .Methods}}
{{$name_html := html .Name}}
<dd>&nbsp; &nbsp; <a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl false}}</a></dd>
<dd>&nbsp; &nbsp; <a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
{{end}}
{{end}}
{{if $.Notes}}