This is new API, but we can still tweak it until it is released,
probably in Go 1.1.
I am curious about the future uses of the CommentMap. It seems like it
does not have enough information to be used in gofmt, for example. What
are the plans?
http://codereview.appspot.com/6281044/diff/15002/src/pkg/go/ast/commentmap.go
File src/pkg/go/ast/commentmap.go (right):
http://codereview.appspot.com/6281044/diff/15002/src/pkg/go/ast/commentmap.go#newcode12
src/pkg/go/ast/commentmap.go:12: // byPos implements sort.Interface
These are fairly formulaic. I'd drop them, or change them to say
something specific to the type, like
// byPos implements sort.Interface, comparing by source position.
http://codereview.appspot.com/6281044/diff/15002/src/pkg/go/ast/commentmap.go#newcode19
src/pkg/go/ast/commentmap.go:19: // SortComments sorts the list of
comment groups in source order.
Does this need to be public API?
http://codereview.appspot.com/6281044/diff/15002/src/pkg/go/ast/commentmap.go#newcode30
src/pkg/go/ast/commentmap.go:30: // A CommentMap maps AST nodes to the
list of comment groups
Please use singular where possible, to be more precise:
// A CommentMap maps an AST node to a list of comment groups
// associated with it.
I would also appreciate a sentence or two more explaining the
relationship, like "These are the comments preceding that statement." or
something. I don't understand how the map distinguishes a preceding
block comment from a following end-of-line comment.
http://codereview.appspot.com/6281044/diff/15002/src/pkg/go/ast/commentmap.go#newcode58
src/pkg/go/ast/commentmap.go:58: list := make([]Node, 0, 64) // 64 seems
like a good initial capacity
Any particular reason? I would think append would be in charge of that
decision.
http://codereview.appspot.com/6281044/diff/15002/src/pkg/go/ast/commentmap.go#newcode65
src/pkg/go/ast/commentmap.go:65: panic("internal error: should not be
reachable")
Is there harm in returning false? Might avoid panics later.
http://codereview.appspot.com/6281044/diff/15002/src/pkg/go/ast/commentmap.go#newcode131
src/pkg/go/ast/commentmap.go:131: // and the comments are taken from
f.Comments.
Like above, it would be nice to make clear how block comments vs
end-of-line comments are handled.
http://codereview.appspot.com/6281044/diff/15002/src/pkg/go/ast/commentmap.go#newcode141
src/pkg/go/ast/commentmap.go:141: clist := make([]*CommentGroup,
len(f.Comments))
maybe comments and nodes instead of clist and nlist? The types make
clear that they are lists.
http://codereview.appspot.com/6281044/diff/15002/src/pkg/go/ast/commentmap.go#newcode147
src/pkg/go/ast/commentmap.go:147: // create node list in lexcial order
lexical
http://codereview.appspot.com/6281044/diff/15002/src/pkg/go/ast/commentmap.go#newcode152
src/pkg/go/ast/commentmap.go:152: var p Node // previous
node
var ( ...?
http://codereview.appspot.com/6281044/diff/15002/src/pkg/go/ast/commentmap.go#newcode181
src/pkg/go/ast/commentmap.go:181: // TODO(gri) try to simplify the logic
below
One way to simplify would be to pop nodes from the stack until the top
of stack holds a node that cannot match the comment, and then use the
node before that (the one most recently popped). I wonder if the stack
is even necessary. Perhaps it would work to do the depth-first pre-order
traversal here instead:
comments = ... sorted by order
Inspect(f, func(n Node) bool {
switch n.(type) {
case nil, *CommentGroup, *Comment:
return false
}
for len(comments) > 0 && comments[0].Line <= n.Line {
cmap[n] = append(cmap[n], comments[0])
comments = comments[1:]
}
})
This would have different semantics than the current code but would be
very easy to explain: each comment is assigned to the first node that
starts on the same line or a later line in the source.
// comment1
if x { // comment2
} // comment3
// comment4
f()
in this case comment1 and comment2 would be assigned to the if, while
comment3 and comment4 would be associated with f. I think the comment3
and comment4 cases are pretty rare.
http://codereview.appspot.com/6281044/diff/15002/src/pkg/go/ast/commentmap.go#newcode234
src/pkg/go/ast/commentmap.go:234: // create a map of all nodes
I wonder if it would save noticeable memory to copy cmap instead:
missing := map[Node]bool{}
for n := range cmap { missing[n] = true }
Inspect( ... delete(missing, n) ... )
... if missing[n] { delete(cmap, n) } ...
http://codereview.appspot.com/6281044/diff/15002/src/pkg/go/ast/commentmap.go#newcode248
src/pkg/go/ast/commentmap.go:248: // List returns the list of comment
groups given a comment map.
s/given a/in the/
http://codereview.appspot.com/6281044/diff/15002/src/pkg/go/ast/commentmap_test.go
File src/pkg/go/ast/commentmap_test.go (right):
http://codereview.appspot.com/6281044/diff/15002/src/pkg/go/ast/commentmap_test.go#newcode5
src/pkg/go/ast/commentmap_test.go:5: // To avoid cyclic dependencies,
this file is in a separate package.
This confused me on first reading.
"avoid a cyclic dependency with go/parser"?
http://codereview.appspot.com/6281044/