diff options
author | Robert Griesemer <gri@golang.org> | 2009-07-09 16:38:17 -0700 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2009-07-09 16:38:17 -0700 |
commit | 8a473aa878a6a51b3af23fd3f11d3eaa09d1c681 (patch) | |
tree | fd865f0c1add970888e0aa3b5c650605cc14171b /src/pkg/go/doc/doc.go | |
parent | 5214e17d0bdbd365b14ae1aba8805fb761452ed6 (diff) | |
download | golang-8a473aa878a6a51b3af23fd3f11d3eaa09d1c681.tar.gz |
Show BUG comments in godoc:
ast.go:
- rename Comments -> CommentGroup (less confusion)
- change all comments/docs to be *CommentGroup
filter.go:
- do not remove unassociated comments from program as part
of export filtering (they are needed by doc.go for BUG comments)
scanner.go:
- exclude '\n' from //-style comments
parser.go:
- rewrote collection of comments: now all collected comments
are *ast.CommentGroups
- clarified distinction between leading and trailing comments
- fixed a bug in comment collection (parseGenDecl);
corresponding test case is in printer/testdata
- extra documentation
doc.go:
- collect BUG comments
- corresponding fix for parser bug in comment collection
comment.go:
- simplified regex
printer.go:
- adjust comment printing to new representation
printer_test.go, testdata/*:
- enable printing of doc comments
- extended tests
package.html, package.txt:
- added Bugs section
gofmt:
- enable printing of doc comments
R=rsc
DELTA=339 (126 added, 38 deleted, 175 changed)
OCL=31403
CL=31416
Diffstat (limited to 'src/pkg/go/doc/doc.go')
-rw-r--r-- | src/pkg/go/doc/doc.go | 97 |
1 files changed, 77 insertions, 20 deletions
diff --git a/src/pkg/go/doc/doc.go b/src/pkg/go/doc/doc.go index bbae654a5..3f90397da 100644 --- a/src/pkg/go/doc/doc.go +++ b/src/pkg/go/doc/doc.go @@ -31,11 +31,12 @@ type typeDoc struct { type DocReader struct { name string; // package name path string; // import path - doc ast.Comments; // package documentation, if any + doc *ast.CommentGroup; // package documentation, if any consts *vector.Vector; // list of *ast.GenDecl types map[string] *typeDoc; vars *vector.Vector; // list of *ast.GenDecl funcs map[string] *ast.FuncDecl; + bugs *vector.Vector; // list of *ast.CommentGroup } @@ -49,6 +50,7 @@ func (doc *DocReader) Init(pkg, imp string) { doc.types = make(map[string] *typeDoc); doc.vars = vector.New(0); doc.funcs = make(map[string] *ast.FuncDecl); + doc.bugs = vector.New(0); } @@ -131,11 +133,18 @@ func (doc *DocReader) addDecl(decl ast.Decl) { case token.TYPE: // types are handled individually var noPos token.Position; - for i, spec := range d.Specs { + for _, spec := range d.Specs { // make a (fake) GenDecl node for this TypeSpec // (we need to do this here - as opposed to just // for printing - so we don't lose the GenDecl // documentation) + // + // TODO(gri): Consider just collecting the TypeSpec + // node (and copy in the GenDecl.doc if there is no + // doc in the TypeSpec - this is currently done in + // makeTypeDocs below). Simpler data structures, but + // would lose GenDecl documentation if the TypeSpec + // has documentation as well. s := spec.(*ast.TypeSpec); doc.addType(&ast.GenDecl{d.Doc, d.Pos(), token.TYPE, noPos, []ast.Spec{s}, noPos}); } @@ -150,10 +159,25 @@ func (doc *DocReader) addDecl(decl ast.Decl) { } +func copyCommentList(list []*ast.Comment) []*ast.Comment { + copy := make([]*ast.Comment, len(list)); + for i, c := range list { + copy[i] = c; + } + return copy; +} + + +var bug_markers *regexp.Regexp; // Regexp constructor needs threads - cannot use init expression + // AddProgram adds the AST for a source file to the DocReader. // Adding the same AST multiple times is a no-op. // func (doc *DocReader) AddProgram(prog *ast.Program) { + if bug_markers == nil { + bug_markers = makeRex("^/[/*][ \t]*BUG(\\([^)]*\\))?:?[ \t]*"); + } + if doc.name != prog.Name.Value { panic("package names don't match"); } @@ -165,22 +189,39 @@ func (doc *DocReader) AddProgram(prog *ast.Program) { } // add all declarations - for i, decl := range prog.Decls { + for _, decl := range prog.Decls { doc.addDecl(decl); } + + // collect BUG(...) comments + for _, c := range prog.Comments { + text := c.List[0].Text; + m := bug_markers.Execute(string(text)); + if len(m) > 0 { + // found a BUG comment; + // push a copy of the comment w/o the BUG prefix + list := copyCommentList(c.List); + list[0].Text = text[m[1] : len(text)]; + doc.bugs.Push(&ast.CommentGroup{list, c.EndLine}); + } + } } // ---------------------------------------------------------------------------- // Conversion to external representation -func astComment(comments ast.Comments) string { - text := make([]string, len(comments)); - for i, c := range comments { - text[i] = string(c.Text); +func astComment(comment *ast.CommentGroup) string { + if comment != nil { + text := make([]string, len(comment.List)); + for i, c := range comment.List { + text[i] = string(c.Text); + } + return commentText(text); } - return commentText(text); + return ""; } + // ValueDoc is the documentation for a group of declared // values, either vars or consts. // @@ -252,7 +293,7 @@ func (p sortFuncDoc) Less(i, j int) bool { return p[i].Name < p[j].Name; } func makeFuncDocs(m map[string] *ast.FuncDecl) []*FuncDoc { d := make([]*FuncDoc, len(m)); i := 0; - for name, f := range m { + for _, f := range m { doc := new(FuncDoc); doc.Doc = astComment(f.Doc); if f.Recv != nil { @@ -296,14 +337,19 @@ func (p sortTypeDoc) Less(i, j int) bool { // NOTE(rsc): This would appear not to be correct for type ( ) // blocks, but the doc extractor above has split them into -// individual statements. +// individual declarations. func makeTypeDocs(m map[string] *typeDoc) []*TypeDoc { d := make([]*TypeDoc, len(m)); i := 0; - for name, old := range m { + for _, old := range m { typespec := old.decl.Specs[0].(*ast.TypeSpec); t := new(TypeDoc); - t.Doc = astComment(typespec.Doc); + doc := typespec.Doc; + if doc == nil { + // no doc associated with the spec, use the declaration doc, if any + doc = old.decl.Doc; + } + t.Doc = astComment(doc); t.Type = typespec; t.Factories = makeFuncDocs(old.factories); t.Methods = makeFuncDocs(old.methods); @@ -317,6 +363,15 @@ func makeTypeDocs(m map[string] *typeDoc) []*TypeDoc { } +func makeBugDocs(v *vector.Vector) []string { + d := make([]string, v.Len()); + for i := 0; i < v.Len(); i++ { + d[i] = astComment(v.At(i).(*ast.CommentGroup)); + } + return d; +} + + // PackageDoc is the documentation for an entire package. // type PackageDoc struct { @@ -327,6 +382,7 @@ type PackageDoc struct { Types []*TypeDoc; Vars []*ValueDoc; Funcs []*FuncDoc; + Bugs []string; } @@ -341,6 +397,7 @@ func (doc *DocReader) Doc() *PackageDoc { p.Vars = makeValueDocs(doc.vars); p.Types = makeTypeDocs(doc.types); p.Funcs = makeFuncDocs(doc.funcs); + p.Bugs = makeBugDocs(doc.bugs); return p; } @@ -351,8 +408,8 @@ func (doc *DocReader) Doc() *PackageDoc { // Does s look like a regular expression? func isRegexp(s string) bool { metachars := ".(|)*+?^$[]"; - for i, c := range s { - for j, m := range metachars { + for _, c := range s { + for _, m := range metachars { if c == m { return true } @@ -363,7 +420,7 @@ func isRegexp(s string) bool { func match(s string, a []string) bool { - for i, t := range a { + for _, t := range a { if isRegexp(t) { if matched, err := regexp.Match(t, s); matched { return true; @@ -378,10 +435,10 @@ func match(s string, a []string) bool { func matchDecl(d *ast.GenDecl, names []string) bool { - for i, d := range d.Specs { + for _, d := range d.Specs { switch v := d.(type) { case *ast.ValueSpec: - for j, name := range v.Names { + for _, name := range v.Names { if match(name.Value, names) { return true; } @@ -398,7 +455,7 @@ func matchDecl(d *ast.GenDecl, names []string) bool { func filterValueDocs(a []*ValueDoc, names []string) []*ValueDoc { w := 0; - for i, vd := range a { + for _, vd := range a { if matchDecl(vd.Decl, names) { a[w] = vd; w++; @@ -410,7 +467,7 @@ func filterValueDocs(a []*ValueDoc, names []string) []*ValueDoc { func filterFuncDocs(a []*FuncDoc, names []string) []*FuncDoc { w := 0; - for i, fd := range a { + for _, fd := range a { if match(fd.Name, names) { a[w] = fd; w++; @@ -422,7 +479,7 @@ func filterFuncDocs(a []*FuncDoc, names []string) []*FuncDoc { func filterTypeDocs(a []*TypeDoc, names []string) []*TypeDoc { w := 0; - for i, td := range a { + for _, td := range a { match := false; if matchDecl(td.Decl, names) { match = true; |