Skip to content

Commit 9f5eee1

Browse files
committed
Select a matching deprecated alternative in anyOf/oneOf
A deprecation notice is advisory, not a validation failure, but hasProblems() counted it like any other problem. So a deprecated branch of an anyOf/oneOf that actually matched the value was treated as a non-match, and a non-matching sibling was reported instead (e.g. a const branch's 'Value is not accepted' message). The const case happened to work only because enumValueMatch is a separate tiebreaker; a pattern branch had no such luck. Exclude deprecation problems from hasProblems() so match selection ignores them. The deprecation diagnostic is still reported. Fixes #304
1 parent 257468d commit 9f5eee1

2 files changed

Lines changed: 36 additions & 1 deletion

File tree

src/parser/jsonParser.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,11 @@ export class ValidationResult {
276276
}
277277

278278
public hasProblems(): boolean {
279-
return !!this.problems.length;
279+
// A deprecation notice is advisory, not a validation failure. It must not make an
280+
// otherwise-valid schema look like a non-match, otherwise a deprecated-but-matching
281+
// `anyOf`/`oneOf` alternative loses to a non-matching one (see #304). The deprecation
282+
// problem is still reported; it just doesn't count towards match selection here.
283+
return this.problems.some(p => p.code !== ErrorCode.Deprecated);
280284
}
281285

282286
public merge(validationResult: ValidationResult): void {

src/test/parser.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2633,6 +2633,37 @@ suite('JSON Parser', () => {
26332633

26342634
});
26352635

2636+
test('deprecated alternative in anyOf is selected when it matches (#304)', function () {
2637+
// The value matches the second (deprecated) branch. The deprecation warning must not make
2638+
// that branch look like a non-match, otherwise the non-matching `const` branch is reported
2639+
// instead of the expected "Value is deprecated".
2640+
const schema: JSONSchema = {
2641+
type: 'object',
2642+
properties: {
2643+
'key': {
2644+
anyOf: [
2645+
{ type: 'string', const: 'unused literal' },
2646+
{ type: 'string', pattern: '^text value$', deprecated: true }
2647+
]
2648+
}
2649+
}
2650+
};
2651+
{
2652+
const { textDoc, jsonDoc } = toDocument('{ "key": "text value" }');
2653+
const semanticErrors = validate2(jsonDoc, textDoc, schema)!;
2654+
assert.strictEqual(semanticErrors.length, 1);
2655+
assert.strictEqual(semanticErrors[0].code, ErrorCode.Deprecated);
2656+
}
2657+
2658+
// A value that matches neither branch still reports the non-match, unaffected by the fix.
2659+
{
2660+
const { textDoc, jsonDoc } = toDocument('{ "key": "other value" }');
2661+
const semanticErrors = validate2(jsonDoc, textDoc, schema)!;
2662+
assert.strictEqual(semanticErrors.length, 1);
2663+
assert.notStrictEqual(semanticErrors[0].code, ErrorCode.Deprecated);
2664+
}
2665+
});
2666+
26362667
test('Strings with spaces', function () {
26372668

26382669
const { textDoc, jsonDoc } = toDocument('{"key1":"first string", "key2":["second string"]}');

0 commit comments

Comments
 (0)