Skip to content

Commit 14deefa

Browse files
committed
cue/load: move towards unified syntax cache
In order to to fix issue #3177, we need a cache that's shared between the module code in `internal/mod/...` and the `cue/load` package, which means that the syntax cache needs to be pushed down to a lower level in `cue/load` because currently it's based around cue/load-specific abstractions. This CL is an incremental progression towards that goal: it adds a `getCUESyntax` method to the internal filesystem abstraction in `cue/load`, which will become a cache in a subsequent CL. In order to do this, some refactoring was required, namely removal of the `matchFile` function, because that function read data without parsing the CUE, but the parsing and reading operations now need to be implemented by the same operation (the new `getCUESyntax` method). In any case, the `matchFile` function did not really fulfil its original purpose or fit the name any more. Also remove the return value from `fileProcessor.add` while we're refactoring it, because nothing uses it. For #3177. Signed-off-by: Roger Peppe <[email protected]> Change-Id: I1876f22b99a5c611e3d8650d3b7afb8f8e43f202 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1197525 Unity-Result: CUE porcuepine <[email protected]> TryBot-Result: CUEcueckoo <[email protected]> Reviewed-by: Paul Jolly <[email protected]>
1 parent b03789f commit 14deefa

File tree

5 files changed

+108
-114
lines changed

5 files changed

+108
-114
lines changed

cue/load/fs.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@ import (
2727
"time"
2828

2929
"cuelang.org/go/cue/ast"
30+
"cuelang.org/go/cue/build"
3031
"cuelang.org/go/cue/errors"
32+
"cuelang.org/go/cue/parser"
3133
"cuelang.org/go/cue/token"
34+
"cuelang.org/go/internal/cueimports"
3235
"cuelang.org/go/mod/module"
3336
)
3437

@@ -179,6 +182,58 @@ func (fs *fileSystem) getOverlay(path string) *overlayFile {
179182
return nil
180183
}
181184

185+
func (fs *fileSystem) getCUESyntax(fi *build.File) (*ast.File, error) {
186+
switch src := fi.Source.(type) {
187+
case []byte, string:
188+
return parser.ParseFile(fi.Filename, src, parser.ImportsOnly)
189+
case *ast.File:
190+
return src, nil
191+
case nil:
192+
if fi.Filename == "-" {
193+
panic("source unexpectedly not provided for stdin")
194+
}
195+
return fs.readCUE(fi.Filename, true)
196+
}
197+
return nil, errors.Newf(token.NoPos, "unsupported source type %T", fi.Source)
198+
}
199+
200+
func (fs *fileSystem) readCUE(path string, importsOnly bool) (*ast.File, error) {
201+
var parseMode parser.Option
202+
if importsOnly {
203+
parseMode = parser.ImportsOnly
204+
}
205+
var data []byte
206+
if f := fs.getOverlay(path); f != nil {
207+
if f.file != nil {
208+
return f.file, nil
209+
}
210+
if f.isDir {
211+
return nil, fmt.Errorf("%q is a directory", path)
212+
}
213+
data = f.contents
214+
} else {
215+
var err error
216+
f, err := fs.openFile(path)
217+
if err != nil {
218+
return nil, err
219+
}
220+
defer f.Close()
221+
if importsOnly {
222+
data, err = cueimports.Read(f)
223+
} else {
224+
data, err = io.ReadAll(f)
225+
}
226+
if err != nil {
227+
return nil, fmt.Errorf("read %s: %v", path, err)
228+
}
229+
}
230+
pf, err := parser.ParseFile(path, data, parseMode)
231+
if err != nil {
232+
return nil, err
233+
}
234+
return pf, nil
235+
}
236+
182237
func (fs *fileSystem) stat(path string) (iofs.FileInfo, errors.Error) {
183238
path = fs.makeAbs(path)
184239
if fi := fs.getOverlay(path); fi != nil {

cue/load/loader.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ func (c *syntaxCache) getSyntax(bf *build.File) ([]*ast.File, error) {
186186
if ok {
187187
return syntax.files, syntax.err
188188
}
189+
if bf.Encoding != build.CUE {
190+
panic("syntax for non-CUE file")
191+
}
189192
d := encoding.NewDecoder(c.ctx, bf, &c.config)
190193
for ; !d.Done(); d.Next() {
191194
syntax.files = append(syntax.files, d.File())

cue/load/loader_common.go

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525

2626
"cuelang.org/go/cue/build"
2727
"cuelang.org/go/cue/errors"
28-
"cuelang.org/go/cue/parser"
2928
"cuelang.org/go/cue/token"
3029
)
3130

@@ -37,6 +36,15 @@ const (
3736
allowExcludedFiles
3837
)
3938

39+
var errExclude = errors.New("file rejected")
40+
41+
type cueError = errors.Error
42+
type excludeError struct {
43+
cueError
44+
}
45+
46+
func (e excludeError) Is(err error) bool { return err == errExclude }
47+
4048
func rewriteFiles(p *build.Instance, root string, isLocal bool) {
4149
p.Root = root
4250

@@ -145,7 +153,7 @@ func (fp *fileProcessor) finalize(p *build.Instance) errors.Error {
145153
}
146154

147155
// add adds the given file to the appropriate package in fp.
148-
func (fp *fileProcessor) add(root string, file *build.File, mode importMode) (added bool) {
156+
func (fp *fileProcessor) add(root string, file *build.File, mode importMode) {
149157
fullPath := file.Filename
150158
if fullPath != "-" {
151159
if !filepath.IsAbs(fullPath) {
@@ -160,42 +168,46 @@ func (fp *fileProcessor) add(root string, file *build.File, mode importMode) (ad
160168
p := fp.pkg // default package
161169

162170
// badFile := func(p *build.Instance, err errors.Error) bool {
163-
badFile := func(err errors.Error) bool {
171+
badFile := func(err errors.Error) {
164172
fp.err = errors.Append(fp.err, err)
165173
file.ExcludeReason = fp.err
166174
p.InvalidFiles = append(p.InvalidFiles, file)
167-
return true
175+
return
168176
}
169177
if err := setFileSource(fp.c, file); err != nil {
170-
return badFile(errors.Promote(err, ""))
178+
badFile(errors.Promote(err, ""))
179+
return
171180
}
172181

173-
match, data, err := matchFile(fp.c, file, true, mode)
174-
switch {
175-
case match:
176-
177-
case err == nil:
182+
if file.Encoding != build.CUE {
178183
// Not a CUE file.
179184
p.OrphanedFiles = append(p.OrphanedFiles, file)
180-
return false
181-
182-
case !errors.Is(err, errExclude):
183-
return badFile(err)
184-
185-
default:
186-
file.ExcludeReason = err
187-
if file.Interpretation == "" {
188-
p.IgnoredFiles = append(p.IgnoredFiles, file)
189-
} else {
190-
p.OrphanedFiles = append(p.OrphanedFiles, file)
185+
return
186+
}
187+
if (mode & allowExcludedFiles) == 0 {
188+
var badPrefix string
189+
for _, prefix := range []string{".", "_"} {
190+
if strings.HasPrefix(base, prefix) {
191+
badPrefix = prefix
192+
}
193+
}
194+
if badPrefix != "" {
195+
file.ExcludeReason = errors.Newf(token.NoPos, "filename starts with a '%s'", badPrefix)
196+
if file.Interpretation == "" {
197+
p.IgnoredFiles = append(p.IgnoredFiles, file)
198+
} else {
199+
p.OrphanedFiles = append(p.OrphanedFiles, file)
200+
}
201+
return
191202
}
192-
return false
193203
}
194-
195-
pf, perr := parser.ParseFile(fullPath, data, parser.ImportsOnly)
204+
// Note: when path is "-" (stdin), it will already have
205+
// been read and file.Source set to the resulting data
206+
// by setFileSource.
207+
pf, perr := fp.c.fileSystem.getCUESyntax(file)
196208
if perr != nil {
197209
badFile(errors.Promote(perr, "add failed"))
198-
return true
210+
return
199211
}
200212

201213
pkg := pf.PackageName()
@@ -227,7 +239,7 @@ func (fp *fileProcessor) add(root string, file *build.File, mode importMode) (ad
227239
default:
228240
file.ExcludeReason = excludeError{errors.Newf(pos, "no package name")}
229241
p.IgnoredFiles = append(p.IgnoredFiles, file)
230-
return false // don't mark as added
242+
return
231243
}
232244

233245
if !fp.c.AllCUEFiles {
@@ -245,7 +257,7 @@ func (fp *fileProcessor) add(root string, file *build.File, mode importMode) (ad
245257
}
246258
file.ExcludeReason = err
247259
p.IgnoredFiles = append(p.IgnoredFiles, file)
248-
return false
260+
return
249261
}
250262
}
251263

@@ -258,14 +270,15 @@ func (fp *fileProcessor) add(root string, file *build.File, mode importMode) (ad
258270
file.ExcludeReason = excludeError{errors.Newf(pos,
259271
"package is %s, want %s", pkg, p.PkgName)}
260272
p.IgnoredFiles = append(p.IgnoredFiles, file)
261-
return false
273+
return
262274
}
263275
if !fp.allPackages {
264-
return badFile(&MultiplePackageError{
276+
badFile(&MultiplePackageError{
265277
Dir: p.Dir,
266278
Packages: []string{p.PkgName, pkg},
267279
Files: []string{fp.firstFile, base},
268280
})
281+
return
269282
}
270283
}
271284
}
@@ -306,7 +319,6 @@ func (fp *fileProcessor) add(root string, file *build.File, mode importMode) (ad
306319
default:
307320
p.BuildFiles = append(p.BuildFiles, file)
308321
}
309-
return true
310322
}
311323

312324
func cleanImports(m map[string][]token.Pos) ([]string, map[string][]token.Pos) {

cue/load/match.go

Lines changed: 0 additions & 84 deletions
This file was deleted.

cue/load/search.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ import (
2828
"cuelang.org/go/mod/module"
2929
)
3030

31+
// A match represents the result of matching a single package pattern.
32+
type match struct {
33+
Pattern string // the pattern itself
34+
Literal bool // whether it is a literal (no wildcards)
35+
Pkgs []*build.Instance
36+
Err errors.Error
37+
}
38+
3139
// TODO: should be matched from module file only.
3240
// The pattern is either "all" (all packages), "std" (standard packages),
3341
// "cmd" (standard commands), or a path including "...".

0 commit comments

Comments
 (0)