Open mvdan opened 1 month ago
Also worth noting that I'm tracking the APIs where we should start using Go func iterators soon here, including ast.File.VisitImports
: https://github.com/cue-lang/cue/issues/2953
I should also note that the iterator being called AllImports
rather than just Imports
is perhaps slightly unfortunate, but we can't possibly make a slow and nice transition where we swap File.Imports
from []*ast.ImportSpec
to iter.Seq[*ImportSpec]
. Iterating via a for loop would work the same on both, but any other use case would be broken.
Currently, a file's imported packages are tracked in two places separately:
1) As a flat list of type
[]*ast.ImportSpec
inast.File.Imports
, used in cases like the loader or compiler, where one just needs to list all the imports to use them.2) As grouped
*ast.ImportDecl
declarations inast.File.Decls
, used to keep track of the original syntax information so thatcue/format
can print the syntax back out as CUE, and full position information is retained.This is inherited from Go's https://pkg.go.dev/go/ast#File. It made sense that Go began with both fields and duplicate data back in the day, because being able to iterate over the flat list of imports is a common need for many syntax tree users, and Go didn't gain iterators until very recently. A method that let you iterate over a flat list of imports would have had to allocate a slice and copy them all in upfront, which isn't great.
The duplicate information is not just wasteful, but also error prone. Take for instance https://review.gerrithub.io/c/cue-lang/cue/+/1198351 -
astutil.Sanitize
updatedDecls
when removing an unused import but notImports
, hence they ended up inconsistent. Printing the CUE viacue/format
would omit the removed import as it usesDecls
, but trying to build the file would fail as the compiler usesImports
.Now we have iterators, so we should replace
ast.File.Imports
with an iterator method. We even have one such method already in https://pkg.go.dev/cuelang.org/go/cue/ast@master#File.VisitImports, althoughfor _, spec := range file.VisitImports {
reads a bit weird, so we might need a new name for it likeAllImports
.I propose the following sequential steps: 1) Add a new
File.AllImports
method following the common iterator signature from https://github.com/golang/go/issues/61897, e.g.func (*File) AllImports() iter.Seq[*ImportSpec]
. 2) RewriteFile.VisitImports
in terms ofFile.AllImports
, and deprecate it in favor of the new func. 3) DeprecateFile.Imports
in favor ofFile.AllImports
. 4) About a year later, removeFile.Imports
.