Skip to content

proposal: go/ast: add CommentsBetween helper function #75556

Description

@mateusz834

Proposal Details

Working with go/ast and comments is hard (inserting/moving comments), but the current API of go/ast does not even make it easy to inspect comments between ast.Nodes. I have defined and seen some sort of Comments function to solve that. Maybe it would be worth adding it directly into go/ast? Additionally none of these implementations that i have seen use binary search to speed this up (EDIT: gofumpt does), we could do that safely here (CL 704255).

I propose:

// CommentsBetween returns a slice of CommentGroups that fully
// reside between start and end.
//
// The returned slice shares the backing array with f.Comments (after slices.Clip).
func CommentsBetween(f *File, start, end token.Pos) []*CommentGroup

or

// CommentsBetween returns an iterator, that yields all CommentGroups that
// fully reside between start and end.
func CommentsBetween(f *File, start, end token.Pos) iter.Seq[*CommentGroup]

By "fully reside," I mean that if start or end falls in the middle of a CommentGroup, that comment is not included.

The benefit of the first variant is that it makes it easy to check for presence: len(CommentsBetween(f, start, end)) != 0, whereas the iterator variant requires more typing: len(slices.Collect(CommentsBetween(f, start, end)) != 0 and is less performant (allocates).

Some code samples that might benefit from such API:

https://github.com/golang/tools/blob/cb57b4c286444e6dbb13514e73962503f5afcf04/internal/analysisinternal/analysis.go#L618-L637

go/src/go/ast/import.go

Lines 140 to 159 in 7f6ff5e

for i, g := range f.Comments {
if g.End() >= end {
break
}
// g.End() < end
if beg <= g.Pos() {
// comment is within the range [beg, end[ of import declarations
if i < first {
first = i
}
if i > last {
last = i
}
}
}
var comments []*CommentGroup
if last >= 0 {
comments = f.Comments[first : last+1]
}

https://github.com/mvdan/gofumpt/blob/ea1909574445e99958cdcd3416c6bf3a4bb64dfa/format/simplify.go#L161-L166
https://github.com/mvdan/gofumpt/blob/ea1909574445e99958cdcd3416c6bf3a4bb64dfa/format/format.go#L199-L210

Metadata

Metadata

Assignees

No one assigned

    Labels

    LibraryProposalIssues describing a requested change to the Go standard library or x/ libraries, but not to a toolProposal

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions