From fcf330606a202182cba67965a54beb022d222432 Mon Sep 17 00:00:00 2001 From: Roger Peppe Date: Tue, 10 Sep 2024 09:55:11 +0100 Subject: [PATCH] internal/filetypes: simplify MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `stream` attribute is not used or tested for anywhere and is therefore likely incorrect. Remove it: we can always reinstate if it's needed in the future. Also unify `FileInfo` with `File`. This has no direct semantic effect, but means that the two are more closely related, and allows us to add information to `interpretations` that also has an effect in `tagInfo`, something we'll use in a subsequent CL. The latter change does mean that we now get a non-empty `Form` in some cases when it was previously empty but that actually seems more correct: if we're interpreting as JSON Schema, for example, it seems right to treat it as schema not data. Also add some documentation and make `modes.[_].FileInfo` and `modes.[_].Default` into required fields as suggested by the TODO. Also change the tests to use `cue/build` constants, thus giving more confidence that they match the strings used in the CUE. Signed-off-by: Roger Peppe Change-Id: I3a9246a3060837ea03eae6daf3841ae305faa016 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1200923 Reviewed-by: Daniel Martí TryBot-Result: CUEcueckoo Unity-Result: CUE porcuepine --- internal/filetypes/filetypes.go | 3 +- internal/filetypes/filetypes_test.go | 105 ++++++++++++++------------- internal/filetypes/types.cue | 75 +++++++------------ 3 files changed, 80 insertions(+), 103 deletions(-) diff --git a/internal/filetypes/filetypes.go b/internal/filetypes/filetypes.go index b813e6f32a7..f8b24be6b7e 100644 --- a/internal/filetypes/filetypes.go +++ b/internal/filetypes/filetypes.go @@ -92,7 +92,6 @@ func FromFile(b *build.File, mode Mode) (*FileInfo, error) { KeepDefaults: true, Incomplete: true, Imports: true, - Stream: true, Docs: true, Attributes: true, }, nil @@ -312,7 +311,7 @@ func toFile(modeVal, fileVal cue.Value, filename string) (*build.File, error) { func parseType(scope string, mode Mode) (modeVal, fileVal cue.Value, _ error) { modeVal = typesValue.LookupPath(cue.MakePath(cue.Str("modes"), cue.Str(mode.String()))) - fileVal = modeVal.LookupPath(cue.MakePath(cue.Str("File"))) + fileVal = modeVal.LookupPath(cue.MakePath(cue.Str("FileInfo"))) if scope != "" { for _, tag := range strings.Split(scope, "+") { diff --git a/internal/filetypes/filetypes_test.go b/internal/filetypes/filetypes_test.go index 8d29223bc19..f4cf4ac525a 100644 --- a/internal/filetypes/filetypes_test.go +++ b/internal/filetypes/filetypes_test.go @@ -56,8 +56,8 @@ func TestFromFile(t *testing.T) { out: &FileInfo{ File: &build.File{ Filename: "", - Encoding: "cue", - Form: "schema", + Encoding: build.CUE, + Form: build.Schema, }, Definitions: true, Data: true, @@ -83,8 +83,8 @@ func TestFromFile(t *testing.T) { out: &FileInfo{ File: &build.File{ Filename: "", - Encoding: "cue", - Form: "data", + Encoding: build.CUE, + Form: build.Data, }, Data: true, Docs: true, @@ -107,8 +107,8 @@ func TestFromFile(t *testing.T) { out: &FileInfo{ File: &build.File{ Filename: "foo.yaml", - Encoding: "yaml", - Form: "graph", + Encoding: build.YAML, + Form: build.Graph, }, Data: true, References: true, @@ -121,14 +121,14 @@ func TestFromFile(t *testing.T) { name: "yaml+openapi", in: build.File{ Filename: "foo.yaml", - Interpretation: "openapi", + Interpretation: build.OpenAPI, }, out: &FileInfo{ File: &build.File{ Filename: "foo.yaml", - Encoding: "yaml", - Interpretation: "openapi", - Form: "schema", + Encoding: build.YAML, + Interpretation: build.OpenAPI, + Form: build.Schema, }, Definitions: true, Data: true, @@ -151,9 +151,9 @@ func TestFromFile(t *testing.T) { out: &FileInfo{ File: &build.File{ Filename: "data.json", - Encoding: "json", - Interpretation: "auto", - Form: "schema", + Encoding: build.JSON, + Interpretation: build.Auto, + Form: build.Schema, }, Definitions: true, Data: true, @@ -176,9 +176,9 @@ func TestFromFile(t *testing.T) { out: &FileInfo{ File: &build.File{ Filename: "foo.json", - Encoding: "json", + Encoding: build.JSON, Interpretation: "jsonschema", - Form: "schema", + Form: build.Schema, }, Definitions: true, Data: true, @@ -196,15 +196,15 @@ func TestFromFile(t *testing.T) { name: "JSONOpenAPI", in: build.File{ Filename: "foo.json", - Interpretation: "openapi", + Interpretation: build.OpenAPI, }, mode: Def, out: &FileInfo{ File: &build.File{ Filename: "foo.json", - Encoding: "json", - Interpretation: "openapi", - Form: "schema", + Encoding: build.JSON, + Interpretation: build.OpenAPI, + Form: build.Schema, }, Definitions: true, Data: true, @@ -222,15 +222,15 @@ func TestFromFile(t *testing.T) { name: "OpenAPIDefaults", in: build.File{ Filename: "-", - Interpretation: "openapi", + Interpretation: build.OpenAPI, }, mode: Def, out: &FileInfo{ File: &build.File{ Filename: "-", - Encoding: "json", - Interpretation: "openapi", - Form: "schema", + Encoding: build.JSON, + Interpretation: build.OpenAPI, + Form: build.Schema, }, Definitions: true, Data: true, @@ -253,8 +253,8 @@ func TestFromFile(t *testing.T) { out: &FileInfo{ File: &build.File{ Filename: "foo.go", - Encoding: "code", - Form: "schema", + Encoding: build.Code, + Form: build.Schema, Tags: map[string]string{"lang": "go"}, }, Definitions: true, @@ -266,7 +266,6 @@ func TestFromFile(t *testing.T) { KeepDefaults: true, Incomplete: true, Imports: true, - Stream: false, Docs: true, Attributes: true, }, @@ -290,8 +289,8 @@ func TestParseFile(t *testing.T) { mode: Input, out: &build.File{ Filename: "file.json", - Encoding: "json", - Interpretation: "auto", + Encoding: build.JSON, + Interpretation: build.Auto, }, }, { in: ".json", @@ -302,49 +301,50 @@ func TestParseFile(t *testing.T) { mode: Input, out: &build.File{ Filename: ".json.yaml", - Encoding: "yaml", - Interpretation: "auto", + Encoding: build.YAML, + Interpretation: build.Auto, }, }, { in: "file.json", mode: Def, out: &build.File{ Filename: "file.json", - Encoding: "json", + Encoding: build.JSON, }, }, { in: "schema:file.json", out: &build.File{ Filename: "file.json", - Encoding: "json", - Interpretation: "auto", - Form: "schema", + Encoding: build.JSON, + Interpretation: build.Auto, + Form: build.Schema, }, }, { in: "openapi:-", out: &build.File{ Filename: "-", - Encoding: "json", - Interpretation: "openapi", + Encoding: build.JSON, + Form: build.Schema, + Interpretation: build.OpenAPI, }, }, { in: "cue:file.json", out: &build.File{ Filename: "file.json", - Encoding: "cue", + Encoding: build.CUE, }, }, { in: "cue+schema:-", out: &build.File{ Filename: "-", - Encoding: "cue", - Form: "schema", + Encoding: build.CUE, + Form: build.Schema, }, }, { in: "code+lang=js:foo.x", out: &build.File{ Filename: "foo.x", - Encoding: "code", + Encoding: build.Code, Tags: map[string]string{"lang": "js"}, }, }, { @@ -358,14 +358,14 @@ func TestParseFile(t *testing.T) { mode: Input, out: &build.File{ Filename: "-", - Encoding: "cue", + Encoding: build.CUE, }, }, { in: "-", mode: Export, out: &build.File{ Filename: "-", - Encoding: "json", + Encoding: build.JSON, }, }} for _, tc := range testCases { @@ -385,36 +385,37 @@ func TestParseArgs(t *testing.T) { out: []*build.File{ { Filename: "foo.json", - Encoding: "json", - Interpretation: "auto", + Encoding: build.JSON, + Interpretation: build.Auto, }, { Filename: "baz.yaml", - Encoding: "yaml", - Interpretation: "auto", + Encoding: build.YAML, + Interpretation: build.Auto, }, }, }, { in: "data: foo.cue", out: []*build.File{ - {Filename: "foo.cue", Encoding: "cue", Form: "data"}, + {Filename: "foo.cue", Encoding: build.CUE, Form: build.Data}, }, }, { in: "json: foo.json bar.data jsonschema: bar.schema", out: []*build.File{ - {Filename: "foo.json", Encoding: "json"}, // no auto! - {Filename: "bar.data", Encoding: "json"}, + {Filename: "foo.json", Encoding: build.JSON}, // no auto! + {Filename: "bar.data", Encoding: build.JSON}, { Filename: "bar.schema", - Encoding: "json", + Encoding: build.JSON, + Form: build.Schema, Interpretation: "jsonschema", }, }, }, { in: `json: c:\foo.json c:\path\to\file.dat`, out: []*build.File{ - {Filename: `c:\foo.json`, Encoding: "json"}, - {Filename: `c:\path\to\file.dat`, Encoding: "json"}, + {Filename: `c:\foo.json`, Encoding: build.JSON}, + {Filename: `c:\path\to\file.dat`, Encoding: build.JSON}, }, }, { in: "json: json+schema: bar.schema", diff --git a/internal/filetypes/types.cue b/internal/filetypes/types.cue index 803d8b8b8cb..486f337d339 100644 --- a/internal/filetypes/types.cue +++ b/internal/filetypes/types.cue @@ -32,7 +32,7 @@ package build // Default is the file used for stdin and stdout. The settings depend // on the file mode. -#Default: #File & { +#Default: #FileInfo & { filename: *"-" | string } @@ -68,12 +68,16 @@ package build fileForExtVanilla: modes.input.extensions // modes sets defaults for different operational modes. +// The key corresponds to the Go internal/filetypes.Mode type. modes: [string]: { - // TODO(mvdan): Document these once they are better understood. - // Perhaps make them required as well. - File: #File - FileInfo: #FileInfo - Default: #Default + // FileInfo holds the base file information for this mode. + // This will be unified with information derived from the + // file extension and any filetype tags explicitly provided. + FileInfo!: #FileInfo + + // Default holds the base file information for standard input + // or output, where we don't have any file extension available. + Default!: #Default } // input defines modes for input, such as import, eval, vet or def. @@ -107,18 +111,6 @@ modes: export: { encodings: cue: forms.data } -// TODO(mvdan): this "output" mode appears to be unused at the moment. -modes: output: { - Default: { - encoding: *"cue" | _ - } - FileInfo: { - docs: true | *false - attributes: true | *false - } - encodings: cue: forms.data -} - // eval is a legacy mode modes: eval: { Default: { @@ -148,8 +140,12 @@ modes: def: { // An Interpretation determines how a certain program should be interpreted. // For instance, data may be interpreted as describing a schema, which itself // can be converted to a CUE schema. +// This corresponds to the Go cue/build.Interpretation type. #Interpretation: string -#Form: string + +// A Form specifies the form in which a program should be represented. +// It corresponds to the Go cue/build.Form type. +#Form: string modes: [string]: { // extensions maps a file extension to its associated default file properties. @@ -192,11 +188,6 @@ modes: [string]: { stream: false | *true } - encodings: yaml: { - forms.graph - stream: false | *true - } - encodings: jsonl: { forms.data stream: true @@ -234,11 +225,6 @@ modes: [string]: { stream: false } - // encodings: binproto: { - // forms.DataEncoding - // encoding: "binproto" - // } - encodings: code: { forms.schema stream: false @@ -249,9 +235,9 @@ modes: [string]: { forms: [Name=string]: #FileInfo forms: schema: { - form: *"schema" | "final" | "graph" - stream: true | *false + form: *"schema" | "final" | "graph" + stream: true | *false incomplete: *true | false definitions: *true | false optional: *true | false @@ -298,12 +284,12 @@ forms: data: { optional: false } -interpretations: [Name=string]: #FileInfo - -interpretations: auto: { - forms.schema +interpretations: [Name=string]: #FileInfo & { + interpretation: Name } +interpretations: auto: forms.schema + interpretations: jsonschema: { forms.schema encoding: *"json" | _ @@ -326,8 +312,7 @@ tagInfo: { dag: form: "dag" data: form: "data" - cue: encoding: "cue" - + cue: encoding: "cue" json: encoding: "json" jsonl: encoding: "jsonl" yaml: encoding: "yaml" @@ -363,17 +348,9 @@ tagInfo: { interpretation: "" tags: lang: *"" | string } - - auto: { - interpretation: "auto" - encoding: *"json" | _ - } - jsonschema: { - interpretation: "jsonschema" - encoding: *"json" | _ - } - openapi: { - interpretation: "openapi" - encoding: *"json" | _ + auto: interpretations.auto & { + encoding: *"json" | string } + jsonschema: interpretations.jsonschema + openapi: interpretations.openapi }