]> Cypherpunks repositories - gostls13.git/commitdiff
go/ast: use a slice instead of a linked list for the list of comments
authorRobert Griesemer <gri@golang.org>
Sat, 20 Feb 2010 01:03:09 +0000 (17:03 -0800)
committerRobert Griesemer <gri@golang.org>
Sat, 20 Feb 2010 01:03:09 +0000 (17:03 -0800)
        (this will simplify some further changes)
removed several TODOs

R=rsc
CC=golang-dev
https://golang.org/cl/216059

src/pkg/go/ast/ast.go
src/pkg/go/ast/filter.go
src/pkg/go/ast/walk.go
src/pkg/go/doc/doc.go
src/pkg/go/parser/parser.go
src/pkg/go/printer/nodes.go
src/pkg/go/printer/printer.go

index 0976a5ec7856098c1d1408db46624a6e34befac1..4773efaf6490dfcdd50bd87f1bfa0c4af898b104 100644 (file)
@@ -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
 }
 
 
index 3dc87696a682c8894017517bd1cbcd944183631d..4f1f0ab477f791bdd191d50dce920a798c657a67 100644 (file)
@@ -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}
 }
index ee2c89cbe111b928a868d5e86d8192bc83f87e3d..641aae0c9109072c4b1d7b585c26132e836a5354 100644 (file)
@@ -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 {
index 9bd1158de72a9d6bdb1b4c4192705ce748410416..ba7cf45c35fbb3d3eaa7e5474a0cdbdb5fa22f2e 100644 (file)
@@ -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})
                        }
                }
        }
index 15bb2d61251b484d8b2645934d9fd00ed41df8fe..22e14167a08c722add027e7946d2b5d037c429c4 100644 (file)
@@ -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}
 }
index 9a7519ba35b678921e68295068786e2a6f4ba34e..32864bd159875bcb4f3c0442bf590cd33d8f7e99 100644 (file)
@@ -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
        }
 }
 
index 90f3e20161a0ecf263d2c06f7514738a4fc0a701..7321c0da1fd2ed757f4c57febbfd42cdeec8c100 100644 (file)
@@ -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))