diff --git a/internal/gengapic/auxiliary.go b/internal/gengapic/auxiliary.go index ac966522..6a151d32 100644 --- a/internal/gengapic/auxiliary.go +++ b/internal/gengapic/auxiliary.go @@ -79,6 +79,10 @@ func (g *generator) genAuxFile() error { g.commit(filepath.Join(g.opts.outDir, "auxiliary.go"), g.opts.pkgName) g.reset() + g.genIteratorsGo123() + g.commitWithBuildTag(filepath.Join(g.opts.outDir, "auxiliary_go123.go"), g.opts.pkgName, "go1.23") + g.reset() + return nil } @@ -123,6 +127,17 @@ func (g *generator) genIterators() error { return nil } +// genIteratorsGo123 generates adapters for Go iterators for Go versions 1.23+. +func (g *generator) genIteratorsGo123() { + // Sort iterators to generate by type name to + // avoid spurious regenerations created by + // non-deterministic map traversal order. + iters := sortIteratorMap(g.aux.iters) + for _, iter := range iters { + g.pagingIterGo123(iter) + } +} + // sortIteratorMap sorts the map of iterator types by iterTypeName. func sortIteratorMap(m map[string]*iterType) []*iterType { var iters []*iterType diff --git a/internal/gengapic/auxiliary_test.go b/internal/gengapic/auxiliary_test.go index 44d2ee7e..2ee7198d 100644 --- a/internal/gengapic/auxiliary_test.go +++ b/internal/gengapic/auxiliary_test.go @@ -444,6 +444,22 @@ func TestGenIterators(t *testing.T) { } txtdiff.Diff(t, g.pt.String(), filepath.Join("testdata", "gen_iterators.want")) + + g.reset() + + wantImports = map[pbinfo.ImportSpec]bool{ + {Path: "iter"}: true, + {Path: "github.com/googleapis/gax-go/v2/iterator"}: true, + {Name: "examplepb", Path: "cloud.google.com/go/example/apiv1/examplepb"}: true, + } + + g.genIteratorsGo123() + + if diff := cmp.Diff(g.imports, wantImports); diff != "" { + t.Errorf("imports got(-),want(+):\n%s", diff) + } + + txtdiff.Diff(t, g.pt.String(), filepath.Join("testdata", "gen_iterators_go123.want")) } func TestSortOperationWrapperMap(t *testing.T) { diff --git a/internal/gengapic/generator.go b/internal/gengapic/generator.go index 945ae976..9d90711c 100644 --- a/internal/gengapic/generator.go +++ b/internal/gengapic/generator.go @@ -221,12 +221,19 @@ func (g *generator) printf(s string, a ...interface{}) { // TODO(chrisdsmith): Add generator_test.go with TestCommit +func (g *generator) commit(fileName, pkgName string) int { + return g.commitWithBuildTag(fileName, pkgName, "") +} + // commit adds header, etc to current pt and returns the line length of the // final file output. -func (g *generator) commit(fileName, pkgName string) int { +func (g *generator) commitWithBuildTag(fileName, pkgName, buildTag string) int { var header strings.Builder fmt.Fprintf(&header, license.Apache, time.Now().Year()) header.WriteString(g.headerComments.String() + "\n") + if buildTag != "" { + fmt.Fprintf(&header, "//go:build %s\n\n", buildTag) + } fmt.Fprintf(&header, "package %s\n\n", pkgName) var imps []pbinfo.ImportSpec diff --git a/internal/gengapic/paging.go b/internal/gengapic/paging.go index df5f3d85..3a89f2b8 100644 --- a/internal/gengapic/paging.go +++ b/internal/gengapic/paging.go @@ -389,3 +389,20 @@ func (g *generator) pagingIter(pt *iterType) { g.imports[spec] = true } } + +func (g *generator) pagingIterGo123(pt *iterType) { + p := g.printf + + p("// All returns an iterator. If an error is returned by the iterator, the") + p("// iterator will stop after that iteration.") + p("func (it *%s) All() iter.Seq2[%s, error] {", pt.iterTypeName, pt.elemTypeName) + p(" return iterator.RangeAdapter[%s](it.Next)", pt.elemTypeName) + p("}") + p("") + + g.imports[pbinfo.ImportSpec{Path: "iter"}] = true + g.imports[pbinfo.ImportSpec{Path: "github.com/googleapis/gax-go/v2/iterator"}] = true + for _, spec := range pt.elemImports { + g.imports[spec] = true + } +} diff --git a/internal/gengapic/testdata/gen_iterators_go123.want b/internal/gengapic/testdata/gen_iterators_go123.want new file mode 100644 index 00000000..d9310a7c --- /dev/null +++ b/internal/gengapic/testdata/gen_iterators_go123.want @@ -0,0 +1,6 @@ +// All returns an iterator. If an error is returned by the iterator, the +// iterator will stop after that iteration. +func (it *FooIterator) All() iter.Seq2[*examplepb.Foo, error] { + return iterator.RangeAdapter[*examplepb.Foo](it.Next) +} +