go.tools/godoc: ignore //line comments in source code

Per suggestion from Gary Burd.

Fixes golang/go#5247.

LGTM=rsc
R=bgarcia, rsc
CC=golang-codereviews
https://golang.org/cl/84050044
This commit is contained in:
Robert Griesemer 2014-04-03 13:12:54 -07:00
parent bf97d00464
commit 55ea531257
2 changed files with 49 additions and 1 deletions

View File

@ -169,6 +169,14 @@ func First() {
func Second() {
}
`,
"src/pkg/gen/gen.go": `// Package gen
package gen
//line notgen.go:3
// F doc //line 1 should appear
// line 2 should appear
func F()
//line foo.go:100`, // no newline on end to check corner cases!
"src/pkg/vet/vet.go": `// Package vet
package vet
`,
@ -230,6 +238,11 @@ package main
args: []string{"src/foo", "Second"},
exp: "// Second function is second.\nfunc Second() {\n}",
},
{
desc: "package w. //line comments",
args: []string{"gen", "F"},
exp: "PACKAGE \nfunc F()\n F doc //line 1 should appear line 2 should appear\n",
},
{
desc: "command",
args: []string{"go"},
@ -259,7 +272,7 @@ package main
w := new(bytes.Buffer)
err := CommandLine(w, fs, p, tc.args)
if got, want := w.String(), tc.exp; got != want || tc.err == (err == nil) {
t.Errorf("%s: CommandLine(%v) = %q,%v; want %q,%v",
t.Errorf("%s: CommandLine(%v) = %q (%v); want %q (%v)",
tc.desc, tc.args, got, err, want, tc.err)
}
}

View File

@ -8,6 +8,7 @@
package godoc
import (
"bytes"
"go/ast"
"go/parser"
"go/token"
@ -16,11 +17,45 @@ import (
"code.google.com/p/go.tools/godoc/vfs"
)
var linePrefix = []byte("//line ")
// This function replaces source lines starting with "//line " with a blank line.
// It does this irrespective of whether the line is truly a line comment or not;
// e.g., the line may be inside a string, or a /*-style comment; however that is
// rather unlikely (proper testing would require a full Go scan which we want to
// avoid for performance).
func replaceLinePrefixCommentsWithBlankLine(src []byte) {
for {
i := bytes.Index(src, linePrefix)
if i < 0 {
break // we're done
}
// 0 <= i && i+len(linePrefix) <= len(src)
if i == 0 || src[i-1] == '\n' {
// at beginning of line: blank out line
for i < len(src) && src[i] != '\n' {
src[i] = ' '
i++
}
} else {
// not at beginning of line: skip over prefix
i += len(linePrefix)
}
// i <= len(src)
src = src[i:]
}
}
func (c *Corpus) parseFile(fset *token.FileSet, filename string, mode parser.Mode) (*ast.File, error) {
src, err := vfs.ReadFile(c.fs, filename)
if err != nil {
return nil, err
}
// Temporary ad-hoc fix for issue 5247.
// TODO(gri) Remove this in favor of a better fix, eventually (see issue 7702).
replaceLinePrefixCommentsWithBlankLine(src)
return parser.ParseFile(fset, filename, src, mode)
}