diff --git a/cmd/cue/cmd/testdata/script/def_jsonschema.txtar b/cmd/cue/cmd/testdata/script/def_jsonschema.txtar index 48085d11e18..a310db20815 100644 --- a/cmd/cue/cmd/testdata/script/def_jsonschema.txtar +++ b/cmd/cue/cmd/testdata/script/def_jsonschema.txtar @@ -66,7 +66,7 @@ import "strings" "foo": "bar" } -- expect-stderr -- -unsupported constraint "foo": +unknown keyword "foo": ./bad.json:3:3 -- data.yaml -- age: twenty diff --git a/encoding/jsonschema/constraints_meta.go b/encoding/jsonschema/constraints_meta.go index 41eb023f4bf..e99444d5e44 100644 --- a/encoding/jsonschema/constraints_meta.go +++ b/encoding/jsonschema/constraints_meta.go @@ -34,6 +34,10 @@ func constraintID(key string, n cue.Value, s *state) { } if u.Fragment != "" { + // TODO do not use Strict for this. The specification is clear: + // before 2019-09, IDs could contain plain-name fragments; + // (see https://json-schema.org/draft-07/draft-handrews-json-schema-01#rfc.section.5) + // afterwards, $anchor was reserved for that purpose. if s.cfg.Strict { s.errf(n, "$id URI may not contain a fragment") } @@ -61,7 +65,7 @@ func constraintSchema(key string, n cue.Value, s *state) { } func constraintTODO(key string, n cue.Value, s *state) { - if s.cfg.Strict { + if s.cfg.StrictFeatures { s.errf(n, `keyword %q not yet implemented`, key) } } diff --git a/encoding/jsonschema/constraints_string.go b/encoding/jsonschema/constraints_string.go index df1f69abd44..b0126d8a90f 100644 --- a/encoding/jsonschema/constraints_string.go +++ b/encoding/jsonschema/constraints_string.go @@ -51,7 +51,10 @@ func constraintMinLength(key string, n cue.Value, s *state) { func constraintPattern(key string, n cue.Value, s *state) { str, _ := n.String() if _, err := regexp.Compile(str); err != nil { - if s.cfg.Strict { + if s.cfg.StrictFeatures { + // TODO check if the error is only because of an unsupported + // regexp feature (e.g. perl regexp) or because the regexp is just + // bad. If the latter, this should be an error even if Strict is false. s.errf(n, "unsupported regexp: %v", err) } return diff --git a/encoding/jsonschema/decode.go b/encoding/jsonschema/decode.go index 1469df570ac..f9f6a3d6bfa 100644 --- a/encoding/jsonschema/decode.go +++ b/encoding/jsonschema/decode.go @@ -673,9 +673,9 @@ func (s *state) schemaState(n cue.Value, types cue.Kind, idRef []label, isLogica // Convert each constraint into a either a value or a functor. c := constraintMap[key] if c == nil { - if pass == 0 && s.cfg.Strict { + if pass == 0 && s.cfg.StrictKeywords { // TODO: value is not the correct position, albeit close. Fix this. - s.warnf(value.Pos(), "unsupported constraint %q", key) + s.warnf(value.Pos(), "unknown keyword %q", key) } return } @@ -683,8 +683,8 @@ func (s *state) schemaState(n cue.Value, types cue.Kind, idRef []label, isLogica return } if !c.versions.contains(state.schemaVersion) { - if s.cfg.Strict { - s.warnf(value.Pos(), "constraint %q is not supported in JSON schema version %v", key, state.schemaVersion) + if s.cfg.StrictKeywords { + s.warnf(value.Pos(), "keyword %q is not supported in JSON schema version %v", key, state.schemaVersion) } return } diff --git a/encoding/jsonschema/decode_test.go b/encoding/jsonschema/decode_test.go index 282041fdc4f..3c9f09bdc24 100644 --- a/encoding/jsonschema/decode_test.go +++ b/encoding/jsonschema/decode_test.go @@ -90,6 +90,8 @@ func TestDecode(t *testing.T) { } } cfg.Strict = t.HasTag("strict") + cfg.StrictKeywords = t.HasTag("strictKeywords") + cfg.StrictFeatures = t.HasTag("strictFeatures") ctx := t.CueContext() diff --git a/encoding/jsonschema/jsonschema.go b/encoding/jsonschema/jsonschema.go index 93e8bcadf7a..a286e7413a2 100644 --- a/encoding/jsonschema/jsonschema.go +++ b/encoding/jsonschema/jsonschema.go @@ -51,6 +51,10 @@ func Extract(data cue.InstanceOrValue, cfg *Config) (f *ast.File, err error) { if cfg.DefaultVersion == VersionUnknown { cfg.DefaultVersion = VersionDraft7 } + if cfg.Strict { + cfg.StrictKeywords = true + cfg.StrictFeatures = true + } d := &decoder{ cfg: cfg, mapURLErrors: make(map[string]bool), @@ -102,10 +106,19 @@ type Config struct { // - selection and definition of formats // - documentation hooks. - // Strict reports an error for unsupported features, rather than ignoring - // them. + // Strict reports an error for unsupported features and keywords, + // rather than ignoring them. When true, this is equivalent to + // setting both StrictFeatures and StrictKeywords to true. Strict bool + // StrictFeatures reports an error for features that are known + // to be unsupported. + StrictFeatures bool + + // StrictKeywords reports an error when unknown keywords + // are encountered. + StrictKeywords bool + // DefaultVersion holds the default schema version to use // when no $schema field is present. If it is zero, [DefaultVersion] // will be used. diff --git a/encoding/jsonschema/testdata/external/tests/draft2019-09/items.json b/encoding/jsonschema/testdata/external/tests/draft2019-09/items.json index 0aecf2b7957..6bd96f214e0 100644 --- a/encoding/jsonschema/testdata/external/tests/draft2019-09/items.json +++ b/encoding/jsonschema/testdata/external/tests/draft2019-09/items.json @@ -436,7 +436,7 @@ "valid": true, "skip": { "v2": "incompatible list lengths (2 and 3)\n0: incompatible list lengths (1 and 2)\n1: incompatible list lengths (1 and 2)\n", - "v3": "incompatible list lengths (2 and 3):\n generated.cue:2:1\n" + "v3": "incompatible list lengths (2 and 3):\n generated.cue:2:1\n0: incompatible list lengths (1 and 2):\n generated.cue:4:8\n" } } ] diff --git a/encoding/jsonschema/testdata/external/tests/draft2019-09/optional/refOfUnknownKeyword.json b/encoding/jsonschema/testdata/external/tests/draft2019-09/optional/refOfUnknownKeyword.json index 7e331714c9b..70c06635444 100644 --- a/encoding/jsonschema/testdata/external/tests/draft2019-09/optional/refOfUnknownKeyword.json +++ b/encoding/jsonschema/testdata/external/tests/draft2019-09/optional/refOfUnknownKeyword.json @@ -13,8 +13,8 @@ } }, "skip": { - "v2": "extract error: unsupported constraint \"unknown-keyword\"", - "v3": "extract error: unsupported constraint \"unknown-keyword\"" + "v2": "extract error: unknown keyword \"unknown-keyword\"", + "v3": "extract error: unknown keyword \"unknown-keyword\"" }, "tests": [ { @@ -57,8 +57,8 @@ } }, "skip": { - "v2": "extract error: unsupported constraint \"unknown-keyword\"", - "v3": "extract error: unsupported constraint \"unknown-keyword\"" + "v2": "extract error: unknown keyword \"unknown-keyword\"", + "v3": "extract error: unknown keyword \"unknown-keyword\"" }, "tests": [ { diff --git a/encoding/jsonschema/testdata/external/tests/draft2019-09/optional/unknownKeyword.json b/encoding/jsonschema/testdata/external/tests/draft2019-09/optional/unknownKeyword.json index 8ff3f8725ab..5862a066e27 100644 --- a/encoding/jsonschema/testdata/external/tests/draft2019-09/optional/unknownKeyword.json +++ b/encoding/jsonschema/testdata/external/tests/draft2019-09/optional/unknownKeyword.json @@ -43,8 +43,8 @@ ] }, "skip": { - "v2": "extract error: unsupported constraint \"array_of_schemas\" (and 1 more errors)", - "v3": "extract error: unsupported constraint \"array_of_schemas\" (and 1 more errors)" + "v2": "extract error: unknown keyword \"array_of_schemas\" (and 1 more errors)", + "v3": "extract error: unknown keyword \"array_of_schemas\" (and 1 more errors)" }, "tests": [ { diff --git a/encoding/jsonschema/testdata/external/tests/draft2020-12/optional/refOfUnknownKeyword.json b/encoding/jsonschema/testdata/external/tests/draft2020-12/optional/refOfUnknownKeyword.json index 349f82dac92..a9371eacab7 100644 --- a/encoding/jsonschema/testdata/external/tests/draft2020-12/optional/refOfUnknownKeyword.json +++ b/encoding/jsonschema/testdata/external/tests/draft2020-12/optional/refOfUnknownKeyword.json @@ -13,8 +13,8 @@ } }, "skip": { - "v2": "extract error: unsupported constraint \"unknown-keyword\"", - "v3": "extract error: unsupported constraint \"unknown-keyword\"" + "v2": "extract error: unknown keyword \"unknown-keyword\"", + "v3": "extract error: unknown keyword \"unknown-keyword\"" }, "tests": [ { @@ -57,8 +57,8 @@ } }, "skip": { - "v2": "extract error: unsupported constraint \"unknown-keyword\"", - "v3": "extract error: unsupported constraint \"unknown-keyword\"" + "v2": "extract error: unknown keyword \"unknown-keyword\"", + "v3": "extract error: unknown keyword \"unknown-keyword\"" }, "tests": [ { diff --git a/encoding/jsonschema/testdata/external/tests/draft2020-12/optional/unknownKeyword.json b/encoding/jsonschema/testdata/external/tests/draft2020-12/optional/unknownKeyword.json index 07479c6575e..5e3a4d2570c 100644 --- a/encoding/jsonschema/testdata/external/tests/draft2020-12/optional/unknownKeyword.json +++ b/encoding/jsonschema/testdata/external/tests/draft2020-12/optional/unknownKeyword.json @@ -43,8 +43,8 @@ ] }, "skip": { - "v2": "extract error: unsupported constraint \"array_of_schemas\" (and 1 more errors)", - "v3": "extract error: unsupported constraint \"array_of_schemas\" (and 1 more errors)" + "v2": "extract error: unknown keyword \"array_of_schemas\" (and 1 more errors)", + "v3": "extract error: unknown keyword \"array_of_schemas\" (and 1 more errors)" }, "tests": [ { diff --git a/encoding/jsonschema/testdata/external/tests/draft4/items.json b/encoding/jsonschema/testdata/external/tests/draft4/items.json index 7ef0f067e50..4948181f296 100644 --- a/encoding/jsonschema/testdata/external/tests/draft4/items.json +++ b/encoding/jsonschema/testdata/external/tests/draft4/items.json @@ -323,7 +323,7 @@ "valid": true, "skip": { "v2": "incompatible list lengths (2 and 3)\n0: incompatible list lengths (1 and 2)\n1: incompatible list lengths (1 and 2)\n", - "v3": "incompatible list lengths (2 and 3):\n generated.cue:2:1\n" + "v3": "incompatible list lengths (2 and 3):\n generated.cue:2:1\n0: incompatible list lengths (1 and 2):\n generated.cue:4:8\n" } } ] diff --git a/encoding/jsonschema/testdata/external/tests/draft4/optional/id.json b/encoding/jsonschema/testdata/external/tests/draft4/optional/id.json index 0db77d32ce8..9e295a3c9e0 100644 --- a/encoding/jsonschema/testdata/external/tests/draft4/optional/id.json +++ b/encoding/jsonschema/testdata/external/tests/draft4/optional/id.json @@ -33,8 +33,8 @@ ] }, "skip": { - "v2": "extract error: constraint \"const\" is not supported in JSON schema version http://json-schema.org/draft-04/schema#", - "v3": "extract error: constraint \"const\" is not supported in JSON schema version http://json-schema.org/draft-04/schema#" + "v2": "extract error: keyword \"const\" is not supported in JSON schema version http://json-schema.org/draft-04/schema#", + "v3": "extract error: keyword \"const\" is not supported in JSON schema version http://json-schema.org/draft-04/schema#" }, "tests": [ { diff --git a/encoding/jsonschema/testdata/external/tests/draft4/ref.json b/encoding/jsonschema/testdata/external/tests/draft4/ref.json index 693040ad903..6128b344fee 100644 --- a/encoding/jsonschema/testdata/external/tests/draft4/ref.json +++ b/encoding/jsonschema/testdata/external/tests/draft4/ref.json @@ -329,8 +329,8 @@ ] }, "skip": { - "v2": "extract error: constraint \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-04/schema# (and 1 more errors)", - "v3": "extract error: constraint \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-04/schema# (and 1 more errors)" + "v2": "extract error: keyword \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-04/schema# (and 1 more errors)", + "v3": "extract error: keyword \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-04/schema# (and 1 more errors)" }, "tests": [ { diff --git a/encoding/jsonschema/testdata/external/tests/draft6/items.json b/encoding/jsonschema/testdata/external/tests/draft6/items.json index 9f05cfa5743..bdaafa2c307 100644 --- a/encoding/jsonschema/testdata/external/tests/draft6/items.json +++ b/encoding/jsonschema/testdata/external/tests/draft6/items.json @@ -430,7 +430,7 @@ "valid": true, "skip": { "v2": "incompatible list lengths (2 and 3)\n0: incompatible list lengths (1 and 2)\n1: incompatible list lengths (1 and 2)\n", - "v3": "incompatible list lengths (2 and 3):\n generated.cue:2:1\n" + "v3": "incompatible list lengths (2 and 3):\n generated.cue:2:1\n0: incompatible list lengths (1 and 2):\n generated.cue:4:8\n" } } ] diff --git a/encoding/jsonschema/testdata/external/tests/draft6/optional/unknownKeyword.json b/encoding/jsonschema/testdata/external/tests/draft6/optional/unknownKeyword.json index f665e4afd0f..f60e74e6ff5 100644 --- a/encoding/jsonschema/testdata/external/tests/draft6/optional/unknownKeyword.json +++ b/encoding/jsonschema/testdata/external/tests/draft6/optional/unknownKeyword.json @@ -42,8 +42,8 @@ ] }, "skip": { - "v2": "extract error: unsupported constraint \"array_of_schemas\" (and 1 more errors)", - "v3": "extract error: unsupported constraint \"array_of_schemas\" (and 1 more errors)" + "v2": "extract error: unknown keyword \"array_of_schemas\" (and 1 more errors)", + "v3": "extract error: unknown keyword \"array_of_schemas\" (and 1 more errors)" }, "tests": [ { diff --git a/encoding/jsonschema/testdata/external/tests/draft6/ref.json b/encoding/jsonschema/testdata/external/tests/draft6/ref.json index 70202ddfbb9..7e11cf10b9c 100644 --- a/encoding/jsonschema/testdata/external/tests/draft6/ref.json +++ b/encoding/jsonschema/testdata/external/tests/draft6/ref.json @@ -329,8 +329,8 @@ ] }, "skip": { - "v2": "extract error: constraint \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema# (and 1 more errors)", - "v3": "extract error: constraint \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema# (and 1 more errors)" + "v2": "extract error: keyword \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema# (and 1 more errors)", + "v3": "extract error: keyword \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema# (and 1 more errors)" }, "tests": [ { @@ -994,8 +994,8 @@ } }, "skip": { - "v2": "extract error: constraint \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#", - "v3": "extract error: constraint \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#" + "v2": "extract error: keyword \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#", + "v3": "extract error: keyword \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#" }, "tests": [ { @@ -1039,8 +1039,8 @@ } }, "skip": { - "v2": "extract error: constraint \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#", - "v3": "extract error: constraint \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#" + "v2": "extract error: keyword \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#", + "v3": "extract error: keyword \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#" }, "tests": [ { @@ -1084,8 +1084,8 @@ } }, "skip": { - "v2": "extract error: constraint \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#", - "v3": "extract error: constraint \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#" + "v2": "extract error: keyword \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#", + "v3": "extract error: keyword \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#" }, "tests": [ { @@ -1129,8 +1129,8 @@ } }, "skip": { - "v2": "extract error: constraint \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#", - "v3": "extract error: constraint \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#" + "v2": "extract error: keyword \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#", + "v3": "extract error: keyword \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#" }, "tests": [ { @@ -1174,8 +1174,8 @@ } }, "skip": { - "v2": "extract error: constraint \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#", - "v3": "extract error: constraint \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#" + "v2": "extract error: keyword \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#", + "v3": "extract error: keyword \"$comment\" is not supported in JSON schema version http://json-schema.org/draft-06/schema#" }, "tests": [ { diff --git a/encoding/jsonschema/testdata/external/tests/draft7/items.json b/encoding/jsonschema/testdata/external/tests/draft7/items.json index 9f05cfa5743..bdaafa2c307 100644 --- a/encoding/jsonschema/testdata/external/tests/draft7/items.json +++ b/encoding/jsonschema/testdata/external/tests/draft7/items.json @@ -430,7 +430,7 @@ "valid": true, "skip": { "v2": "incompatible list lengths (2 and 3)\n0: incompatible list lengths (1 and 2)\n1: incompatible list lengths (1 and 2)\n", - "v3": "incompatible list lengths (2 and 3):\n generated.cue:2:1\n" + "v3": "incompatible list lengths (2 and 3):\n generated.cue:2:1\n0: incompatible list lengths (1 and 2):\n generated.cue:4:8\n" } } ] diff --git a/encoding/jsonschema/testdata/external/tests/draft7/optional/unknownKeyword.json b/encoding/jsonschema/testdata/external/tests/draft7/optional/unknownKeyword.json index f665e4afd0f..f60e74e6ff5 100644 --- a/encoding/jsonschema/testdata/external/tests/draft7/optional/unknownKeyword.json +++ b/encoding/jsonschema/testdata/external/tests/draft7/optional/unknownKeyword.json @@ -42,8 +42,8 @@ ] }, "skip": { - "v2": "extract error: unsupported constraint \"array_of_schemas\" (and 1 more errors)", - "v3": "extract error: unsupported constraint \"array_of_schemas\" (and 1 more errors)" + "v2": "extract error: unknown keyword \"array_of_schemas\" (and 1 more errors)", + "v3": "extract error: unknown keyword \"array_of_schemas\" (and 1 more errors)" }, "tests": [ { diff --git a/encoding/jsonschema/testdata/txtar/defaultversion.txtar b/encoding/jsonschema/testdata/txtar/defaultversion.txtar index 8a398963bce..0177b8c1034 100644 --- a/encoding/jsonschema/testdata/txtar/defaultversion.txtar +++ b/encoding/jsonschema/testdata/txtar/defaultversion.txtar @@ -7,5 +7,5 @@ } -- out/decode/extract -- ERROR: -constraint "$id" is not supported in JSON schema version http://json-schema.org/draft-04/schema#: +keyword "$id" is not supported in JSON schema version http://json-schema.org/draft-04/schema#: schema.json:2:3 diff --git a/encoding/jsonschema/testdata/txtar/newid_oldversion.txtar b/encoding/jsonschema/testdata/txtar/newid_oldversion.txtar index 8422aa98359..182fa3b60cc 100644 --- a/encoding/jsonschema/testdata/txtar/newid_oldversion.txtar +++ b/encoding/jsonschema/testdata/txtar/newid_oldversion.txtar @@ -7,5 +7,5 @@ } -- out/decode/extract -- ERROR: -constraint "$id" is not supported in JSON schema version http://json-schema.org/draft-04/schema#: +keyword "$id" is not supported in JSON schema version http://json-schema.org/draft-04/schema#: schema.json:3:3 diff --git a/encoding/jsonschema/testdata/txtar/oldid_newversion.txtar b/encoding/jsonschema/testdata/txtar/oldid_newversion.txtar index 0c7b95c8e98..9a837facf7f 100644 --- a/encoding/jsonschema/testdata/txtar/oldid_newversion.txtar +++ b/encoding/jsonschema/testdata/txtar/oldid_newversion.txtar @@ -7,5 +7,5 @@ } -- out/decode/extract -- ERROR: -constraint "id" is not supported in JSON schema version http://json-schema.org/draft-07/schema#: +keyword "id" is not supported in JSON schema version http://json-schema.org/draft-07/schema#: schema.json:3:3 diff --git a/encoding/jsonschema/testdata/txtar/strictfeatures.txtar b/encoding/jsonschema/testdata/txtar/strictfeatures.txtar new file mode 100644 index 00000000000..31ca27d5293 --- /dev/null +++ b/encoding/jsonschema/testdata/txtar/strictfeatures.txtar @@ -0,0 +1,12 @@ +#strictFeatures +-- schema.json -- +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "number", + "$dynamicAnchor": "bar", + "foo": true +} +-- out/decode/extract -- +ERROR: +keyword "$dynamicAnchor" not yet implemented: + schema.json:4:3 diff --git a/encoding/jsonschema/testdata/txtar/strictkeywords.txtar b/encoding/jsonschema/testdata/txtar/strictkeywords.txtar new file mode 100644 index 00000000000..d1e5aa0c6de --- /dev/null +++ b/encoding/jsonschema/testdata/txtar/strictkeywords.txtar @@ -0,0 +1,12 @@ +#strictKeywords +-- schema.json -- +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "number", + "$dynamicAnchor": "bar", + "foo": true +} +-- out/decode/extract -- +ERROR: +unknown keyword "foo": + schema.json:5:3