this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

encoding/jsonschema: allow impossible subschemas

Some real-world schemas contain self-contradictory elements, despite
being useful in practice. We change `encoding/jsonschema` so that it's
not necessarily an error to have a self-contradictory schema as long as
the top level schema itself is not self-contradictory.

This allows us to generate CUE for more real-world schemas, such as this
one:

https://github.com/SchemaStore/schemastore/blob/c084075dbfa7eb7da2c4c81456d04543b7be5744/src/schemas/json/stylelintrc.json#L173

We might add functionality to enable stricter vetting of such schemas in
the future, but for now, schema linting is not what we're aiming for.

Fixes #3455

Signed-off-by: Roger Peppe <rogpeppe@gmail.com>
Change-Id: I60f5b56b7afd59d9e42ca93906f6f335b4500a39
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1201396
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>

+81 -9
+1 -1
cue.mod/pkg/github.com/SchemaStore/schemastore/src/schemas/json/github-workflow.cue
··· 778 778 779 779 // The type of machine to run the job on. The machine can be 780 780 // either a GitHub-hosted runner, or a self-hosted runner. 781 - "runs-on"!: matchN(>=1, [string, matchN(>=1, [[string] & [_, ...]]), { 781 + "runs-on"!: matchN(>=1, [string, [string] & [_, ...] & [...], { 782 782 group?: string 783 783 labels?: matchN(1, [string, [...string]]) 784 784 ...
+17
encoding/jsonschema/constraints_combinator.go
··· 75 75 a := make([]ast.Expr, 0, len(items)) 76 76 for _, v := range items { 77 77 x, sub := s.schemaState(v, s.allowedTypes, nil, true) 78 + if sub.allowedTypes == 0 { 79 + // Nothing is allowed; omit. 80 + continue 81 + } 78 82 types |= sub.allowedTypes 79 83 knownTypes |= sub.knownTypes 80 84 a = append(a, x) 85 + } 86 + if len(a) == 0 { 87 + // Nothing at all is allowed. 88 + s.allowedTypes = 0 89 + return 90 + } 91 + if len(a) == 1 { 92 + s.all.add(n, a[0]) 93 + return 81 94 } 82 95 s.allowedTypes &= types 83 96 s.knownTypes &= knownTypes ··· 106 119 a := make([]ast.Expr, 0, len(items)) 107 120 for _, v := range items { 108 121 x, sub := s.schemaState(v, s.allowedTypes, nil, true) 122 + if sub.allowedTypes == 0 { 123 + // Nothing is allowed; omit 124 + continue 125 + } 109 126 types |= sub.allowedTypes 110 127 111 128 // TODO: make more finegrained by making it two pass.
+5 -2
encoding/jsonschema/decode.go
··· 126 126 } 127 127 128 128 expr, state := root.schemaState(v, allTypes, nil, false) 129 + if state.allowedTypes == 0 { 130 + d.addErr(errors.Newf(state.pos.Pos(), "constraints are not possible to satisfy")) 131 + } 129 132 130 133 tags := []string{} 131 134 if state.schemaVersionPresent { ··· 485 488 // finalize constructs a CUE type from the collected constraints. 486 489 func (s *state) finalize() (e ast.Expr) { 487 490 if s.allowedTypes == 0 { 488 - // Nothing is possible. 489 - s.addErr(errors.Newf(s.pos.Pos(), "constraints are not possible to satisfy")) 491 + // Nothing is possible. This isn't a necessarily a problem, as 492 + // we might be inside an allOf or oneOf with other valid constraints. 490 493 return bottom() 491 494 } 492 495 s.addIfThenElse()
+2 -2
encoding/jsonschema/testdata/external/tests/draft2019-09/anchor.json
··· 141 141 "$ref": "child1#my_anchor" 142 142 }, 143 143 "skip": { 144 - "v2": "extract error: keyword \"$anchor\" not yet implemented (and 4 more errors)", 145 - "v3": "extract error: keyword \"$anchor\" not yet implemented (and 4 more errors)" 144 + "v2": "extract error: keyword \"$anchor\" not yet implemented (and 2 more errors)", 145 + "v3": "extract error: keyword \"$anchor\" not yet implemented (and 2 more errors)" 146 146 }, 147 147 "tests": [ 148 148 {
+2 -2
encoding/jsonschema/testdata/external/tests/draft2020-12/anchor.json
··· 141 141 "$ref": "child1#my_anchor" 142 142 }, 143 143 "skip": { 144 - "v2": "extract error: keyword \"$anchor\" not yet implemented (and 4 more errors)", 145 - "v3": "extract error: keyword \"$anchor\" not yet implemented (and 4 more errors)" 144 + "v2": "extract error: keyword \"$anchor\" not yet implemented (and 2 more errors)", 145 + "v3": "extract error: keyword \"$anchor\" not yet implemented (and 2 more errors)" 146 146 }, 147 147 "tests": [ 148 148 {
+17
encoding/jsonschema/testdata/txtar/anyof_with_one_possible.txtar
··· 1 + -- schema.json -- 2 + { 3 + "anyOf": [ 4 + { 5 + "type": "string", 6 + "enum": [ 7 + 1, 8 + 2 9 + ] 10 + }, 11 + { 12 + "type": "boolean" 13 + } 14 + ] 15 + } 16 + -- out/decode/extract -- 17 + bool
+20
encoding/jsonschema/testdata/txtar/anyofof_with_impossible_elements.txtar
··· 1 + -- schema.json -- 2 + { 3 + "anyOf": [ 4 + { 5 + "type": "string", 6 + "enum": [ 7 + 1, 8 + 2 9 + ] 10 + }, 11 + { 12 + "type": "boolean" 13 + }, 14 + { 15 + "type": "number" 16 + } 17 + ] 18 + } 19 + -- out/decode/extract -- 20 + matchN(>=1, [bool, number])
-2
encoding/jsonschema/testdata/txtar/impossibleallof.txtar
··· 9 9 ERROR: 10 10 constraints are not possible to satisfy: 11 11 schema.json:1:1 12 - constraints are not possible to satisfy: 13 - schema.json:4:9
+17
encoding/jsonschema/testdata/txtar/oneof_with_one_possible.txtar
··· 1 + -- schema.json -- 2 + { 3 + "oneOf": [ 4 + { 5 + "type": "string", 6 + "enum": [ 7 + 1, 8 + 2 9 + ] 10 + }, 11 + { 12 + "type": "boolean" 13 + } 14 + ] 15 + } 16 + -- out/decode/extract -- 17 + bool