this repo has no description
0
fork

Configure Feed

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

encoding/jsonschema: fix patternProperties in Extract

Although the current code goes to some lengths to apply the
`patternProperties` constraint only to fields that are not explicitly
defined, this does not conform to the spec, which says [1]:

> Validation succeeds if, for each instance name that matches any
> regular expressions that appear as a property name in this keyword's
> value, the child instance for that name successfully validates against
> each schema that corresponds to a matching regular expression.

That is, there is no interaction between this keyword and the
`properties` keyword. I have verified that this is the case manually,
and it's borne out by the fact that various external tests start passing.

It's a nice bonus that this behavior actually aligns more closely
with CUE itself.

[1]: https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-01#section-10.3.2.2

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

+10 -20
+2 -6
encoding/jsonschema/constraints_object.go
··· 308 308 s.errf(n, `value of "patternProperties" must be an object, found %v`, n.Kind()) 309 309 } 310 310 obj := s.object(n) 311 - existing := excludeFields(s.obj.Elts) 312 311 s.processMap(n, func(key string, n cue.Value) { 313 312 if !s.checkRegexp(n, key) { 314 313 return ··· 321 320 &ast.UnaryExpr{Op: token.NMAT, X: ast.NewString(key)}) 322 321 323 322 // We'll make a pattern constraint of the form: 324 - // [pattern & !~(properties)]: schema 323 + // [pattern]: schema 325 324 f := embedStruct(ast.NewStruct(&ast.Field{ 326 - Label: ast.NewList(ast.NewBinExpr( 327 - token.AND, 328 - append([]ast.Expr{&ast.UnaryExpr{Op: token.MAT, X: ast.NewString(key)}}, existing...)..., 329 - )), 325 + Label: ast.NewList(&ast.UnaryExpr{Op: token.MAT, X: ast.NewString(key)}), 330 326 Value: s.schema(n), 331 327 })) 332 328 ast.SetRelPos(f, token.NewSection)
+2 -2
encoding/jsonschema/external_teststats.txt
··· 4 4 5 5 v3: 6 6 schema extract (pass / total): 1072 / 1363 = 78.7% 7 - tests (pass / total): 3908 / 4803 = 81.4% 8 - tests on extracted schemas (pass / total): 3908 / 4041 = 96.7% 7 + tests (pass / total): 3913 / 4803 = 81.5% 8 + tests on extracted schemas (pass / total): 3913 / 4041 = 96.8% 9 9 10 10 v3-roundtrip: 11 11 schema extract (pass / total): 233 / 1363 = 17.1%
-1
encoding/jsonschema/testdata/external/tests/draft2019-09/properties.json
··· 138 138 }, 139 139 "valid": false, 140 140 "skip": { 141 - "v3": "unexpected success", 142 141 "v3-roundtrip": "could not extract schema" 143 142 } 144 143 },
-1
encoding/jsonschema/testdata/external/tests/draft2020-12/properties.json
··· 108 108 }, 109 109 "valid": false, 110 110 "skip": { 111 - "v3": "unexpected success", 112 111 "v3-roundtrip": "unexpected success" 113 112 } 114 113 },
-1
encoding/jsonschema/testdata/external/tests/draft4/properties.json
··· 136 136 }, 137 137 "valid": false, 138 138 "skip": { 139 - "v3": "unexpected success", 140 139 "v3-roundtrip": "could not extract schema" 141 140 } 142 141 },
-1
encoding/jsonschema/testdata/external/tests/draft6/properties.json
··· 136 136 }, 137 137 "valid": false, 138 138 "skip": { 139 - "v3": "unexpected success", 140 139 "v3-roundtrip": "could not extract schema" 141 140 } 142 141 },
-1
encoding/jsonschema/testdata/external/tests/draft7/properties.json
··· 136 136 }, 137 137 "valid": false, 138 138 "skip": { 139 - "v3": "unexpected success", 140 139 "v3-roundtrip": "could not extract schema" 141 140 } 142 141 },
+4 -5
encoding/jsonschema/testdata/txtar/object.txtar
··· 66 66 }, 67 67 "additionalProperties": false 68 68 } 69 - 70 69 -- out/decode/extract -- 71 70 // Main schema 72 71 ··· 86 85 foo?: number 87 86 bar?: number 88 87 89 - {[=~"^\\P{Lu}" & !~"^(foo|bar)$"]: string} 88 + {[=~"^\\P{Lu}"]: string} 90 89 91 - {[=~"^\\P{Lo}" & !~"^(foo|bar)$"]: int} 90 + {[=~"^\\P{Lo}"]: int} 92 91 ... 93 92 } 94 93 patternsNoProps?: { ··· 101 100 foo?: number 102 101 bar?: number 103 102 104 - {[=~"^\\P{Lu}" & !~"^(foo|bar)$"]: string} 103 + {[=~"^\\P{Lu}"]: string} 105 104 106 - {[=~"^\\P{Lo}" & !~"^(foo|bar)$"]: int} 105 + {[=~"^\\P{Lo}"]: int} 107 106 {[!~"^\\P{Lu}" & !~"^\\P{Lo}" & !~"^(foo|bar)$"]: string} 108 107 } 109 108 multi?: >=7 | struct.MaxFields(5) & {
+2 -2
encoding/jsonschema/testdata/txtar/pattern_with_regexp_fields.txtar
··· 22 22 @jsonschema(schema="http://json-schema.org/draft-07/schema#") 23 23 "c.e"?: bool 24 24 25 - {[=~".*" & !~"^(c\\.e)$"]: string} 25 + {[=~".*"]: string} 26 26 ... 27 27 -- test/err-field.json -- 28 28 { ··· 31 31 -- out/decode/testerr/err-field -- 32 32 cue: conflicting values 123 and string (mismatched types int and string): 33 33 generated.cue:4:1 34 - generated.cue:4:28 34 + generated.cue:4:12 35 35 test/err-field.json:2:12