diff --git a/internal/filetypes/filetypes.go b/internal/filetypes/filetypes.go index 99a1272812b..f9b64841fec 100644 --- a/internal/filetypes/filetypes.go +++ b/internal/filetypes/filetypes.go @@ -78,7 +78,7 @@ func FromFile(b *build.File, mode Mode) (*FileInfo, error) { // isolation without interference from evaluating these files. if mode == Input && b.Encoding == build.CUE && - b.Form == build.Schema && + b.Form == "" && b.Interpretation == "" { return &FileInfo{ File: b, @@ -175,11 +175,9 @@ func ParseArgs(args []string) (files []*build.File, err error) { if !fileVal.Exists() { if len(a) == 1 && strings.HasSuffix(a[0], ".cue") { // Handle majority case. - files = append(files, &build.File{ - Filename: a[0], - Encoding: build.CUE, - Form: build.Schema, - }) + f := *fileForCUE + f.Filename = a[0] + files = append(files, &f) hasFiles = true continue } @@ -269,15 +267,20 @@ func ParseFileAndType(file, scope string, mode Mode) (*build.File, error) { // Quickly discard files which we aren't interested in. // These cases are very common when loading `./...` in a large repository. typesInit() - if scope == "" { + if scope == "" && file != "-" { ext := fileExt(file) - if file == "-" { - // not handled here - } else if ext == "" { + if ext == "" { return nil, errors.Newf(token.NoPos, "no encoding specified for file %q", file) - } else if !knownExtensions[ext] { + } + f, ok := fileForExt[ext] + if !ok { return nil, errors.Newf(token.NoPos, "unknown file extension %s", ext) } + if mode == Input { + f1 := *f + f1.Filename = file + return &f1, nil + } } modeVal, fileVal, err := parseType(scope, mode) if err != nil { diff --git a/internal/filetypes/types.cue b/internal/filetypes/types.cue index 9ebd42397b7..ff5eaa93ba3 100644 --- a/internal/filetypes/types.cue +++ b/internal/filetypes/types.cue @@ -3,7 +3,7 @@ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software @@ -56,15 +56,15 @@ package build attributes?: bool // include/allow attributes } -// knownExtensions derives all the known file extensions -// from those that are mentioned in modes, -// allowing us to quickly discard files with unknown extensions. -knownExtensions: { - for mode in modes - for ext, _ in mode.extensions { - (ext): true - } -} +// fileForExtVanilla holds the extensions supported in +// input mode with scope="" - the most common form +// of file type to evaluate. +// +// It's also used as a source of truth for all known file +// extensions as all modes define attributes for +// all file extensions. If that ever changed, we'd need +// to change this. +fileForExtVanilla: modes.input.extensions // modes sets defaults for different operational modes. modes: [string]: { diff --git a/internal/filetypes/types.go b/internal/filetypes/types.go index 21981b7eb04..22d390c6bea 100644 --- a/internal/filetypes/types.go +++ b/internal/filetypes/types.go @@ -16,17 +16,22 @@ package filetypes import ( _ "embed" + "fmt" "sync" "cuelang.org/go/cue" + "cuelang.org/go/cue/build" "cuelang.org/go/cue/cuecontext" ) //go:embed types.cue var typesCUE string -var typesValue cue.Value -var knownExtensions map[string]bool +var ( + typesValue cue.Value + fileForExt map[string]*build.File + fileForCUE *build.File +) var typesInit = sync.OnceFunc(func() { ctx := cuecontext.New() @@ -34,7 +39,15 @@ var typesInit = sync.OnceFunc(func() { if err := typesValue.Err(); err != nil { panic(err) } - if err := typesValue.LookupPath(cue.MakePath(cue.Str("knownExtensions"))).Decode(&knownExtensions); err != nil { + // Reading a file in input mode with a non-explicit scope is a very + // common operation, so cache the build.File value for all + // the known file extensions. + if err := typesValue.LookupPath(cue.MakePath(cue.Str("fileForExtVanilla"))).Decode(&fileForExt); err != nil { panic(err) } + fileForCUE = fileForExt[".cue"] + // Check invariants assumed by FromFile + if fileForCUE.Form != "" || fileForCUE.Interpretation != "" || fileForCUE.Encoding != build.CUE { + panic(fmt.Errorf("unexpected value for CUE file type: %#v", fileForCUE)) + } })