1
0
mirror of https://github.com/golang/go synced 2024-11-25 16:07:56 -07:00

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
This commit is contained in:
Robert Griesemer 2010-02-19 17:03:09 -08:00
parent aaec61555a
commit 989ef60509
7 changed files with 38 additions and 42 deletions

View File

@ -75,7 +75,6 @@ type Comment struct {
// //
type CommentGroup struct { type CommentGroup struct {
List []*Comment 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. // 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 { type File struct {
Doc *CommentGroup // associated documentation; or nil Doc *CommentGroup // associated documentation; or nil
token.Position // position of "package" keyword token.Position // position of "package" keyword
Name *Ident // package name Name *Ident // package name
Decls []Decl // top-level declarations Decls []Decl // top-level declarations
Comments *CommentGroup // list of all comments in the source file Comments []*CommentGroup // list of all comments in the source file
} }

View File

@ -107,8 +107,6 @@ func filterSpec(spec Spec) bool {
return true return true
} }
case *TypeSpec: case *TypeSpec:
// TODO(gri) consider stripping forward declarations
// of structs, interfaces, functions, and methods
if s.Name.IsExported() { if s.Name.IsExported() {
filterType(s.Type) filterType(s.Type)
return true return true
@ -136,9 +134,6 @@ func filterDecl(decl Decl) bool {
d.Specs = filterSpecList(d.Specs) d.Specs = filterSpecList(d.Specs)
return len(d.Specs) > 0 return len(d.Specs) > 0
case *FuncDecl: 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 d.Body = nil // strip body
return d.Name.IsExported() 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. // 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 // TODO(gri) Should collect comments as well.
// list should be changed back into a []*CommentGroup,
// otherwise need to modify the existing linked list.
return &File{doc, noPos, NewIdent(pkg.Name), decls, nil} return &File{doc, noPos, NewIdent(pkg.Name), decls, nil}
} }

View File

@ -64,11 +64,6 @@ func Walk(v Visitor, node interface{}) {
for _, c := range n.List { for _, c := range n.List {
Walk(v, c) 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: case *Field:
walkCommentGroup(v, n.Doc) walkCommentGroup(v, n.Doc)
@ -283,7 +278,9 @@ func Walk(v Visitor, node interface{}) {
walkCommentGroup(v, n.Doc) walkCommentGroup(v, n.Doc)
walkIdent(v, n.Name) walkIdent(v, n.Name)
Walk(v, n.Decls) Walk(v, n.Decls)
walkCommentGroup(v, n.Comments) for _, g := range n.Comments {
Walk(v, g)
}
case *Package: case *Package:
for _, f := range n.Files { for _, f := range n.Files {

View File

@ -272,7 +272,7 @@ func (doc *docReader) addFile(src *ast.File) {
} }
// collect BUG(...) comments // collect BUG(...) comments
for c := src.Comments; c != nil; c = c.Next { for _, c := range src.Comments {
text := c.List[0].Text text := c.List[0].Text
cstr := string(text) cstr := string(text)
if m := bug_markers.ExecuteString(cstr); len(m) > 0 { 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 // non-empty BUG comment; collect comment without BUG prefix
list := copyCommentList(c.List) list := copyCommentList(c.List)
list[0].Text = text[m[1]:] list[0].Text = text[m[1]:]
doc.bugs.Push(&ast.CommentGroup{list, nil}) doc.bugs.Push(&ast.CommentGroup{list})
} }
} }
} }

View File

@ -45,7 +45,7 @@ type parser struct {
indent uint // indentation used for tracing output indent uint // indentation used for tracing output
// Comments // Comments
comments *ast.CommentGroup // list of collected comments comments vector.Vector // list of *CommentGroup
lastComment *ast.CommentGroup // last comment in the comments list lastComment *ast.CommentGroup // last comment in the comments list
leadComment *ast.CommentGroup // the last lead comment leadComment *ast.CommentGroup // the last lead comment
lineComment *ast.CommentGroup // the last line comment lineComment *ast.CommentGroup // the last line comment
@ -183,12 +183,8 @@ func (p *parser) consumeCommentGroup() int {
} }
// add comment group to the comments list // add comment group to the comments list
g := &ast.CommentGroup{group, nil} g := &ast.CommentGroup{group}
if p.lastComment != nil { p.comments.Push(g)
p.lastComment.Next = g
} else {
p.comments = g
}
p.lastComment = g p.lastComment = g
return endline 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}
} }

View File

@ -88,7 +88,7 @@ func (p *printer) commentList(list []*ast.Comment) {
// Print a lead comment followed by a newline. // Print a lead comment followed by a newline.
func (p *printer) leadComment(d *ast.CommentGroup) { func (p *printer) leadComment(d *ast.CommentGroup) {
// Ignore the comment if we have comments interspersed (p.comment != nil). // 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.commentList(d.List)
p.print(newline) p.print(newline)
} }
@ -100,7 +100,7 @@ func (p *printer) leadComment(d *ast.CommentGroup) {
// the comment may be a //-style comment. // the comment may be a //-style comment.
func (p *printer) lineComment(d *ast.CommentGroup) { func (p *printer) lineComment(d *ast.CommentGroup) {
// Ignore the comment if we have comments interspersed (p.comment != nil). // 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.print(vtab)
p.commentList(d.List) p.commentList(d.List)
} }
@ -152,8 +152,8 @@ const (
// Remove this after transitioning to new semicolon syntax and // Remove this after transitioning to new semicolon syntax and
// some reasonable grace period (12/11/09). // some reasonable grace period (12/11/09).
func (p *printer) beforeComment(pos token.Position) token.Position { func (p *printer) beforeComment(pos token.Position) token.Position {
if p.comment != nil { if p.cindex < len(p.comments) {
p := p.comment.List[0].Position p := p.comments[p.cindex].List[0].Position
if !pos.IsValid() || pos.Offset > p.Offset { if !pos.IsValid() || pos.Offset > p.Offset {
return p return p
} }
@ -852,7 +852,7 @@ func (p *printer) moveCommentsAfter(pos token.Position) {
// Remove this after transitioning to new semicolon // Remove this after transitioning to new semicolon
// syntax and some reasonable grace period (12/11/09). // syntax and some reasonable grace period (12/11/09).
if p.commentBefore(pos) { if p.commentBefore(pos) {
p.comment.List[0].Position = pos p.comments[p.cindex].List[0].Position = pos
} }
} }

View File

@ -88,8 +88,9 @@ type printer struct {
// HTML support // HTML support
lastTaggedLine int // last line for which a line tag was written lastTaggedLine int // last line for which a line tag was written
// The list of comments; or nil. // The list of all source comments, in order of appearance.
comment *ast.CommentGroup 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 isFirst := true
needsLinebreak := false needsLinebreak := false
var last *ast.Comment var last *ast.Comment
for ; p.commentBefore(next); p.comment = p.comment.Next { for ; p.commentBefore(next); p.cindex++ {
for _, c := range p.comment.List { for _, c := range p.comments[p.cindex].List {
p.writeCommentPrefix(c.Pos(), next, isFirst, isKeyword) p.writeCommentPrefix(c.Pos(), next, isFirst, isKeyword)
isFirst = false isFirst = false
p.writeComment(c) p.writeComment(c)
@ -792,7 +793,7 @@ func (p *printer) print(args ...) {
// before the next position in the source code. // before the next position in the source code.
// //
func (p *printer) commentBefore(next token.Position) bool { 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: case ast.Decl:
p.decl(n, atTop, ignoreMultiLine) p.decl(n, atTop, ignoreMultiLine)
case *ast.File: case *ast.File:
p.comment = n.Comments p.comments = n.Comments
p.file(n) p.file(n)
default: default:
p.errors <- os.NewError(fmt.Sprintf("printer.Fprint: unsupported node type %T", n)) p.errors <- os.NewError(fmt.Sprintf("printer.Fprint: unsupported node type %T", n))