From f1956d659e80d069d416b9e09b9a9e08e31d2b5b Mon Sep 17 00:00:00 2001 From: msivasubramaniaan Date: Wed, 28 Sep 2022 21:09:08 +0530 Subject: [PATCH] added oneOf schema validation Signed-off-by: msivasubramaniaan --- src/languageservice/parser/jsonParser07.ts | 9 ++++- test/schemaValidation.test.ts | 47 ++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/languageservice/parser/jsonParser07.ts b/src/languageservice/parser/jsonParser07.ts index b81fd2c6..3c1e83df 100644 --- a/src/languageservice/parser/jsonParser07.ts +++ b/src/languageservice/parser/jsonParser07.ts @@ -720,6 +720,7 @@ function validate( const testAlternatives = (alternatives: JSONSchemaRef[], maxOneMatch: boolean): number => { const matches = []; + const subMatches = []; const noPropertyMatches = []; // remember the best match that is used for error messages let bestMatch: { @@ -734,9 +735,13 @@ function validate( validate(node, subSchema, schema, subValidationResult, subMatchingSchemas, options); if (!subValidationResult.hasProblems() || callFromAutoComplete) { matches.push(subSchema); + subMatches.push(subSchema); if (subValidationResult.propertiesMatches === 0) { noPropertyMatches.push(subSchema); } + if (subSchema.format) { + subMatches.pop(); + } } if (!bestMatch) { bestMatch = { @@ -751,11 +756,11 @@ function validate( } } - if (matches.length > 1 && noPropertyMatches.length === 0 && maxOneMatch) { + if (subMatches.length > 1 && (subMatches.length > 1 || noPropertyMatches.length === 0) && maxOneMatch) { validationResult.problems.push({ location: { offset: node.offset, length: 1 }, severity: DiagnosticSeverity.Warning, - message: localize('oneOfWarning', 'Minimum one schema should validate.'), + message: localize('oneOfWarning', 'Matches multiple schemas when only one must validate.'), source: getSchemaSource(schema, originalSchema), schemaUri: getSchemaUri(schema, originalSchema), }); diff --git a/test/schemaValidation.test.ts b/test/schemaValidation.test.ts index ce4c1cbc..c9d8b25f 100644 --- a/test/schemaValidation.test.ts +++ b/test/schemaValidation.test.ts @@ -1767,5 +1767,52 @@ obj: expect(result.length).to.eq(1); expect(result[0].message).to.eq('Value is not accepted. Valid values: "tested".'); }); + + it('value matches more than one schema in oneOf - but among one is format matches', async () => { + languageService.addSchema(SCHEMA_ID, { + type: 'object', + properties: { + repository: { + oneOf: [ + { + type: 'string', + format: 'uri', + }, + { + type: 'string', + pattern: '^@', + }, + ], + }, + }, + }); + const content = `repository: '@bittrr'`; + const result = await parseSetup(content); + expect(result.length).to.eq(0); + expect(telemetry.messages).to.be.empty; + }); + + it('value matches more than one schema in oneOf', async () => { + languageService.addSchema(SCHEMA_ID, { + type: 'object', + properties: { + foo: {}, + bar: {}, + }, + oneOf: [ + { + required: ['foo'], + }, + { + required: ['bar'], + }, + ], + }); + const content = `foo: bar\nbar: baz`; + const result = await parseSetup(content); + expect(result.length).to.eq(1); + expect(result[0].message).to.eq('Matches multiple schemas when only one must validate.'); + expect(telemetry.messages).to.be.empty; + }); }); });