From bdcbf1942a3833c5533aa9cfcd87c8a75c1bfa20 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 28 Jul 2009 16:38:59 -0700 Subject: Intersperse comments nicely when printing an AST. gofmt formatted source code looks pretty good already; with a bit more fine-tuning it should be great. printer.go: - Implemented comment intersperse algorithm. The approach is a result of many trial-and-error experiments but at this point reasonably simple and open to arbitrary fine-tuning. parser.go: - Simplified handling of lead and line comments (formerly called leading and trailing comments). - Use a comments list instead of an array (I may change this back - this is not obviously better and uses more space). doc.go: - Remove comments from AST nodes that have been 'consumed' in the documentation to avoid duplicate printing of them. Allows for better control of what is printed w/o use of printing control flags (which are hard to use and not fine-grained enough). Corresponding adjustments to various clients of these files. R=rsc DELTA=478 (275 added, 108 deleted, 95 changed) OCL=32185 CL=32380 --- src/pkg/go/doc/doc.go | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'src/pkg/go/doc/doc.go') diff --git a/src/pkg/go/doc/doc.go b/src/pkg/go/doc/doc.go index 860d6d54c..167535323 100644 --- a/src/pkg/go/doc/doc.go +++ b/src/pkg/go/doc/doc.go @@ -27,6 +27,11 @@ type typeDoc struct { // DocReader accumulates documentation for a single package. +// It modifies the AST: Comments (declaration documentation) +// that have been collected by the DocReader are set to nil +// in the respective AST nodes so that they are not printed +// twice (once when printing the documentation and once when +// printing the corresponding AST node). // type DocReader struct { name string; // package name @@ -151,8 +156,8 @@ func (doc *DocReader) addDecl(decl ast.Decl) { // 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}); + doc.addType(&ast.GenDecl{d.Doc, d.Pos(), token.TYPE, noPos, []ast.Spec{spec}, noPos}); + // A new GenDecl node is created, no need to nil out d.Doc. } case token.VAR: // variables are always handled as a group @@ -197,7 +202,8 @@ func (doc *DocReader) AddFile(src *ast.File) { // add package documentation // TODO(gri) what to do if there are multiple files? if src.Doc != nil { - doc.doc = src.Doc + doc.doc = src.Doc; + src.Doc = nil; // doc consumed - remove from ast.File node } // add all declarations @@ -206,7 +212,7 @@ func (doc *DocReader) AddFile(src *ast.File) { } // collect BUG(...) comments - for _, c := range src.Comments { + for c := src.Comments; c != nil; c = c.Next { text := c.List[0].Text; cstr := string(text); if m := bug_markers.Execute(cstr); len(m) > 0 { @@ -215,10 +221,11 @@ func (doc *DocReader) AddFile(src *ast.File) { // non-empty BUG comment; collect comment without BUG prefix list := copyCommentList(c.List); list[0].Text = text[m[1] : len(text)]; - doc.bugs.Push(&ast.CommentGroup{list, c.EndLine}); + doc.bugs.Push(&ast.CommentGroup{list, nil}); } } } + src.Comments = nil; // consumed unassociated comments - remove from ast.File node } // ---------------------------------------------------------------------------- @@ -282,6 +289,7 @@ func makeValueDocs(v *vector.Vector) []*ValueDoc { for i := range d { decl := v.At(i).(*ast.GenDecl); d[i] = &ValueDoc{astComment(decl.Doc), decl, i}; + decl.Doc = nil; // doc consumed - removed from AST } sort.Sort(sortValueDoc(d)); return d; @@ -310,6 +318,7 @@ func makeFuncDocs(m map[string] *ast.FuncDecl) []*FuncDoc { for _, f := range m { doc := new(FuncDoc); doc.Doc = astComment(f.Doc); + f.Doc = nil; // doc consumed - remove from ast.FuncDecl node if f.Recv != nil { doc.Recv = f.Recv.Type; } @@ -359,10 +368,12 @@ func makeTypeDocs(m map[string] *typeDoc) []*TypeDoc { typespec := old.decl.Specs[0].(*ast.TypeSpec); t := new(TypeDoc); doc := typespec.Doc; + typespec.Doc = nil; // doc consumed - remove from ast.TypeSpec node if doc == nil { // no doc associated with the spec, use the declaration doc, if any doc = old.decl.Doc; } + old.decl.Doc = nil; // doc consumed - remove from ast.Decl node t.Doc = astComment(doc); t.Type = typespec; t.Factories = makeFuncDocs(old.factories); -- cgit v1.2.3