UNPKG

vscode-json-languageservice

Version:
166 lines (165 loc) 8.71 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ (function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define(["require", "exports", "../jsonLanguageTypes", "@vscode/l10n", "../utils/objects"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.JSONValidation = void 0; const jsonLanguageTypes_1 = require("../jsonLanguageTypes"); const l10n = require("@vscode/l10n"); const objects_1 = require("../utils/objects"); class JSONValidation { constructor(jsonSchemaService, promiseConstructor) { this.jsonSchemaService = jsonSchemaService; this.promise = promiseConstructor; this.validationEnabled = true; } configure(raw) { if (raw) { this.validationEnabled = raw.validate !== false; this.commentSeverity = raw.allowComments ? undefined : jsonLanguageTypes_1.DiagnosticSeverity.Error; } } doValidation(textDocument, jsonDocument, documentSettings, schema) { if (!this.validationEnabled) { return this.promise.resolve([]); } const diagnostics = []; const added = {}; const addProblem = (problem) => { // remove duplicated messages const signature = problem.range.start.line + ' ' + problem.range.start.character + ' ' + problem.message; if (!added[signature]) { added[signature] = true; diagnostics.push(problem); } }; const getDiagnostics = (schema) => { let trailingCommaSeverity = documentSettings?.trailingCommas ? toDiagnosticSeverity(documentSettings.trailingCommas) : jsonLanguageTypes_1.DiagnosticSeverity.Error; let commentSeverity = documentSettings?.comments ? toDiagnosticSeverity(documentSettings.comments) : this.commentSeverity; let schemaValidation = documentSettings?.schemaValidation ? toDiagnosticSeverity(documentSettings.schemaValidation) : jsonLanguageTypes_1.DiagnosticSeverity.Warning; let schemaRequest = documentSettings?.schemaRequest ? toDiagnosticSeverity(documentSettings.schemaRequest) : jsonLanguageTypes_1.DiagnosticSeverity.Warning; if (schema) { const addSchemaProblem = (errorMessage, errorCode, relatedInformation) => { if (jsonDocument.root && schemaRequest) { const astRoot = jsonDocument.root; const property = astRoot.type === 'object' ? astRoot.properties[0] : undefined; if (property && property.keyNode.value === '$schema') { const node = property.valueNode || property; const range = jsonLanguageTypes_1.Range.create(textDocument.positionAt(node.offset), textDocument.positionAt(node.offset + node.length)); addProblem(jsonLanguageTypes_1.Diagnostic.create(range, errorMessage, schemaRequest, errorCode, 'json', relatedInformation)); } else { const range = jsonLanguageTypes_1.Range.create(textDocument.positionAt(astRoot.offset), textDocument.positionAt(astRoot.offset + 1)); addProblem(jsonLanguageTypes_1.Diagnostic.create(range, errorMessage, schemaRequest, errorCode, 'json', relatedInformation)); } } }; if (schema.errors.length) { const error = schema.errors[0]; addSchemaProblem(error.message, error.code, error.relatedInformation); } else if (schemaValidation) { for (const warning of schema.warnings) { addSchemaProblem(warning.message, warning.code, warning.relatedInformation); } const semanticErrors = jsonDocument.validate(textDocument, schema.schema, schemaValidation, documentSettings?.schemaDraft); if (semanticErrors) { semanticErrors.forEach(addProblem); } } if (schemaAllowsComments(schema.schema)) { commentSeverity = undefined; } if (schemaAllowsTrailingCommas(schema.schema)) { trailingCommaSeverity = undefined; } } for (const p of jsonDocument.syntaxErrors) { if (p.code === jsonLanguageTypes_1.ErrorCode.TrailingComma) { if (typeof trailingCommaSeverity !== 'number') { continue; } p.severity = trailingCommaSeverity; } addProblem(p); } if (typeof commentSeverity === 'number') { const message = l10n.t('Comments are not permitted in JSON.'); jsonDocument.comments.forEach(c => { addProblem(jsonLanguageTypes_1.Diagnostic.create(c, message, commentSeverity, jsonLanguageTypes_1.ErrorCode.CommentNotPermitted)); }); } return diagnostics; }; if (schema) { const uri = schema.id || ('schemaservice://untitled/' + idCounter++); const handle = this.jsonSchemaService.registerExternalSchema({ uri, schema }); return handle.getResolvedSchema().then(resolvedSchema => { return getDiagnostics(resolvedSchema); }); } return this.jsonSchemaService.getSchemaForResource(textDocument.uri, jsonDocument).then(schema => { return getDiagnostics(schema); }); } getLanguageStatus(textDocument, jsonDocument) { return { schemas: this.jsonSchemaService.getSchemaURIsForResource(textDocument.uri, jsonDocument) }; } } exports.JSONValidation = JSONValidation; let idCounter = 0; function schemaAllowsComments(schemaRef) { if (schemaRef && typeof schemaRef === 'object') { if ((0, objects_1.isBoolean)(schemaRef.allowComments)) { return schemaRef.allowComments; } if (schemaRef.allOf) { for (const schema of schemaRef.allOf) { const allow = schemaAllowsComments(schema); if ((0, objects_1.isBoolean)(allow)) { return allow; } } } } return undefined; } function schemaAllowsTrailingCommas(schemaRef) { if (schemaRef && typeof schemaRef === 'object') { if ((0, objects_1.isBoolean)(schemaRef.allowTrailingCommas)) { return schemaRef.allowTrailingCommas; } const deprSchemaRef = schemaRef; if ((0, objects_1.isBoolean)(deprSchemaRef['allowsTrailingCommas'])) { // deprecated return deprSchemaRef['allowsTrailingCommas']; } if (schemaRef.allOf) { for (const schema of schemaRef.allOf) { const allow = schemaAllowsTrailingCommas(schema); if ((0, objects_1.isBoolean)(allow)) { return allow; } } } } return undefined; } function toDiagnosticSeverity(severityLevel) { switch (severityLevel) { case 'error': return jsonLanguageTypes_1.DiagnosticSeverity.Error; case 'warning': return jsonLanguageTypes_1.DiagnosticSeverity.Warning; case 'ignore': return undefined; } return undefined; } });