From: Robert Griesemer Date: Sat, 20 Feb 2010 01:03:09 +0000 (-0800) Subject: go/ast: use a slice instead of a linked list for the list of comments X-Git-Tag: weekly.2010-02-23~25 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=989ef60509e13234a10f75ad8e61ce7f76307176;p=gostls13.git go/ast: use a slice instead of a linked list for the list of comments (this will simplify some further changes) removed several TODOs R=rsc CC=golang-dev https://golang.org/cl/216059 --- diff --git a/src/pkg/go/ast/ast.go b/src/pkg/go/ast/ast.go index 0976a5ec78..4773efaf64 100644 --- a/src/pkg/go/ast/ast.go +++ b/src/pkg/go/ast/ast.go @@ -75,7 +75,6 @@ type Comment struct { // type CommentGroup struct { List []*Comment - Next *CommentGroup // next comment group in source order } @@ -695,12 +694,16 @@ func (d *FuncDecl) declNode() {} // A File node represents a Go source file. // +// The Comments list contains all comments in the source file in order of +// appearance, including the comments that are pointed to from other nodes +// via Doc and Comment fields. +// type File struct { - Doc *CommentGroup // associated documentation; or nil - token.Position // position of "package" keyword - Name *Ident // package name - Decls []Decl // top-level declarations - Comments *CommentGroup // list of all comments in the source file + Doc *CommentGroup // associated documentation; or nil + token.Position // position of "package" keyword + Name *Ident // package name + Decls []Decl // top-level declarations + Comments []*CommentGroup // list of all comments in the source file } diff --git a/src/pkg/go/ast/filter.go b/src/pkg/go/ast/filter.go index 3dc87696a6..4f1f0ab477 100644 --- a/src/pkg/go/ast/filter.go +++ b/src/pkg/go/ast/filter.go @@ -107,8 +107,6 @@ func filterSpec(spec Spec) bool { return true } case *TypeSpec: - // TODO(gri) consider stripping forward declarations - // of structs, interfaces, functions, and methods if s.Name.IsExported() { filterType(s.Type) return true @@ -136,9 +134,6 @@ func filterDecl(decl Decl) bool { d.Specs = filterSpecList(d.Specs) return len(d.Specs) > 0 case *FuncDecl: - // TODO consider removing function declaration altogether if - // forward declaration (i.e., if d.Body == nil) because - // in that case the actual declaration will come later. d.Body = nil // strip body return d.Name.IsExported() } @@ -230,7 +225,7 @@ func MergePackageFiles(pkg *Package) *File { } } } - doc = &CommentGroup{list, nil} + doc = &CommentGroup{list} } // Collect declarations from all package files. @@ -246,8 +241,6 @@ func MergePackageFiles(pkg *Package) *File { } } - // TODO(gri) Should collect comments as well. For that the comment - // list should be changed back into a []*CommentGroup, - // otherwise need to modify the existing linked list. + // TODO(gri) Should collect comments as well. return &File{doc, noPos, NewIdent(pkg.Name), decls, nil} } diff --git a/src/pkg/go/ast/walk.go b/src/pkg/go/ast/walk.go index ee2c89cbe1..641aae0c91 100644 --- a/src/pkg/go/ast/walk.go +++ b/src/pkg/go/ast/walk.go @@ -64,11 +64,6 @@ func Walk(v Visitor, node interface{}) { for _, c := range n.List { Walk(v, c) } - // TODO(gri): Keep comments in a list/vector instead - // of linking them via Next. Following next will lead - // to multiple visits and potentially n^2 behavior - // since Doc and Comments fields point into the global - // comments list. case *Field: walkCommentGroup(v, n.Doc) @@ -283,7 +278,9 @@ func Walk(v Visitor, node interface{}) { walkCommentGroup(v, n.Doc) walkIdent(v, n.Name) Walk(v, n.Decls) - walkCommentGroup(v, n.Comments) + for _, g := range n.Comments { + Walk(v, g) + } case *Package: for _, f := range n.Files { diff --git a/src/pkg/go/doc/doc.go b/src/pkg/go/doc/doc.go index 9bd1158de7..ba7cf45c35 100644 --- a/src/pkg/go/doc/doc.go +++ b/src/pkg/go/doc/doc.go @@ -272,7 +272,7 @@ func (doc *docReader) addFile(src *ast.File) { } // collect BUG(...) comments - for c := src.Comments; c != nil; c = c.Next { + for _, c := range src.Comments { text := c.List[0].Text cstr := string(text) if m := bug_markers.ExecuteString(cstr); len(m) > 0 { @@ -281,7 +281,7 @@ 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]:] - doc.bugs.Push(&ast.CommentGroup{list, nil}) + doc.bugs.Push(&ast.CommentGroup{list}) } } } diff --git a/src/pkg/go/parser/parser.go b/src/pkg/go/parser/parser.go index 15bb2d6125..22e14167a0 100644 --- a/src/pkg/go/parser/parser.go +++ b/src/pkg/go/parser/parser.go @@ -45,7 +45,7 @@ type parser struct { indent uint // indentation used for tracing output // Comments - comments *ast.CommentGroup // list of collected comments + comments vector.Vector // list of *CommentGroup lastComment *ast.CommentGroup // last comment in the comments list leadComment *ast.CommentGroup // the last lead comment lineComment *ast.CommentGroup // the last line comment @@ -183,12 +183,8 @@ func (p *parser) consumeCommentGroup() int { } // add comment group to the comments list - g := &ast.CommentGroup{group, nil} - if p.lastComment != nil { - p.lastComment.Next = g - } else { - p.comments = g - } + g := &ast.CommentGroup{group} + p.comments.Push(g) p.lastComment = g return endline @@ -2095,5 +2091,11 @@ func (p *parser) parseFile() *ast.File { } } - return &ast.File{doc, pos, ident, decls, p.comments} + // convert comments list + comments := make([]*ast.CommentGroup, len(p.comments)) + for i, x := range p.comments { + comments[i] = x.(*ast.CommentGroup) + } + + return &ast.File{doc, pos, ident, decls, comments} } diff --git a/src/pkg/go/printer/nodes.go b/src/pkg/go/printer/nodes.go index 9a7519ba35..32864bd159 100644 --- a/src/pkg/go/printer/nodes.go +++ b/src/pkg/go/printer/nodes.go @@ -88,7 +88,7 @@ func (p *printer) commentList(list []*ast.Comment) { // Print a lead comment followed by a newline. func (p *printer) leadComment(d *ast.CommentGroup) { // Ignore the comment if we have comments interspersed (p.comment != nil). - if p.comment == nil && d != nil { + if p.comments == nil && d != nil { p.commentList(d.List) p.print(newline) } @@ -100,7 +100,7 @@ func (p *printer) leadComment(d *ast.CommentGroup) { // the comment may be a //-style comment. func (p *printer) lineComment(d *ast.CommentGroup) { // Ignore the comment if we have comments interspersed (p.comment != nil). - if p.comment == nil && d != nil { + if p.comments == nil && d != nil { p.print(vtab) p.commentList(d.List) } @@ -152,8 +152,8 @@ const ( // Remove this after transitioning to new semicolon syntax and // some reasonable grace period (12/11/09). func (p *printer) beforeComment(pos token.Position) token.Position { - if p.comment != nil { - p := p.comment.List[0].Position + if p.cindex < len(p.comments) { + p := p.comments[p.cindex].List[0].Position if !pos.IsValid() || pos.Offset > p.Offset { return p } @@ -852,7 +852,7 @@ func (p *printer) moveCommentsAfter(pos token.Position) { // Remove this after transitioning to new semicolon // syntax and some reasonable grace period (12/11/09). if p.commentBefore(pos) { - p.comment.List[0].Position = pos + p.comments[p.cindex].List[0].Position = pos } } diff --git a/src/pkg/go/printer/printer.go b/src/pkg/go/printer/printer.go index 90f3e20161..7321c0da1f 100644 --- a/src/pkg/go/printer/printer.go +++ b/src/pkg/go/printer/printer.go @@ -88,8 +88,9 @@ type printer struct { // HTML support lastTaggedLine int // last line for which a line tag was written - // The list of comments; or nil. - comment *ast.CommentGroup + // The list of all source comments, in order of appearance. + comments []*ast.CommentGroup // may be nil + cindex int // current comment index } @@ -624,8 +625,8 @@ func (p *printer) intersperseComments(next token.Position, isKeyword bool) { isFirst := true needsLinebreak := false var last *ast.Comment - for ; p.commentBefore(next); p.comment = p.comment.Next { - for _, c := range p.comment.List { + for ; p.commentBefore(next); p.cindex++ { + for _, c := range p.comments[p.cindex].List { p.writeCommentPrefix(c.Pos(), next, isFirst, isKeyword) isFirst = false p.writeComment(c) @@ -792,7 +793,7 @@ func (p *printer) print(args ...) { // before the next position in the source code. // func (p *printer) commentBefore(next token.Position) bool { - return p.comment != nil && p.comment.List[0].Pos().Offset < next.Offset + return p.cindex < len(p.comments) && p.comments[p.cindex].List[0].Pos().Offset < next.Offset } @@ -981,7 +982,7 @@ func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) { case ast.Decl: p.decl(n, atTop, ignoreMultiLine) case *ast.File: - p.comment = n.Comments + p.comments = n.Comments p.file(n) default: p.errors <- os.NewError(fmt.Sprintf("printer.Fprint: unsupported node type %T", n))