diff --git a/godoc/cmdline_test.go b/godoc/cmdline_test.go index f9b8b477..0211d0ed 100644 --- a/godoc/cmdline_test.go +++ b/godoc/cmdline_test.go @@ -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) } } diff --git a/godoc/parser.go b/godoc/parser.go index 4762bef2..6ecad73f 100644 --- a/godoc/parser.go +++ b/godoc/parser.go @@ -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) }