diff --git a/src/languageservice/services/yamlSchemaService.ts b/src/languageservice/services/yamlSchemaService.ts index 453b74eb..1ae50391 100644 --- a/src/languageservice/services/yamlSchemaService.ts +++ b/src/languageservice/services/yamlSchemaService.ts @@ -5,7 +5,7 @@ *--------------------------------------------------------------------------------------------*/ import { JSONSchema, JSONSchemaMap, JSONSchemaRef } from '../jsonSchema'; -import { SchemaPriority, SchemaRequestService, WorkspaceContextService } from '../yamlLanguageService'; +import { LanguageSettings, SchemaPriority, SchemaRequestService, WorkspaceContextService } from '../yamlLanguageService'; import { UnresolvedSchema, ResolvedSchema, @@ -27,7 +27,7 @@ import { getSchemaFromModeline } from './modelineUtil'; import { JSONSchemaDescriptionExt } from '../../requestTypes'; import { SchemaVersions } from '../yamlTypes'; -import Ajv, { DefinedError } from 'ajv'; +import Ajv, { DefinedError, ValidateFunction } from 'ajv'; import { getSchemaTitle } from '../utils/schemaUtils'; const localize = nls.loadMessageBundle(); @@ -37,7 +37,8 @@ const ajv = new Ajv(); // load JSON Schema 07 def to validate loaded schemas // eslint-disable-next-line @typescript-eslint/no-var-requires const jsonSchema07 = require('ajv/dist/refs/json-schema-draft-07.json'); -const schema07Validator = ajv.compile(jsonSchema07); + +var schema07Validator: ValidateFunction; export declare type CustomSchemaProvider = (uri: string) => Promise; @@ -111,6 +112,7 @@ export class YAMLSchemaService extends JSONSchemaService { public schemaPriorityMapping: Map>; private schemaUriToNameAndDescription = new Map(); + private skipSchemaValidation: boolean; constructor( requestService: SchemaRequestService, @@ -121,6 +123,13 @@ export class YAMLSchemaService extends JSONSchemaService { this.customSchemaProvider = undefined; this.requestService = requestService; this.schemaPriorityMapping = new Map(); + this.skipSchemaValidation = false; + } + + configure(languageSettings: LanguageSettings): void { + if (languageSettings) { + this.skipSchemaValidation = languageSettings.skipSchemaValidation; + } } registerCustomSchemaProvider(customSchemaProvider: CustomSchemaProvider): void { @@ -155,6 +164,16 @@ export class YAMLSchemaService extends JSONSchemaService { return result; } + private getSchemaValidator(): ValidateFunction | undefined { + if (this.skipSchemaValidation) { + return undefined; + } + if (!schema07Validator) { + schema07Validator = ajv.compile(jsonSchema07); + } + return schema07Validator; + } + async resolveSchemaContent( schemaToResolve: UnresolvedSchema, schemaURL: string, @@ -164,9 +183,10 @@ export class YAMLSchemaService extends JSONSchemaService { let schema: JSONSchema = schemaToResolve.schema; const contextService = this.contextService; - if (!schema07Validator(schema)) { + const schemaValidator = this.getSchemaValidator(); + if (schemaValidator && !schemaValidator(schema)) { const errs: string[] = []; - for (const err of schema07Validator.errors as DefinedError[]) { + for (const err of schemaValidator.errors as DefinedError[]) { errs.push(`${err.instancePath} : ${err.message}`); } resolveErrors.push(`Schema '${getSchemaTitle(schemaToResolve.schema, schemaURL)}' is not valid:\n${errs.join('\n')}`); diff --git a/src/languageservice/yamlLanguageService.ts b/src/languageservice/yamlLanguageService.ts index 539371d8..9ec3b40b 100644 --- a/src/languageservice/yamlLanguageService.ts +++ b/src/languageservice/yamlLanguageService.ts @@ -119,6 +119,10 @@ export interface LanguageSettings { * If set enforce alphabetical ordering of keys in mappings. */ keyOrdering?: boolean; + /** + * If set skip json schema validation. Allows to not use unsafe-eval rule + */ + skipSchemaValidation?: boolean; } export interface WorkspaceContextService { @@ -204,6 +208,7 @@ export function getLanguageService(params: { return { configure: (settings) => { + schemaService.configure(settings); schemaService.clearExternalSchemas(); if (settings.schemas) { schemaService.schemaPriorityMapping = new Map(); diff --git a/test/schemaValidation.test.ts b/test/schemaValidation.test.ts index 71268db7..3ef482e7 100644 --- a/test/schemaValidation.test.ts +++ b/test/schemaValidation.test.ts @@ -1847,6 +1847,24 @@ obj: }); }); + describe('Skip json schema validation with enabled skipSchemaValidation', () => { + before(() => { + languageSettingsSetup.languageSettings.skipSchemaValidation = true; + languageService.configure(languageSettingsSetup.languageSettings); + }); + after(() => { + languageSettingsSetup.languageSettings.skipSchemaValidation = false; + }); + it('should handle not valid schema object', async () => { + const schema = 'Foo'; + schemaProvider.addSchema(SCHEMA_ID, schema as JSONSchema); + const content = `foo: bar`; + const result = await parseSetup(content); + expect(result).to.be.empty; + expect(telemetry.messages).to.be.empty; + }); + }); + describe('Enum tests', () => { afterEach(() => { schemaProvider.deleteSchema(SCHEMA_ID); diff --git a/test/utils/serviceSetup.ts b/test/utils/serviceSetup.ts index 1a20386d..c9cc1403 100644 --- a/test/utils/serviceSetup.ts +++ b/test/utils/serviceSetup.ts @@ -21,6 +21,7 @@ export class ServiceSetup { yamlVersion: '1.2', flowMapping: 'allow', flowSequence: 'allow', + skipSchemaValidation: false, }; withValidate(): ServiceSetup {