1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- var __extends = (this && this.__extends) || (function () {
- var extendStatics = function (d, b) {
- extendStatics = Object.setPrototypeOf ||
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
- return extendStatics(d, b);
- };
- return function (d, b) {
- if (typeof b !== "function" && b !== null)
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
- extendStatics(d, b);
- function __() { this.constructor = d; }
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
- };
- })();
- (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", "jsonc-parser", "../utils/objects", "../utils/strings", "../jsonLanguageTypes", "vscode-nls"], factory);
- }
- })(function (require, exports) {
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.parse = exports.JSONDocument = exports.contains = exports.getNodePath = exports.getNodeValue = exports.newJSONDocument = exports.ValidationResult = exports.EnumMatch = exports.asSchema = exports.ObjectASTNodeImpl = exports.PropertyASTNodeImpl = exports.StringASTNodeImpl = exports.NumberASTNodeImpl = exports.ArrayASTNodeImpl = exports.BooleanASTNodeImpl = exports.NullASTNodeImpl = exports.ASTNodeImpl = void 0;
- var Json = require("jsonc-parser");
- var objects_1 = require("../utils/objects");
- var strings_1 = require("../utils/strings");
- var jsonLanguageTypes_1 = require("../jsonLanguageTypes");
- var nls = require("vscode-nls");
- var localize = nls.loadMessageBundle();
- var formats = {
- 'color-hex': { errorMessage: localize('colorHexFormatWarning', 'Invalid color format. Use #RGB, #RGBA, #RRGGBB or #RRGGBBAA.'), pattern: /^#([0-9A-Fa-f]{3,4}|([0-9A-Fa-f]{2}){3,4})$/ },
- 'date-time': { errorMessage: localize('dateTimeFormatWarning', 'String is not a RFC3339 date-time.'), pattern: /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)([01][0-9]|2[0-3]):([0-5][0-9]))$/i },
- 'date': { errorMessage: localize('dateFormatWarning', 'String is not a RFC3339 date.'), pattern: /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/i },
- 'time': { errorMessage: localize('timeFormatWarning', 'String is not a RFC3339 time.'), pattern: /^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)([01][0-9]|2[0-3]):([0-5][0-9]))$/i },
- 'email': { errorMessage: localize('emailFormatWarning', 'String is not an e-mail address.'), pattern: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ }
- };
- var ASTNodeImpl = /** @class */ (function () {
- function ASTNodeImpl(parent, offset, length) {
- if (length === void 0) { length = 0; }
- this.offset = offset;
- this.length = length;
- this.parent = parent;
- }
- Object.defineProperty(ASTNodeImpl.prototype, "children", {
- get: function () {
- return [];
- },
- enumerable: false,
- configurable: true
- });
- ASTNodeImpl.prototype.toString = function () {
- return 'type: ' + this.type + ' (' + this.offset + '/' + this.length + ')' + (this.parent ? ' parent: {' + this.parent.toString() + '}' : '');
- };
- return ASTNodeImpl;
- }());
- exports.ASTNodeImpl = ASTNodeImpl;
- var NullASTNodeImpl = /** @class */ (function (_super) {
- __extends(NullASTNodeImpl, _super);
- function NullASTNodeImpl(parent, offset) {
- var _this = _super.call(this, parent, offset) || this;
- _this.type = 'null';
- _this.value = null;
- return _this;
- }
- return NullASTNodeImpl;
- }(ASTNodeImpl));
- exports.NullASTNodeImpl = NullASTNodeImpl;
- var BooleanASTNodeImpl = /** @class */ (function (_super) {
- __extends(BooleanASTNodeImpl, _super);
- function BooleanASTNodeImpl(parent, boolValue, offset) {
- var _this = _super.call(this, parent, offset) || this;
- _this.type = 'boolean';
- _this.value = boolValue;
- return _this;
- }
- return BooleanASTNodeImpl;
- }(ASTNodeImpl));
- exports.BooleanASTNodeImpl = BooleanASTNodeImpl;
- var ArrayASTNodeImpl = /** @class */ (function (_super) {
- __extends(ArrayASTNodeImpl, _super);
- function ArrayASTNodeImpl(parent, offset) {
- var _this = _super.call(this, parent, offset) || this;
- _this.type = 'array';
- _this.items = [];
- return _this;
- }
- Object.defineProperty(ArrayASTNodeImpl.prototype, "children", {
- get: function () {
- return this.items;
- },
- enumerable: false,
- configurable: true
- });
- return ArrayASTNodeImpl;
- }(ASTNodeImpl));
- exports.ArrayASTNodeImpl = ArrayASTNodeImpl;
- var NumberASTNodeImpl = /** @class */ (function (_super) {
- __extends(NumberASTNodeImpl, _super);
- function NumberASTNodeImpl(parent, offset) {
- var _this = _super.call(this, parent, offset) || this;
- _this.type = 'number';
- _this.isInteger = true;
- _this.value = Number.NaN;
- return _this;
- }
- return NumberASTNodeImpl;
- }(ASTNodeImpl));
- exports.NumberASTNodeImpl = NumberASTNodeImpl;
- var StringASTNodeImpl = /** @class */ (function (_super) {
- __extends(StringASTNodeImpl, _super);
- function StringASTNodeImpl(parent, offset, length) {
- var _this = _super.call(this, parent, offset, length) || this;
- _this.type = 'string';
- _this.value = '';
- return _this;
- }
- return StringASTNodeImpl;
- }(ASTNodeImpl));
- exports.StringASTNodeImpl = StringASTNodeImpl;
- var PropertyASTNodeImpl = /** @class */ (function (_super) {
- __extends(PropertyASTNodeImpl, _super);
- function PropertyASTNodeImpl(parent, offset, keyNode) {
- var _this = _super.call(this, parent, offset) || this;
- _this.type = 'property';
- _this.colonOffset = -1;
- _this.keyNode = keyNode;
- return _this;
- }
- Object.defineProperty(PropertyASTNodeImpl.prototype, "children", {
- get: function () {
- return this.valueNode ? [this.keyNode, this.valueNode] : [this.keyNode];
- },
- enumerable: false,
- configurable: true
- });
- return PropertyASTNodeImpl;
- }(ASTNodeImpl));
- exports.PropertyASTNodeImpl = PropertyASTNodeImpl;
- var ObjectASTNodeImpl = /** @class */ (function (_super) {
- __extends(ObjectASTNodeImpl, _super);
- function ObjectASTNodeImpl(parent, offset) {
- var _this = _super.call(this, parent, offset) || this;
- _this.type = 'object';
- _this.properties = [];
- return _this;
- }
- Object.defineProperty(ObjectASTNodeImpl.prototype, "children", {
- get: function () {
- return this.properties;
- },
- enumerable: false,
- configurable: true
- });
- return ObjectASTNodeImpl;
- }(ASTNodeImpl));
- exports.ObjectASTNodeImpl = ObjectASTNodeImpl;
- function asSchema(schema) {
- if (objects_1.isBoolean(schema)) {
- return schema ? {} : { "not": {} };
- }
- return schema;
- }
- exports.asSchema = asSchema;
- var EnumMatch;
- (function (EnumMatch) {
- EnumMatch[EnumMatch["Key"] = 0] = "Key";
- EnumMatch[EnumMatch["Enum"] = 1] = "Enum";
- })(EnumMatch = exports.EnumMatch || (exports.EnumMatch = {}));
- var SchemaCollector = /** @class */ (function () {
- function SchemaCollector(focusOffset, exclude) {
- if (focusOffset === void 0) { focusOffset = -1; }
- this.focusOffset = focusOffset;
- this.exclude = exclude;
- this.schemas = [];
- }
- SchemaCollector.prototype.add = function (schema) {
- this.schemas.push(schema);
- };
- SchemaCollector.prototype.merge = function (other) {
- Array.prototype.push.apply(this.schemas, other.schemas);
- };
- SchemaCollector.prototype.include = function (node) {
- return (this.focusOffset === -1 || contains(node, this.focusOffset)) && (node !== this.exclude);
- };
- SchemaCollector.prototype.newSub = function () {
- return new SchemaCollector(-1, this.exclude);
- };
- return SchemaCollector;
- }());
- var NoOpSchemaCollector = /** @class */ (function () {
- function NoOpSchemaCollector() {
- }
- Object.defineProperty(NoOpSchemaCollector.prototype, "schemas", {
- get: function () { return []; },
- enumerable: false,
- configurable: true
- });
- NoOpSchemaCollector.prototype.add = function (schema) { };
- NoOpSchemaCollector.prototype.merge = function (other) { };
- NoOpSchemaCollector.prototype.include = function (node) { return true; };
- NoOpSchemaCollector.prototype.newSub = function () { return this; };
- NoOpSchemaCollector.instance = new NoOpSchemaCollector();
- return NoOpSchemaCollector;
- }());
- var ValidationResult = /** @class */ (function () {
- function ValidationResult() {
- this.problems = [];
- this.propertiesMatches = 0;
- this.propertiesValueMatches = 0;
- this.primaryValueMatches = 0;
- this.enumValueMatch = false;
- this.enumValues = undefined;
- }
- ValidationResult.prototype.hasProblems = function () {
- return !!this.problems.length;
- };
- ValidationResult.prototype.mergeAll = function (validationResults) {
- for (var _i = 0, validationResults_1 = validationResults; _i < validationResults_1.length; _i++) {
- var validationResult = validationResults_1[_i];
- this.merge(validationResult);
- }
- };
- ValidationResult.prototype.merge = function (validationResult) {
- this.problems = this.problems.concat(validationResult.problems);
- };
- ValidationResult.prototype.mergeEnumValues = function (validationResult) {
- if (!this.enumValueMatch && !validationResult.enumValueMatch && this.enumValues && validationResult.enumValues) {
- this.enumValues = this.enumValues.concat(validationResult.enumValues);
- for (var _i = 0, _a = this.problems; _i < _a.length; _i++) {
- var error = _a[_i];
- if (error.code === jsonLanguageTypes_1.ErrorCode.EnumValueMismatch) {
- error.message = localize('enumWarning', 'Value is not accepted. Valid values: {0}.', this.enumValues.map(function (v) { return JSON.stringify(v); }).join(', '));
- }
- }
- }
- };
- ValidationResult.prototype.mergePropertyMatch = function (propertyValidationResult) {
- this.merge(propertyValidationResult);
- this.propertiesMatches++;
- if (propertyValidationResult.enumValueMatch || !propertyValidationResult.hasProblems() && propertyValidationResult.propertiesMatches) {
- this.propertiesValueMatches++;
- }
- if (propertyValidationResult.enumValueMatch && propertyValidationResult.enumValues && propertyValidationResult.enumValues.length === 1) {
- this.primaryValueMatches++;
- }
- };
- ValidationResult.prototype.compare = function (other) {
- var hasProblems = this.hasProblems();
- if (hasProblems !== other.hasProblems()) {
- return hasProblems ? -1 : 1;
- }
- if (this.enumValueMatch !== other.enumValueMatch) {
- return other.enumValueMatch ? -1 : 1;
- }
- if (this.primaryValueMatches !== other.primaryValueMatches) {
- return this.primaryValueMatches - other.primaryValueMatches;
- }
- if (this.propertiesValueMatches !== other.propertiesValueMatches) {
- return this.propertiesValueMatches - other.propertiesValueMatches;
- }
- return this.propertiesMatches - other.propertiesMatches;
- };
- return ValidationResult;
- }());
- exports.ValidationResult = ValidationResult;
- function newJSONDocument(root, diagnostics) {
- if (diagnostics === void 0) { diagnostics = []; }
- return new JSONDocument(root, diagnostics, []);
- }
- exports.newJSONDocument = newJSONDocument;
- function getNodeValue(node) {
- return Json.getNodeValue(node);
- }
- exports.getNodeValue = getNodeValue;
- function getNodePath(node) {
- return Json.getNodePath(node);
- }
- exports.getNodePath = getNodePath;
- function contains(node, offset, includeRightBound) {
- if (includeRightBound === void 0) { includeRightBound = false; }
- return offset >= node.offset && offset < (node.offset + node.length) || includeRightBound && offset === (node.offset + node.length);
- }
- exports.contains = contains;
- var JSONDocument = /** @class */ (function () {
- function JSONDocument(root, syntaxErrors, comments) {
- if (syntaxErrors === void 0) { syntaxErrors = []; }
- if (comments === void 0) { comments = []; }
- this.root = root;
- this.syntaxErrors = syntaxErrors;
- this.comments = comments;
- }
- JSONDocument.prototype.getNodeFromOffset = function (offset, includeRightBound) {
- if (includeRightBound === void 0) { includeRightBound = false; }
- if (this.root) {
- return Json.findNodeAtOffset(this.root, offset, includeRightBound);
- }
- return undefined;
- };
- JSONDocument.prototype.visit = function (visitor) {
- if (this.root) {
- var doVisit_1 = function (node) {
- var ctn = visitor(node);
- var children = node.children;
- if (Array.isArray(children)) {
- for (var i = 0; i < children.length && ctn; i++) {
- ctn = doVisit_1(children[i]);
- }
- }
- return ctn;
- };
- doVisit_1(this.root);
- }
- };
- JSONDocument.prototype.validate = function (textDocument, schema, severity) {
- if (severity === void 0) { severity = jsonLanguageTypes_1.DiagnosticSeverity.Warning; }
- if (this.root && schema) {
- var validationResult = new ValidationResult();
- validate(this.root, schema, validationResult, NoOpSchemaCollector.instance);
- return validationResult.problems.map(function (p) {
- var _a;
- var range = jsonLanguageTypes_1.Range.create(textDocument.positionAt(p.location.offset), textDocument.positionAt(p.location.offset + p.location.length));
- return jsonLanguageTypes_1.Diagnostic.create(range, p.message, (_a = p.severity) !== null && _a !== void 0 ? _a : severity, p.code);
- });
- }
- return undefined;
- };
- JSONDocument.prototype.getMatchingSchemas = function (schema, focusOffset, exclude) {
- if (focusOffset === void 0) { focusOffset = -1; }
- var matchingSchemas = new SchemaCollector(focusOffset, exclude);
- if (this.root && schema) {
- validate(this.root, schema, new ValidationResult(), matchingSchemas);
- }
- return matchingSchemas.schemas;
- };
- return JSONDocument;
- }());
- exports.JSONDocument = JSONDocument;
- function validate(n, schema, validationResult, matchingSchemas) {
- if (!n || !matchingSchemas.include(n)) {
- return;
- }
- var node = n;
- switch (node.type) {
- case 'object':
- _validateObjectNode(node, schema, validationResult, matchingSchemas);
- break;
- case 'array':
- _validateArrayNode(node, schema, validationResult, matchingSchemas);
- break;
- case 'string':
- _validateStringNode(node, schema, validationResult, matchingSchemas);
- break;
- case 'number':
- _validateNumberNode(node, schema, validationResult, matchingSchemas);
- break;
- case 'property':
- return validate(node.valueNode, schema, validationResult, matchingSchemas);
- }
- _validateNode();
- matchingSchemas.add({ node: node, schema: schema });
- function _validateNode() {
- function matchesType(type) {
- return node.type === type || (type === 'integer' && node.type === 'number' && node.isInteger);
- }
- if (Array.isArray(schema.type)) {
- if (!schema.type.some(matchesType)) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: schema.errorMessage || localize('typeArrayMismatchWarning', 'Incorrect type. Expected one of {0}.', schema.type.join(', '))
- });
- }
- }
- else if (schema.type) {
- if (!matchesType(schema.type)) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: schema.errorMessage || localize('typeMismatchWarning', 'Incorrect type. Expected "{0}".', schema.type)
- });
- }
- }
- if (Array.isArray(schema.allOf)) {
- for (var _i = 0, _a = schema.allOf; _i < _a.length; _i++) {
- var subSchemaRef = _a[_i];
- validate(node, asSchema(subSchemaRef), validationResult, matchingSchemas);
- }
- }
- var notSchema = asSchema(schema.not);
- if (notSchema) {
- var subValidationResult = new ValidationResult();
- var subMatchingSchemas = matchingSchemas.newSub();
- validate(node, notSchema, subValidationResult, subMatchingSchemas);
- if (!subValidationResult.hasProblems()) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: localize('notSchemaWarning', "Matches a schema that is not allowed.")
- });
- }
- for (var _b = 0, _c = subMatchingSchemas.schemas; _b < _c.length; _b++) {
- var ms = _c[_b];
- ms.inverted = !ms.inverted;
- matchingSchemas.add(ms);
- }
- }
- var testAlternatives = function (alternatives, maxOneMatch) {
- var matches = [];
- // remember the best match that is used for error messages
- var bestMatch = undefined;
- for (var _i = 0, alternatives_1 = alternatives; _i < alternatives_1.length; _i++) {
- var subSchemaRef = alternatives_1[_i];
- var subSchema = asSchema(subSchemaRef);
- var subValidationResult = new ValidationResult();
- var subMatchingSchemas = matchingSchemas.newSub();
- validate(node, subSchema, subValidationResult, subMatchingSchemas);
- if (!subValidationResult.hasProblems()) {
- matches.push(subSchema);
- }
- if (!bestMatch) {
- bestMatch = { schema: subSchema, validationResult: subValidationResult, matchingSchemas: subMatchingSchemas };
- }
- else {
- if (!maxOneMatch && !subValidationResult.hasProblems() && !bestMatch.validationResult.hasProblems()) {
- // no errors, both are equally good matches
- bestMatch.matchingSchemas.merge(subMatchingSchemas);
- bestMatch.validationResult.propertiesMatches += subValidationResult.propertiesMatches;
- bestMatch.validationResult.propertiesValueMatches += subValidationResult.propertiesValueMatches;
- }
- else {
- var compareResult = subValidationResult.compare(bestMatch.validationResult);
- if (compareResult > 0) {
- // our node is the best matching so far
- bestMatch = { schema: subSchema, validationResult: subValidationResult, matchingSchemas: subMatchingSchemas };
- }
- else if (compareResult === 0) {
- // there's already a best matching but we are as good
- bestMatch.matchingSchemas.merge(subMatchingSchemas);
- bestMatch.validationResult.mergeEnumValues(subValidationResult);
- }
- }
- }
- }
- if (matches.length > 1 && maxOneMatch) {
- validationResult.problems.push({
- location: { offset: node.offset, length: 1 },
- message: localize('oneOfWarning', "Matches multiple schemas when only one must validate.")
- });
- }
- if (bestMatch) {
- validationResult.merge(bestMatch.validationResult);
- validationResult.propertiesMatches += bestMatch.validationResult.propertiesMatches;
- validationResult.propertiesValueMatches += bestMatch.validationResult.propertiesValueMatches;
- matchingSchemas.merge(bestMatch.matchingSchemas);
- }
- return matches.length;
- };
- if (Array.isArray(schema.anyOf)) {
- testAlternatives(schema.anyOf, false);
- }
- if (Array.isArray(schema.oneOf)) {
- testAlternatives(schema.oneOf, true);
- }
- var testBranch = function (schema) {
- var subValidationResult = new ValidationResult();
- var subMatchingSchemas = matchingSchemas.newSub();
- validate(node, asSchema(schema), subValidationResult, subMatchingSchemas);
- validationResult.merge(subValidationResult);
- validationResult.propertiesMatches += subValidationResult.propertiesMatches;
- validationResult.propertiesValueMatches += subValidationResult.propertiesValueMatches;
- matchingSchemas.merge(subMatchingSchemas);
- };
- var testCondition = function (ifSchema, thenSchema, elseSchema) {
- var subSchema = asSchema(ifSchema);
- var subValidationResult = new ValidationResult();
- var subMatchingSchemas = matchingSchemas.newSub();
- validate(node, subSchema, subValidationResult, subMatchingSchemas);
- matchingSchemas.merge(subMatchingSchemas);
- if (!subValidationResult.hasProblems()) {
- if (thenSchema) {
- testBranch(thenSchema);
- }
- }
- else if (elseSchema) {
- testBranch(elseSchema);
- }
- };
- var ifSchema = asSchema(schema.if);
- if (ifSchema) {
- testCondition(ifSchema, asSchema(schema.then), asSchema(schema.else));
- }
- if (Array.isArray(schema.enum)) {
- var val = getNodeValue(node);
- var enumValueMatch = false;
- for (var _d = 0, _e = schema.enum; _d < _e.length; _d++) {
- var e = _e[_d];
- if (objects_1.equals(val, e)) {
- enumValueMatch = true;
- break;
- }
- }
- validationResult.enumValues = schema.enum;
- validationResult.enumValueMatch = enumValueMatch;
- if (!enumValueMatch) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- code: jsonLanguageTypes_1.ErrorCode.EnumValueMismatch,
- message: schema.errorMessage || localize('enumWarning', 'Value is not accepted. Valid values: {0}.', schema.enum.map(function (v) { return JSON.stringify(v); }).join(', '))
- });
- }
- }
- if (objects_1.isDefined(schema.const)) {
- var val = getNodeValue(node);
- if (!objects_1.equals(val, schema.const)) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- code: jsonLanguageTypes_1.ErrorCode.EnumValueMismatch,
- message: schema.errorMessage || localize('constWarning', 'Value must be {0}.', JSON.stringify(schema.const))
- });
- validationResult.enumValueMatch = false;
- }
- else {
- validationResult.enumValueMatch = true;
- }
- validationResult.enumValues = [schema.const];
- }
- if (schema.deprecationMessage && node.parent) {
- validationResult.problems.push({
- location: { offset: node.parent.offset, length: node.parent.length },
- severity: jsonLanguageTypes_1.DiagnosticSeverity.Warning,
- message: schema.deprecationMessage,
- code: jsonLanguageTypes_1.ErrorCode.Deprecated
- });
- }
- }
- function _validateNumberNode(node, schema, validationResult, matchingSchemas) {
- var val = node.value;
- function normalizeFloats(float) {
- var _a;
- var parts = /^(-?\d+)(?:\.(\d+))?(?:e([-+]\d+))?$/.exec(float.toString());
- return parts && {
- value: Number(parts[1] + (parts[2] || '')),
- multiplier: (((_a = parts[2]) === null || _a === void 0 ? void 0 : _a.length) || 0) - (parseInt(parts[3]) || 0)
- };
- }
- ;
- if (objects_1.isNumber(schema.multipleOf)) {
- var remainder = -1;
- if (Number.isInteger(schema.multipleOf)) {
- remainder = val % schema.multipleOf;
- }
- else {
- var normMultipleOf = normalizeFloats(schema.multipleOf);
- var normValue = normalizeFloats(val);
- if (normMultipleOf && normValue) {
- var multiplier = Math.pow(10, Math.abs(normValue.multiplier - normMultipleOf.multiplier));
- if (normValue.multiplier < normMultipleOf.multiplier) {
- normValue.value *= multiplier;
- }
- else {
- normMultipleOf.value *= multiplier;
- }
- remainder = normValue.value % normMultipleOf.value;
- }
- }
- if (remainder !== 0) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: localize('multipleOfWarning', 'Value is not divisible by {0}.', schema.multipleOf)
- });
- }
- }
- function getExclusiveLimit(limit, exclusive) {
- if (objects_1.isNumber(exclusive)) {
- return exclusive;
- }
- if (objects_1.isBoolean(exclusive) && exclusive) {
- return limit;
- }
- return undefined;
- }
- function getLimit(limit, exclusive) {
- if (!objects_1.isBoolean(exclusive) || !exclusive) {
- return limit;
- }
- return undefined;
- }
- var exclusiveMinimum = getExclusiveLimit(schema.minimum, schema.exclusiveMinimum);
- if (objects_1.isNumber(exclusiveMinimum) && val <= exclusiveMinimum) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: localize('exclusiveMinimumWarning', 'Value is below the exclusive minimum of {0}.', exclusiveMinimum)
- });
- }
- var exclusiveMaximum = getExclusiveLimit(schema.maximum, schema.exclusiveMaximum);
- if (objects_1.isNumber(exclusiveMaximum) && val >= exclusiveMaximum) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: localize('exclusiveMaximumWarning', 'Value is above the exclusive maximum of {0}.', exclusiveMaximum)
- });
- }
- var minimum = getLimit(schema.minimum, schema.exclusiveMinimum);
- if (objects_1.isNumber(minimum) && val < minimum) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: localize('minimumWarning', 'Value is below the minimum of {0}.', minimum)
- });
- }
- var maximum = getLimit(schema.maximum, schema.exclusiveMaximum);
- if (objects_1.isNumber(maximum) && val > maximum) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: localize('maximumWarning', 'Value is above the maximum of {0}.', maximum)
- });
- }
- }
- function _validateStringNode(node, schema, validationResult, matchingSchemas) {
- if (objects_1.isNumber(schema.minLength) && node.value.length < schema.minLength) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: localize('minLengthWarning', 'String is shorter than the minimum length of {0}.', schema.minLength)
- });
- }
- if (objects_1.isNumber(schema.maxLength) && node.value.length > schema.maxLength) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: localize('maxLengthWarning', 'String is longer than the maximum length of {0}.', schema.maxLength)
- });
- }
- if (objects_1.isString(schema.pattern)) {
- var regex = strings_1.extendedRegExp(schema.pattern);
- if (!regex.test(node.value)) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: schema.patternErrorMessage || schema.errorMessage || localize('patternWarning', 'String does not match the pattern of "{0}".', schema.pattern)
- });
- }
- }
- if (schema.format) {
- switch (schema.format) {
- case 'uri':
- case 'uri-reference':
- {
- var errorMessage = void 0;
- if (!node.value) {
- errorMessage = localize('uriEmpty', 'URI expected.');
- }
- else {
- var match = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/.exec(node.value);
- if (!match) {
- errorMessage = localize('uriMissing', 'URI is expected.');
- }
- else if (!match[2] && schema.format === 'uri') {
- errorMessage = localize('uriSchemeMissing', 'URI with a scheme is expected.');
- }
- }
- if (errorMessage) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: schema.patternErrorMessage || schema.errorMessage || localize('uriFormatWarning', 'String is not a URI: {0}', errorMessage)
- });
- }
- }
- break;
- case 'color-hex':
- case 'date-time':
- case 'date':
- case 'time':
- case 'email':
- var format = formats[schema.format];
- if (!node.value || !format.pattern.exec(node.value)) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: schema.patternErrorMessage || schema.errorMessage || format.errorMessage
- });
- }
- default:
- }
- }
- }
- function _validateArrayNode(node, schema, validationResult, matchingSchemas) {
- if (Array.isArray(schema.items)) {
- var subSchemas = schema.items;
- for (var index = 0; index < subSchemas.length; index++) {
- var subSchemaRef = subSchemas[index];
- var subSchema = asSchema(subSchemaRef);
- var itemValidationResult = new ValidationResult();
- var item = node.items[index];
- if (item) {
- validate(item, subSchema, itemValidationResult, matchingSchemas);
- validationResult.mergePropertyMatch(itemValidationResult);
- }
- else if (node.items.length >= subSchemas.length) {
- validationResult.propertiesValueMatches++;
- }
- }
- if (node.items.length > subSchemas.length) {
- if (typeof schema.additionalItems === 'object') {
- for (var i = subSchemas.length; i < node.items.length; i++) {
- var itemValidationResult = new ValidationResult();
- validate(node.items[i], schema.additionalItems, itemValidationResult, matchingSchemas);
- validationResult.mergePropertyMatch(itemValidationResult);
- }
- }
- else if (schema.additionalItems === false) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: localize('additionalItemsWarning', 'Array has too many items according to schema. Expected {0} or fewer.', subSchemas.length)
- });
- }
- }
- }
- else {
- var itemSchema = asSchema(schema.items);
- if (itemSchema) {
- for (var _i = 0, _a = node.items; _i < _a.length; _i++) {
- var item = _a[_i];
- var itemValidationResult = new ValidationResult();
- validate(item, itemSchema, itemValidationResult, matchingSchemas);
- validationResult.mergePropertyMatch(itemValidationResult);
- }
- }
- }
- var containsSchema = asSchema(schema.contains);
- if (containsSchema) {
- var doesContain = node.items.some(function (item) {
- var itemValidationResult = new ValidationResult();
- validate(item, containsSchema, itemValidationResult, NoOpSchemaCollector.instance);
- return !itemValidationResult.hasProblems();
- });
- if (!doesContain) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: schema.errorMessage || localize('requiredItemMissingWarning', 'Array does not contain required item.')
- });
- }
- }
- if (objects_1.isNumber(schema.minItems) && node.items.length < schema.minItems) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: localize('minItemsWarning', 'Array has too few items. Expected {0} or more.', schema.minItems)
- });
- }
- if (objects_1.isNumber(schema.maxItems) && node.items.length > schema.maxItems) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: localize('maxItemsWarning', 'Array has too many items. Expected {0} or fewer.', schema.maxItems)
- });
- }
- if (schema.uniqueItems === true) {
- var values_1 = getNodeValue(node);
- var duplicates = values_1.some(function (value, index) {
- return index !== values_1.lastIndexOf(value);
- });
- if (duplicates) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: localize('uniqueItemsWarning', 'Array has duplicate items.')
- });
- }
- }
- }
- function _validateObjectNode(node, schema, validationResult, matchingSchemas) {
- var seenKeys = Object.create(null);
- var unprocessedProperties = [];
- for (var _i = 0, _a = node.properties; _i < _a.length; _i++) {
- var propertyNode = _a[_i];
- var key = propertyNode.keyNode.value;
- seenKeys[key] = propertyNode.valueNode;
- unprocessedProperties.push(key);
- }
- if (Array.isArray(schema.required)) {
- for (var _b = 0, _c = schema.required; _b < _c.length; _b++) {
- var propertyName = _c[_b];
- if (!seenKeys[propertyName]) {
- var keyNode = node.parent && node.parent.type === 'property' && node.parent.keyNode;
- var location = keyNode ? { offset: keyNode.offset, length: keyNode.length } : { offset: node.offset, length: 1 };
- validationResult.problems.push({
- location: location,
- message: localize('MissingRequiredPropWarning', 'Missing property "{0}".', propertyName)
- });
- }
- }
- }
- var propertyProcessed = function (prop) {
- var index = unprocessedProperties.indexOf(prop);
- while (index >= 0) {
- unprocessedProperties.splice(index, 1);
- index = unprocessedProperties.indexOf(prop);
- }
- };
- if (schema.properties) {
- for (var _d = 0, _e = Object.keys(schema.properties); _d < _e.length; _d++) {
- var propertyName = _e[_d];
- propertyProcessed(propertyName);
- var propertySchema = schema.properties[propertyName];
- var child = seenKeys[propertyName];
- if (child) {
- if (objects_1.isBoolean(propertySchema)) {
- if (!propertySchema) {
- var propertyNode = child.parent;
- validationResult.problems.push({
- location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },
- message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)
- });
- }
- else {
- validationResult.propertiesMatches++;
- validationResult.propertiesValueMatches++;
- }
- }
- else {
- var propertyValidationResult = new ValidationResult();
- validate(child, propertySchema, propertyValidationResult, matchingSchemas);
- validationResult.mergePropertyMatch(propertyValidationResult);
- }
- }
- }
- }
- if (schema.patternProperties) {
- for (var _f = 0, _g = Object.keys(schema.patternProperties); _f < _g.length; _f++) {
- var propertyPattern = _g[_f];
- var regex = strings_1.extendedRegExp(propertyPattern);
- for (var _h = 0, _j = unprocessedProperties.slice(0); _h < _j.length; _h++) {
- var propertyName = _j[_h];
- if (regex.test(propertyName)) {
- propertyProcessed(propertyName);
- var child = seenKeys[propertyName];
- if (child) {
- var propertySchema = schema.patternProperties[propertyPattern];
- if (objects_1.isBoolean(propertySchema)) {
- if (!propertySchema) {
- var propertyNode = child.parent;
- validationResult.problems.push({
- location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },
- message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)
- });
- }
- else {
- validationResult.propertiesMatches++;
- validationResult.propertiesValueMatches++;
- }
- }
- else {
- var propertyValidationResult = new ValidationResult();
- validate(child, propertySchema, propertyValidationResult, matchingSchemas);
- validationResult.mergePropertyMatch(propertyValidationResult);
- }
- }
- }
- }
- }
- }
- if (typeof schema.additionalProperties === 'object') {
- for (var _k = 0, unprocessedProperties_1 = unprocessedProperties; _k < unprocessedProperties_1.length; _k++) {
- var propertyName = unprocessedProperties_1[_k];
- var child = seenKeys[propertyName];
- if (child) {
- var propertyValidationResult = new ValidationResult();
- validate(child, schema.additionalProperties, propertyValidationResult, matchingSchemas);
- validationResult.mergePropertyMatch(propertyValidationResult);
- }
- }
- }
- else if (schema.additionalProperties === false) {
- if (unprocessedProperties.length > 0) {
- for (var _l = 0, unprocessedProperties_2 = unprocessedProperties; _l < unprocessedProperties_2.length; _l++) {
- var propertyName = unprocessedProperties_2[_l];
- var child = seenKeys[propertyName];
- if (child) {
- var propertyNode = child.parent;
- validationResult.problems.push({
- location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },
- message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)
- });
- }
- }
- }
- }
- if (objects_1.isNumber(schema.maxProperties)) {
- if (node.properties.length > schema.maxProperties) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: localize('MaxPropWarning', 'Object has more properties than limit of {0}.', schema.maxProperties)
- });
- }
- }
- if (objects_1.isNumber(schema.minProperties)) {
- if (node.properties.length < schema.minProperties) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: localize('MinPropWarning', 'Object has fewer properties than the required number of {0}', schema.minProperties)
- });
- }
- }
- if (schema.dependencies) {
- for (var _m = 0, _o = Object.keys(schema.dependencies); _m < _o.length; _m++) {
- var key = _o[_m];
- var prop = seenKeys[key];
- if (prop) {
- var propertyDep = schema.dependencies[key];
- if (Array.isArray(propertyDep)) {
- for (var _p = 0, propertyDep_1 = propertyDep; _p < propertyDep_1.length; _p++) {
- var requiredProp = propertyDep_1[_p];
- if (!seenKeys[requiredProp]) {
- validationResult.problems.push({
- location: { offset: node.offset, length: node.length },
- message: localize('RequiredDependentPropWarning', 'Object is missing property {0} required by property {1}.', requiredProp, key)
- });
- }
- else {
- validationResult.propertiesValueMatches++;
- }
- }
- }
- else {
- var propertySchema = asSchema(propertyDep);
- if (propertySchema) {
- var propertyValidationResult = new ValidationResult();
- validate(node, propertySchema, propertyValidationResult, matchingSchemas);
- validationResult.mergePropertyMatch(propertyValidationResult);
- }
- }
- }
- }
- }
- var propertyNames = asSchema(schema.propertyNames);
- if (propertyNames) {
- for (var _q = 0, _r = node.properties; _q < _r.length; _q++) {
- var f = _r[_q];
- var key = f.keyNode;
- if (key) {
- validate(key, propertyNames, validationResult, NoOpSchemaCollector.instance);
- }
- }
- }
- }
- }
- function parse(textDocument, config) {
- var problems = [];
- var lastProblemOffset = -1;
- var text = textDocument.getText();
- var scanner = Json.createScanner(text, false);
- var commentRanges = config && config.collectComments ? [] : undefined;
- function _scanNext() {
- while (true) {
- var token_1 = scanner.scan();
- _checkScanError();
- switch (token_1) {
- case 12 /* LineCommentTrivia */:
- case 13 /* BlockCommentTrivia */:
- if (Array.isArray(commentRanges)) {
- commentRanges.push(jsonLanguageTypes_1.Range.create(textDocument.positionAt(scanner.getTokenOffset()), textDocument.positionAt(scanner.getTokenOffset() + scanner.getTokenLength())));
- }
- break;
- case 15 /* Trivia */:
- case 14 /* LineBreakTrivia */:
- break;
- default:
- return token_1;
- }
- }
- }
- function _accept(token) {
- if (scanner.getToken() === token) {
- _scanNext();
- return true;
- }
- return false;
- }
- function _errorAtRange(message, code, startOffset, endOffset, severity) {
- if (severity === void 0) { severity = jsonLanguageTypes_1.DiagnosticSeverity.Error; }
- if (problems.length === 0 || startOffset !== lastProblemOffset) {
- var range = jsonLanguageTypes_1.Range.create(textDocument.positionAt(startOffset), textDocument.positionAt(endOffset));
- problems.push(jsonLanguageTypes_1.Diagnostic.create(range, message, severity, code, textDocument.languageId));
- lastProblemOffset = startOffset;
- }
- }
- function _error(message, code, node, skipUntilAfter, skipUntil) {
- if (node === void 0) { node = undefined; }
- if (skipUntilAfter === void 0) { skipUntilAfter = []; }
- if (skipUntil === void 0) { skipUntil = []; }
- var start = scanner.getTokenOffset();
- var end = scanner.getTokenOffset() + scanner.getTokenLength();
- if (start === end && start > 0) {
- start--;
- while (start > 0 && /\s/.test(text.charAt(start))) {
- start--;
- }
- end = start + 1;
- }
- _errorAtRange(message, code, start, end);
- if (node) {
- _finalize(node, false);
- }
- if (skipUntilAfter.length + skipUntil.length > 0) {
- var token_2 = scanner.getToken();
- while (token_2 !== 17 /* EOF */) {
- if (skipUntilAfter.indexOf(token_2) !== -1) {
- _scanNext();
- break;
- }
- else if (skipUntil.indexOf(token_2) !== -1) {
- break;
- }
- token_2 = _scanNext();
- }
- }
- return node;
- }
- function _checkScanError() {
- switch (scanner.getTokenError()) {
- case 4 /* InvalidUnicode */:
- _error(localize('InvalidUnicode', 'Invalid unicode sequence in string.'), jsonLanguageTypes_1.ErrorCode.InvalidUnicode);
- return true;
- case 5 /* InvalidEscapeCharacter */:
- _error(localize('InvalidEscapeCharacter', 'Invalid escape character in string.'), jsonLanguageTypes_1.ErrorCode.InvalidEscapeCharacter);
- return true;
- case 3 /* UnexpectedEndOfNumber */:
- _error(localize('UnexpectedEndOfNumber', 'Unexpected end of number.'), jsonLanguageTypes_1.ErrorCode.UnexpectedEndOfNumber);
- return true;
- case 1 /* UnexpectedEndOfComment */:
- _error(localize('UnexpectedEndOfComment', 'Unexpected end of comment.'), jsonLanguageTypes_1.ErrorCode.UnexpectedEndOfComment);
- return true;
- case 2 /* UnexpectedEndOfString */:
- _error(localize('UnexpectedEndOfString', 'Unexpected end of string.'), jsonLanguageTypes_1.ErrorCode.UnexpectedEndOfString);
- return true;
- case 6 /* InvalidCharacter */:
- _error(localize('InvalidCharacter', 'Invalid characters in string. Control characters must be escaped.'), jsonLanguageTypes_1.ErrorCode.InvalidCharacter);
- return true;
- }
- return false;
- }
- function _finalize(node, scanNext) {
- node.length = scanner.getTokenOffset() + scanner.getTokenLength() - node.offset;
- if (scanNext) {
- _scanNext();
- }
- return node;
- }
- function _parseArray(parent) {
- if (scanner.getToken() !== 3 /* OpenBracketToken */) {
- return undefined;
- }
- var node = new ArrayASTNodeImpl(parent, scanner.getTokenOffset());
- _scanNext(); // consume OpenBracketToken
- var count = 0;
- var needsComma = false;
- while (scanner.getToken() !== 4 /* CloseBracketToken */ && scanner.getToken() !== 17 /* EOF */) {
- if (scanner.getToken() === 5 /* CommaToken */) {
- if (!needsComma) {
- _error(localize('ValueExpected', 'Value expected'), jsonLanguageTypes_1.ErrorCode.ValueExpected);
- }
- var commaOffset = scanner.getTokenOffset();
- _scanNext(); // consume comma
- if (scanner.getToken() === 4 /* CloseBracketToken */) {
- if (needsComma) {
- _errorAtRange(localize('TrailingComma', 'Trailing comma'), jsonLanguageTypes_1.ErrorCode.TrailingComma, commaOffset, commaOffset + 1);
- }
- continue;
- }
- }
- else if (needsComma) {
- _error(localize('ExpectedComma', 'Expected comma'), jsonLanguageTypes_1.ErrorCode.CommaExpected);
- }
- var item = _parseValue(node);
- if (!item) {
- _error(localize('PropertyExpected', 'Value expected'), jsonLanguageTypes_1.ErrorCode.ValueExpected, undefined, [], [4 /* CloseBracketToken */, 5 /* CommaToken */]);
- }
- else {
- node.items.push(item);
- }
- needsComma = true;
- }
- if (scanner.getToken() !== 4 /* CloseBracketToken */) {
- return _error(localize('ExpectedCloseBracket', 'Expected comma or closing bracket'), jsonLanguageTypes_1.ErrorCode.CommaOrCloseBacketExpected, node);
- }
- return _finalize(node, true);
- }
- var keyPlaceholder = new StringASTNodeImpl(undefined, 0, 0);
- function _parseProperty(parent, keysSeen) {
- var node = new PropertyASTNodeImpl(parent, scanner.getTokenOffset(), keyPlaceholder);
- var key = _parseString(node);
- if (!key) {
- if (scanner.getToken() === 16 /* Unknown */) {
- // give a more helpful error message
- _error(localize('DoubleQuotesExpected', 'Property keys must be doublequoted'), jsonLanguageTypes_1.ErrorCode.Undefined);
- var keyNode = new StringASTNodeImpl(node, scanner.getTokenOffset(), scanner.getTokenLength());
- keyNode.value = scanner.getTokenValue();
- key = keyNode;
- _scanNext(); // consume Unknown
- }
- else {
- return undefined;
- }
- }
- node.keyNode = key;
- var seen = keysSeen[key.value];
- if (seen) {
- _errorAtRange(localize('DuplicateKeyWarning', "Duplicate object key"), jsonLanguageTypes_1.ErrorCode.DuplicateKey, node.keyNode.offset, node.keyNode.offset + node.keyNode.length, jsonLanguageTypes_1.DiagnosticSeverity.Warning);
- if (typeof seen === 'object') {
- _errorAtRange(localize('DuplicateKeyWarning', "Duplicate object key"), jsonLanguageTypes_1.ErrorCode.DuplicateKey, seen.keyNode.offset, seen.keyNode.offset + seen.keyNode.length, jsonLanguageTypes_1.DiagnosticSeverity.Warning);
- }
- keysSeen[key.value] = true; // if the same key is duplicate again, avoid duplicate error reporting
- }
- else {
- keysSeen[key.value] = node;
- }
- if (scanner.getToken() === 6 /* ColonToken */) {
- node.colonOffset = scanner.getTokenOffset();
- _scanNext(); // consume ColonToken
- }
- else {
- _error(localize('ColonExpected', 'Colon expected'), jsonLanguageTypes_1.ErrorCode.ColonExpected);
- if (scanner.getToken() === 10 /* StringLiteral */ && textDocument.positionAt(key.offset + key.length).line < textDocument.positionAt(scanner.getTokenOffset()).line) {
- node.length = key.length;
- return node;
- }
- }
- var value = _parseValue(node);
- if (!value) {
- return _error(localize('ValueExpected', 'Value expected'), jsonLanguageTypes_1.ErrorCode.ValueExpected, node, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);
- }
- node.valueNode = value;
- node.length = value.offset + value.length - node.offset;
- return node;
- }
- function _parseObject(parent) {
- if (scanner.getToken() !== 1 /* OpenBraceToken */) {
- return undefined;
- }
- var node = new ObjectASTNodeImpl(parent, scanner.getTokenOffset());
- var keysSeen = Object.create(null);
- _scanNext(); // consume OpenBraceToken
- var needsComma = false;
- while (scanner.getToken() !== 2 /* CloseBraceToken */ && scanner.getToken() !== 17 /* EOF */) {
- if (scanner.getToken() === 5 /* CommaToken */) {
- if (!needsComma) {
- _error(localize('PropertyExpected', 'Property expected'), jsonLanguageTypes_1.ErrorCode.PropertyExpected);
- }
- var commaOffset = scanner.getTokenOffset();
- _scanNext(); // consume comma
- if (scanner.getToken() === 2 /* CloseBraceToken */) {
- if (needsComma) {
- _errorAtRange(localize('TrailingComma', 'Trailing comma'), jsonLanguageTypes_1.ErrorCode.TrailingComma, commaOffset, commaOffset + 1);
- }
- continue;
- }
- }
- else if (needsComma) {
- _error(localize('ExpectedComma', 'Expected comma'), jsonLanguageTypes_1.ErrorCode.CommaExpected);
- }
- var property = _parseProperty(node, keysSeen);
- if (!property) {
- _error(localize('PropertyExpected', 'Property expected'), jsonLanguageTypes_1.ErrorCode.PropertyExpected, undefined, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);
- }
- else {
- node.properties.push(property);
- }
- needsComma = true;
- }
- if (scanner.getToken() !== 2 /* CloseBraceToken */) {
- return _error(localize('ExpectedCloseBrace', 'Expected comma or closing brace'), jsonLanguageTypes_1.ErrorCode.CommaOrCloseBraceExpected, node);
- }
- return _finalize(node, true);
- }
- function _parseString(parent) {
- if (scanner.getToken() !== 10 /* StringLiteral */) {
- return undefined;
- }
- var node = new StringASTNodeImpl(parent, scanner.getTokenOffset());
- node.value = scanner.getTokenValue();
- return _finalize(node, true);
- }
- function _parseNumber(parent) {
- if (scanner.getToken() !== 11 /* NumericLiteral */) {
- return undefined;
- }
- var node = new NumberASTNodeImpl(parent, scanner.getTokenOffset());
- if (scanner.getTokenError() === 0 /* None */) {
- var tokenValue = scanner.getTokenValue();
- try {
- var numberValue = JSON.parse(tokenValue);
- if (!objects_1.isNumber(numberValue)) {
- return _error(localize('InvalidNumberFormat', 'Invalid number format.'), jsonLanguageTypes_1.ErrorCode.Undefined, node);
- }
- node.value = numberValue;
- }
- catch (e) {
- return _error(localize('InvalidNumberFormat', 'Invalid number format.'), jsonLanguageTypes_1.ErrorCode.Undefined, node);
- }
- node.isInteger = tokenValue.indexOf('.') === -1;
- }
- return _finalize(node, true);
- }
- function _parseLiteral(parent) {
- var node;
- switch (scanner.getToken()) {
- case 7 /* NullKeyword */:
- return _finalize(new NullASTNodeImpl(parent, scanner.getTokenOffset()), true);
- case 8 /* TrueKeyword */:
- return _finalize(new BooleanASTNodeImpl(parent, true, scanner.getTokenOffset()), true);
- case 9 /* FalseKeyword */:
- return _finalize(new BooleanASTNodeImpl(parent, false, scanner.getTokenOffset()), true);
- default:
- return undefined;
- }
- }
- function _parseValue(parent) {
- return _parseArray(parent) || _parseObject(parent) || _parseString(parent) || _parseNumber(parent) || _parseLiteral(parent);
- }
- var _root = undefined;
- var token = _scanNext();
- if (token !== 17 /* EOF */) {
- _root = _parseValue(_root);
- if (!_root) {
- _error(localize('Invalid symbol', 'Expected a JSON object, array or literal.'), jsonLanguageTypes_1.ErrorCode.Undefined);
- }
- else if (scanner.getToken() !== 17 /* EOF */) {
- _error(localize('End of file expected', 'End of file expected.'), jsonLanguageTypes_1.ErrorCode.Undefined);
- }
- }
- return new JSONDocument(_root, problems, commentRanges);
- }
- exports.parse = parse;
- });
|