Skip to content

Commit e9a412d

Browse files
committed
pkg: swap go/build for go/packages in gen.go
This is the first step towards using go/types to load type information such as constant values and function signatures without handling ASTs. No changes in the generated output. Signed-off-by: Daniel Martí <[email protected]> Change-Id: Ie28990b225c6cf5c39bb06da76686837d02c5113 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/557327 TryBot-Result: CUEcueckoo <[email protected]> Reviewed-by: Roger Peppe <[email protected]>
1 parent bf3ac20 commit e9a412d

File tree

1 file changed

+35
-18
lines changed

1 file changed

+35
-18
lines changed

pkg/gen.go

+35-18
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import (
2929
"flag"
3030
"fmt"
3131
"go/ast"
32-
gobuild "go/build"
3332
"go/constant"
3433
"go/format"
3534
"go/parser"
@@ -43,6 +42,8 @@ import (
4342
"strings"
4443
"text/template"
4544

45+
"golang.org/x/tools/go/packages"
46+
4647
"cuelang.org/go/cue"
4748
"cuelang.org/go/cue/build"
4849
"cuelang.org/go/cue/errors"
@@ -56,8 +57,6 @@ const genFile = "pkg.go"
5657
//go:embed packages.txt
5758
var packagesStr string
5859

59-
var packages = strings.Fields(packagesStr)
60-
6160
type headerParams struct {
6261
GoPkg string
6362
CUEPkg string
@@ -89,19 +88,35 @@ var _ = adt.TopKind // in case the adt package isn't used
8988
{{end}}
9089
`))
9190

91+
const pkgParent = "cuelang.org/go/pkg"
92+
9293
func main() {
9394
flag.Parse()
9495
log.SetFlags(log.Lshortfile)
9596
log.SetOutput(os.Stdout)
9697

97-
for _, pkg := range packages {
98+
var packagesList []string
99+
for _, pkg := range strings.Fields(packagesStr) {
98100
if pkg == "path" {
99101
// TODO remove this special case. Currently the path
100102
// pkg.go file cannot be generated automatically but that
101103
// will be possible when we can attach arbitrary signatures
102104
// to builtin functions.
103105
continue
104106
}
107+
packagesList = append(packagesList, path.Join(pkgParent, pkg))
108+
}
109+
110+
cfg := &packages.Config{Mode: packages.NeedName | packages.NeedFiles}
111+
pkgs, err := packages.Load(cfg, packagesList...)
112+
if err != nil {
113+
fmt.Fprintf(os.Stderr, "load: %v\n", err)
114+
os.Exit(1)
115+
}
116+
if packages.PrintErrors(pkgs) > 0 {
117+
os.Exit(1)
118+
}
119+
for _, pkg := range pkgs {
105120
if err := generate(pkg); err != nil {
106121
log.Fatalf("%s: %v", pkg, err)
107122
}
@@ -116,32 +131,32 @@ type generator struct {
116131
first bool
117132
}
118133

119-
func generate(cuePkgPath string) error {
120-
goPkgPath := path.Join("cuelang.org/go/pkg", cuePkgPath)
121-
pkg, err := gobuild.Import(goPkgPath, "", 0)
122-
if err != nil {
123-
return err
124-
}
125-
134+
func generate(pkg *packages.Package) error {
135+
// go/packages supports multiple build systems, including some which don't keep
136+
// a Go package entirely within a single directory.
137+
// However, we know for certain that CUE uses modules, so it is the case here.
138+
// We can figure out the directory from the first Go file.
139+
pkgDir := filepath.Dir(pkg.GoFiles[0])
140+
cuePkg := strings.TrimPrefix(pkg.PkgPath, pkgParent+"/")
126141
g := generator{
127-
dir: pkg.Dir,
128-
cuePkgPath: cuePkgPath,
142+
dir: pkgDir,
143+
cuePkgPath: cuePkg,
129144
w: &bytes.Buffer{},
130145
fset: token.NewFileSet(),
131146
}
132147

133148
params := headerParams{
134149
GoPkg: pkg.Name,
135-
CUEPkg: cuePkgPath,
150+
CUEPkg: cuePkg,
136151
}
137152
// As a special case, the "tool" package cannot be imported from CUE.
138153
skipRegister := params.CUEPkg == "tool"
139154
if skipRegister {
140155
params.CUEPkg = ""
141156
}
142157

143-
if doc, err := os.ReadFile(filepath.Join(pkg.Dir, "doc.txt")); err == nil {
144-
defs, err := os.ReadFile(filepath.Join(pkg.Dir, pkg.Name+".cue"))
158+
if doc, err := os.ReadFile(filepath.Join(pkgDir, "doc.txt")); err == nil {
159+
defs, err := os.ReadFile(filepath.Join(pkgDir, pkg.Name+".cue"))
145160
if err != nil {
146161
return err
147162
}
@@ -164,7 +179,9 @@ func generate(cuePkgPath string) error {
164179
if filename == genFile {
165180
continue
166181
}
167-
g.processGo(filepath.Join(pkg.Dir, filename))
182+
if err := g.processGo(filename); err != nil {
183+
return err
184+
}
168185
}
169186
fmt.Fprintf(g.w, "},\n")
170187
if err := g.processCUE(); err != nil {
@@ -178,7 +195,7 @@ func generate(cuePkgPath string) error {
178195
b = g.w.Bytes() // write the unformatted source
179196
}
180197

181-
filename := filepath.Join(pkg.Dir, genFile)
198+
filename := filepath.Join(pkgDir, genFile)
182199

183200
if err := os.WriteFile(filename, b, 0666); err != nil {
184201
return err

0 commit comments

Comments
 (0)