Skip to content

Commit

Permalink
Added language setting option to skip runtime schema compilation
Browse files Browse the repository at this point in the history
  • Loading branch information
Anastasiia Derendeeva committed May 7, 2024
1 parent dfccc6f commit 4e7e4e1
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 5 deletions.
30 changes: 25 additions & 5 deletions src/languageservice/services/yamlSchemaService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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();
Expand All @@ -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;

Check failure on line 41 in src/languageservice/services/yamlSchemaService.ts

View workflow job for this annotation

GitHub Actions / build (macos-latest)

Unexpected var, use let or const instead

Check failure on line 41 in src/languageservice/services/yamlSchemaService.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Unexpected var, use let or const instead

export declare type CustomSchemaProvider = (uri: string) => Promise<string | string[]>;

Expand Down Expand Up @@ -111,6 +112,7 @@ export class YAMLSchemaService extends JSONSchemaService {
public schemaPriorityMapping: Map<string, Set<SchemaPriority>>;

private schemaUriToNameAndDescription = new Map<string, SchemaStoreSchema>();
private skipSchemaValidation: boolean;

constructor(
requestService: SchemaRequestService,
Expand All @@ -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 {
Expand Down Expand Up @@ -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,
Expand All @@ -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')}`);
Expand Down
5 changes: 5 additions & 0 deletions src/languageservice/yamlLanguageService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -204,6 +208,7 @@ export function getLanguageService(params: {

return {
configure: (settings) => {
schemaService.configure(settings);
schemaService.clearExternalSchemas();
if (settings.schemas) {
schemaService.schemaPriorityMapping = new Map();
Expand Down
18 changes: 18 additions & 0 deletions test/schemaValidation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions test/utils/serviceSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export class ServiceSetup {
yamlVersion: '1.2',
flowMapping: 'allow',
flowSequence: 'allow',
skipSchemaValidation: false,
};

withValidate(): ServiceSetup {
Expand Down

0 comments on commit 4e7e4e1

Please sign in to comment.